- index.js
Mongoose#_applyPlugins(
schema
)Applies global plugins to
schema
.show codeParameters:
schema
<Schema>
Mongoose.prototype._applyPlugins = function(schema) { 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].schema); } }; Mongoose.prototype._applyPlugins.$hasSideEffects = true;
MongooseThenable#catch(
onFulfilled
,onRejected
)Ability to use mongoose object as a pseudo-promise so
.connect().then()
and.disconnect().then()
are viable.show codeReturns:
- <Promise>
MongooseThenable.prototype.catch = function(onRejected) { return this.then(null, onRejected); };
checkReplicaSetInUri(
uri
)Checks if ?replicaSet query parameter is specified in URI
Parameters:
uri
<String>
Returns:
- <boolean>
show codeExample:
checkReplicaSetInUri('localhost:27000?replicaSet=rs0'); // true
var checkReplicaSetInUri = function(uri) { if (!uri) { return false; } 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; } } return isReplicaSet; };
Mongoose#connect(
uri(s)
,[options]
,[options.useMongoClient]
,[callback]
)Opens the default mongoose connection.
Parameters:
Returns:
- <MongooseThenable> pseudo-promise wrapper around this
show codeIf arguments are passed, they are proxied to either
Connection#open or
Connection#openSet appropriately.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. })
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 new MongooseThenable(this, conn.open.apply(conn, arguments)); }; Mongoose.prototype.connect.$hasSideEffects = true;
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.
show codeEach
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
, andreplset
options to the driver. Note that thesafe
option specified in your schema will overwrite thesafe
db option specified here unless you set your schemassafe
option toundefined
. 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,anotherhost:port,yetanother:port/database'); // and options var opts = { replset: { strategy: 'ping', rs_name: 'testSet' }} 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) // 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.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, callback); } 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); } } return conn; }; Mongoose.prototype.createConnection.$hasSideEffects = true;
Mongoose#disconnect(
[fn]
)Disconnects all connections.
Parameters:
[fn]
<Function> called after all connection close.
show codeReturns:
- <MongooseThenable> pseudo-promise wrapper around this
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#get(
key
)Gets mongoose options
Parameters:
key
<String>
Example:
mongoose.get('test') // returns the 'test' value
Mongoose#getPromiseConstructor()
Returns the current ES6-style promise constructor. In Mongoose 4.x,
equivalent tomongoose.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:
show codeModels defined on the
mongoose
instance are available to all connection created by the samemongoose
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 modelname
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.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'); } } if (typeof schema === 'string') { collection = schema; schema = false; } 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 (typeof collection === 'boolean') { 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. 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); } } if (schema) { this._applyPlugins(schema); } 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] && options.cache !== false) { if (schema && schema.instanceOfSchema && 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); } } // Apply relevant "global" options to the schema if (!('pluralization' in schema.options)) schema.options.pluralization = this.options.pluralization; if (!collection) { collection = schema.get('collection') || format(name, schema.options); } var connection = options.connection || this.connection; model = this.Model.compile(model || name, schema, collection, connection, this); if (!skipInit) { model.init(); } if (options.cache === false) { return model; } this.models[name] = model; return this.models[name]; }; Mongoose.prototype.model.$hasSideEffects = true;
Mongoose#modelNames()
Returns an array of model names created on this instance of Mongoose.
Returns:
- <Array>
show codeNote:
Does not include names of models created using
connection.model()
.Mongoose.prototype.modelNames = function() { var names = Object.keys(this.models); return names; }; Mongoose.prototype.modelNames.$hasSideEffects = true;
Mongoose()
Mongoose constructor.
show codeThe exports object of the
mongoose
module is an instance of this class.
Most apps will only use this one instance.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.
Example:
var mongoose = require('mongoose'); var mongoose2 = new mongoose.Mongoose();
MongooseThenable()
Wraps the given Mongoose instance into a thenable (pseudo-promise). This
show code
is soconnect()
anddisconnect()
can return a thenable while maintaining
backwards compatibility.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; } MongooseThenable.prototype = new Mongoose;
Mongoose#plugin(
fn
,[opts]
)Declares a global plugin executed on all Schemas.
Returns:
- <Mongoose> this
See:
show codeEquivalent to calling
.plugin(fn)
on each Schema you create.Mongoose.prototype.plugin = function(fn, opts) { this.plugins.push([fn, opts]); return this; }; Mongoose.prototype.plugin.$hasSideEffects = true;
Mongoose#Schema()
The Mongoose Schema constructor
Example:
var mongoose = require('mongoose'); var Schema = mongoose.Schema; var CatSchema = new Schema(..);
Mongoose#set(
key
,value
)Sets mongoose options
show codeExample:
mongoose.set('test', value) // sets the 'test' option to `value` 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
Mongoose.prototype.set = function(key, value) { if (arguments.length === 1) { return this.options[key]; } this.options[key] = value; return this; }; Mongoose.prototype.set.$hasSideEffects = true;
MongooseThenable#then(
onFulfilled
,onRejected
)Ability to use mongoose object as a pseudo-promise so
.connect().then()
and.disconnect().then()
are viable.show codeReturns:
- <Promise>
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#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.
show codeMongoose.prototype.__defineGetter__('connection', function() { return this.connections[0]; }); Mongoose.prototype.__defineSetter__('connection', function(v) { if (v instanceof Connection) { this.connections[0] = v; this.models = v.models; } });
Returns:
Mongoose#mongo
The node-mongodb-native driver Mongoose uses.
show codeMongoose.prototype.mongo = require('mongodb');
Mongoose#mquery
The mquery query builder Mongoose uses.
show codeMongoose.prototype.mquery = require('mquery');
Mongoose#SchemaTypes
The various Mongoose SchemaTypes.
Note:
Alias of mongoose.Schema.Types for backwards compatibility.
show codeMongoose.prototype.SchemaTypes = Schema.Types;
Mongoose#Types
The various Mongoose Types.
Example:
var mongoose = require('mongoose'); var array = mongoose.Types.Array;
Types:
Using this exposed access to the
ObjectId
type, we can construct ids on demand.
show codevar ObjectId = mongoose.Types.ObjectId; var id1 = new ObjectId;
Mongoose.prototype.Types = Types;
- virtualtype.js
VirtualType#applyGetters(
value
,scope
)Applies getters to
value
using optionalscope
.show codeReturns:
- <T> the value after applying all getters
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 optionalscope
.show codeReturns:
- <T> the value after applying all setters
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:
fn
<Function>
Returns:
- <VirtualType> this
show codeExample:
var virtual = schema.virtual('fullname'); virtual.get(function () { return this.name.first + ' ' + this.name.last; });
VirtualType.prototype.get = function(fn) { this.getters.push(fn); return this; };
VirtualType#set(
fn
)Defines a setter.
Parameters:
fn
<Function>
Returns:
- <VirtualType> this
show codeExample:
var virtual = schema.virtual('fullname'); virtual.set(function (v) { var parts = v.split(' '); this.name.first = parts[0]; this.name.last = parts[1]; });
VirtualType.prototype.set = function(fn) { this.setters.push(fn); return this; };
VirtualType()
VirtualType constructor
show codeThis is what mongoose uses to define virtual attributes via
Schema.prototype.virtual
.Example:
var fullname = schema.virtual('fullname'); fullname instanceof mongoose.VirtualType // true
function VirtualType(options, name) { this.path = name; this.getters = []; this.setters = []; this.options = options || {}; }
- browserDocument.js
Document(
obj
,[fields]
,[skipId]
)Document constructor.
Parameters:
Inherits:
show codeEvents:
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
function Document(obj, schema, fields, skipId, skipInit) { if (!(this instanceof Document)) { return new Document(obj, schema, fields, skipId, skipInit); } if (utils.isObject(schema) && !schema.instanceOfSchema) { schema = new Schema(schema); } // When creating EmbeddedDocument, it already has the schema and he doesn't need the _id schema = this.schema || schema; // Generate ObjectId if it is missing, but it requires a scheme if (!this.schema && schema.options._id) { obj = obj || {}; if (obj._id === undefined) { obj._id = new ObjectId(); } } if (!schema) { throw new MongooseError.MissingSchemaError(); } this.$__setSchema(schema); this.$__ = new InternalCache; this.$__.emitter = new EventEmitter(); this.isNew = true; this.errors = undefined; if (typeof fields === 'boolean') { this.$__.strictMode = fields; fields = undefined; } else { this.$__.strictMode = this.schema.options && this.schema.options.strict; this.$__.selected = fields; } var required = this.schema.requiredPaths(); 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 (!skipInit && obj) { this.init(obj); } this.$__registerHooksFromSchema(); // 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]; } }
- types/documentarray.js
MongooseDocumentArray(
values
,path
,doc
)DocumentArray constructor
Returns:
show codeInherits:
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.id(
id
)Searches array items for the first document with a matching _id.
Returns:
- <EmbeddedDocument, null> the subdocument or null if not found.
Example:
var embeddedDoc = m.array.id(some_id);
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:
- <Array>
NOTE:
Each sub-document is converted to a plain object by calling its
#toObject
method.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.notify(
event
)Creates a fn that notifies all child docs of
event
.Parameters:
event
<String>
Returns:
- <Function>
- types/array.js
MongooseArray#$__getAtomics()
Depopulates stored atomic operation values as necessary for direct insertion to MongoDB.
Returns:
- <Array>
If no atomics exist, we return all array values after conversion.
MongooseArray#$shift()
Atomically shifts the array at most one time per document
save()
.See:
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.
Inherits:
show codeNOTE:
Values always have to be passed to the constructor to initialize, otherwise
MongooseArray#push
will mark the array as modified.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._markModified(
embeddedDoc
,embeddedPath
)Marks this array as modified.
Parameters:
embeddedDoc
<EmbeddedDocument> the embedded doc that invoked this method on the ArrayembeddedPath
<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> operationval
<T>
MongooseArray.$pop()
Pops the array atomically at most one time per document
save()
.See:
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:
- <Number>
MongooseArray.indexOf(
obj
)Return the index of
obj
or-1
if not found.Parameters:
obj
<Object> the item to look for
Returns:
- <Number>
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
theDocument.equals()
function.Parameters:
[args...]
<T>
See:
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:
[args...]
<Object>
MongooseArray.set()
Sets the casted
val
at indexi
and marks the array modified.Returns:
- <Array> this
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:
options
<Object>
Returns:
- <Array>
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. - types/decimal128.js
- types/objectid.js
- types/subdocument.js
Subdocument#ownerDocument()
Returns the top level document of this sub-document.
show codeReturns:
- <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 = parent.$parent || parent.__parent; } this.$__.ownerDocument = parent; return this.$__.ownerDocument; };
Subdocument#parent()
Returns this sub-documents parent document.
show codeSubdocument.prototype.parent = function() { return this.$parent; };
Subdocument#remove(
[options]
,[callback]
)Null-out this subdoc
show codeParameters:
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:
[fn]
<Function>
Returns:
- <Promise> resolved Promise
show codeNOTE:
This is a no-op. Does not actually save the doc to the db.
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 && this.$basePath) { 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 && this.$basePath) { if (this.$parent.isDirectModified(this.$basePath)) { return; } this.$parent.markModified([this.$basePath, path].join('.'), this); } }; Subdocument.prototype.$markValid = function(path) { Document.prototype.$markValid.call(this, path); if (this.$parent && this.$basePath) { 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.$basePath) { this.$parent.invalidate([this.$basePath, path].join('.'), err, val); } else if (err.kind === 'cast' || err.name === 'CastError') { throw err; } };
Subdocument()
Subdocument constructor.
show codeInherits:
function Subdocument(value, fields, parent, skipId, options) { this.$isSingleNested = true; Document.call(this, value, fields, skipId, options); } Subdocument.prototype = Object.create(Document.prototype); Subdocument.prototype.toBSON = function() { return this.toObject({ transform: false, virtuals: false, _skipDepopulateTopLevel: true, depopulate: true, flattenDecimals: false }); };
- 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:
[path]
<String>
Returns:
- <String>
EmbeddedDocument(
obj
,parentArr
,skipId
)EmbeddedDocument constructor.
Parameters:
obj
<Object> js object returned from the dbparentArr
<MongooseDocumentArray> the parent array of this documentskipId
<Boolean>
show codeInherits:
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 codeEmbeddedDocument.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:
show codeReturns:
- <Boolean>
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.
show codeReturns:
- <Document>
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 codeEmbeddedDocument.prototype.parent = function() { return this.__parent; };
EmbeddedDocument#parentArray()
Returns this sub-documents parent array.
show codeEmbeddedDocument.prototype.parentArray = function() { return this.__parentArray; };
EmbeddedDocument#remove(
[options]
,[fn]
)Removes the subdocument from its parent array.
show codeEmbeddedDocument.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:
[fn]
<Function>
Returns:
- <Promise> resolved Promise
show codeNOTE:
This is a no-op. Does not actually save the doc to the db.
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 codeEmbeddedDocument.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 codeEmbeddedDocument.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');
- types/buffer.js
MongooseBuffer(
value
,encode
,offset
)Mongoose Buffer constructor.
Inherits:
show codeValues always have to be passed to the constructor to initialize.
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: [], enumerable: false }, _path: { value: path, enumerable: false }, _parent: { value: doc, enumerable: false } }); if (doc && typeof path === 'string') { Object.defineProperty(buf, '_schema', { value: doc.schema.path(path) }); } buf._subtype = 0; return buf; }
MongooseBuffer.copy(
target
)Copies the buffer.
Parameters:
target
<Buffer>
Returns:
- <Number> The number of bytes copied.
Note:
Buffer#copy
does not marktarget
as modified so you must copy from aMongooseBuffer
for it to work as expected. This is a work around sincecopy
modifies the target, not this.MongooseBuffer.equals(
other
)Determines if this buffer is equals to
other
bufferParameters:
other
<Buffer>
Returns:
- <Boolean>
MongooseBuffer.subtype(
subtype
)Sets the subtype option and marks the buffer modified.
Parameters:
subtype
<Hex>
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_DEFINEDdoc.buffer.subtype(bson.BSON_BINARY_SUBTYPE_UUID);
MongooseBuffer.toBSON()
Converts this buffer for storage in MongoDB, including subtype
Returns:
- <Binary>
MongooseBuffer.toObject(
[subtype]
)Converts this buffer to its Binary type representation.
Parameters:
[subtype]
<Hex>
Returns:
- <Binary>
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_DEFINEDdoc.buffer.toObject(bson.BSON_BINARY_SUBTYPE_USER_DEFINED);
MongooseBuffer#_subtype
Default subtype for the Binary representing this Buffer
show code_subtype: undefined,
- document_provider.js
module.exports()
Returns the Document constructor for the current context
show codemodule.exports = function() { if (isBrowser) { return BrowserDocument; } return Document; };
- cast.js
module.exports(
schema
,obj
,options
,context
)Handles internal casting for query filters.
show codemodule.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 && !schema.nested[path]) { 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 (Array.isArray(val) && ['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:
- document.js
Document#$__fullPath(
[path]
)Returns the full path to this document.
Parameters:
[path]
<String>
Returns:
- <String>
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:
schema
<Schema>
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:
[path]
<String>
Returns:
- <Boolean>
Example
MyModel = mongoose.model('test', { name: { type: String, default: 'Val '} }); var m = new MyModel(); m.$isDefault('name'); // true
function Object() { [native code] }#$isDeleted(
[val]
)Getter/setter, determines whether the document was removed or not.
Parameters:
[val]
<Boolean> optional, overrides whether mongoose thinks the doc is deleted
Returns:
- <Boolean> whether mongoose thinks this doc is deleted.
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 })
function Object() { [native code] }#$set(
path
,val
,[type]
,[options]
)Alias for
set()
, used internally to avoid conflictsParameters:
Document#depopulate(
path
)Takes a populated field and returns it to its unpopulated state.
Parameters:
path
<String>
Returns:
- <Document> this
show codeExample:
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.
Document.prototype.depopulate = function(path) { if (typeof path === 'string') { path = path.split(' '); } for (var i = 0; i < path.length; i++) { var populatedIds = this.populated(path[i]); if (!populatedIds) { continue; } delete this.$__.populated[path[i]]; this.$set(path[i], populatedIds); } return this; };
Document(
obj
,[fields]
,[skipId]
)Document constructor.
Parameters:
Inherits:
show codeEvents:
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
function Document(obj, fields, skipId, options) { this.$__ = new InternalCache; this.$__.emitter = new EventEmitter(); this.isNew = true; 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') { 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:
doc
<Document> a document to compare
Returns:
- <Boolean>
show codeDocuments are considered equal when they have matching
_id
s, unless neither
document has an_id
, in which case this function falls back to usingdeepEqual()
.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
show codeExample:
var promise = doc. populate('company'). populate({ path: 'notes', match: /airline/, select: 'text', model: 'modelName' options: opts }). execPopulate(); // summary doc.execPopulate().then(resolve, reject);
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:
show codeExample
// path doc.get('age') // 47 // dynamic casting to a string doc.get('age', String) // "47"
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) { if (schema.getters.length === 0) { return void 0; } 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)
show codeParameters:
path
<String>
Document.prototype.getValue = function(path) { return utils.getValue(path, this._doc); };
Document#init(
doc
,fn
)Initializes the document without setters or marking anything modified.
show codeCalled internally after a document is returned from mongodb.
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 codeDocument.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:
Returns:
- <ValidationError> the current ValidationError, with all currently invalidated paths
show codeThe
errorMsg
argument will become the message of theValidationError
.The
value
argument (if passed) will be available through theValidationError.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 } } } })
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:
path
<String>
Returns:
- <Boolean>
show codeExample
doc.set('documents.0.title', 'changed'); doc.isDirectModified('documents.0.title') // true doc.isDirectModified('documents') // false
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:
path
<String>
Returns:
- <Boolean>
show codeExample
Thing.findOne().select('nested.name').exec(function (err, doc) { doc.isDirectSelected('nested.name') // true doc.isDirectSelected('nested.otherName') // false doc.isDirectSelected('nested') // false })
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 (!isDefiningProjection(this.$__.selected[cur])) { 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:
path
<String>
show codeReturns:
- <Boolean>
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:
[path]
<String> optional
Returns:
- <Boolean>
show codeIf
path
is given, checks if a path or any full path containingpath
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
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:
path
<String>
Returns:
- <Boolean>
show codeExample
Thing.findOne().select('name').exec(function (err, doc) { doc.isSelected('name') // true doc.isSelected('age') // false })
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 (!isDefiningProjection(this.$__.selected[cur])) { 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:
show codeVery helpful when using Mixed types.
Example:
doc.mixed.type = 'changed'; doc.markModified('mixed.type'); doc.save() // changes to mixed.type are now persisted
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.
show codeReturns:
- <Array>
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 withexecPopulate()
Parameters:
Returns:
- <Document> this
show codeExample:
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
callexecPopulate()
.
Passing the same path a second time will overwrite the previous path options.
See Model.populate() for explaination of options.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; 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; };
Document#populated(
path
)Gets _id(s) used during population of the given
path
.Parameters:
path
<String>
show codeExample:
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.
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:
[options]
<Object> options optional options[options.safe]
<Object> overrides schema's safe option[options.validateBeforeSave]
<Boolean> set to false to save without validating.[fn]
<Function> optional callback
Returns:
- <Promise> Promise
See:
Example:
product.sold = Date.now(); product.save(function (err, product, numAffected) { if (err) .. })
The callback will receive three parameters
err
if an error occurredproduct
which is the savedproduct
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 - checkingerr
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
thetoObject.retainKeyOrder
option
to true on your schema.(
path
,val
,[type]
,[options]
)Sets the value of a path, or many paths.
Parameters:
show codeExample:
// 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 });
Document.prototype.set = Document.prototype.$set;
Document#setValue(
path
,value
)Sets a raw value for a path (no casting, setters, transformations)
show codeDocument.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:
options
<Object>
Returns:
- <Object>
show codeThis 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.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:
[options]
<Object>
Returns:
- <Object> js object
See:
show codeBuffers are converted to instances of mongodb.Binary for proper storage.
Options:
getters
apply all getters (path and virtual getters)virtuals
apply virtual getters (can overridegetters
option)minimize
remove empty objects (defaults to true)transform
a transform function to apply to the resulting document before returningdepopulate
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 convertedret
The plain object representation which has been convertedoptions
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.
Document.prototype.toObject = function(options) { return this.$toObject(options); };
Document#unmarkModified(
path
)Clears the modified state on the specified path.
Parameters:
path
<String> the path to unmark modified
show codeExample:
doc.foo = 'bar'; doc.unmarkModified('foo'); doc.save() // changes to foo will not be persisted
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.Returns:
- <Query>
See:
show codeExample:
weirdCar.update({$inc: {wheels:1}}, { w: 1 }, callback);
Valid options:
- same as in Model.update
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:
Returns:
- <Promise> Promise
show codeNote:
This method is called
pre
save and if a validation rule is violated, save is aborted and the error is returned to yourcallback
.Example:
doc.validate(function (err) { if (err) handleError(err); else // validation passed });
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.
Returns:
- <MongooseError, undefined> MongooseError if there are errors during validation, or undefined if there is no error.
show codeNote:
This method is useful if you need synchronous validation.
Example:
var err = doc.validateSync(); if ( err ){ handleError( err ); } else { // validation passed }
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.$markValid(
path
)Marks a path as valid, removing existing validation errors.
Parameters:
path
<String> the field to mark as valid
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 itsSchema
to false at construction time.
show codenew Schema({ name: String }, { id: false });
Document.prototype.id;
See:
- cursor/QueryCursor.js
QueryCursor#addCursorFlag(
flag
,value
)Adds a cursor flag.
Useful for setting thenoCursorTimeout
andtailable
flags.Returns:
- <AggregationCursor> this
QueryCursor#close(
callback
)Marks this cursor as closed. Will stop streaming and subsequent calls to
next()
will error.Parameters:
callback
<Function>
Returns:
- <Promise>
See:
QueryCursor#eachAsync(
fn
,[options]
,[options.parallel]
,[callback]
)Execute
fn
for every document in the cursor. Iffn
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:
- <Promise>
QueryCursor#map(
fn
)Registers a transform function which subsequently maps documents retrieved
via the streams interface or.next()
Parameters:
fn
<Function>
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:
callback
<Function>
Returns:
- <Promise>
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.Inherits:
Events:
cursor
: Emitted when the cursor is createderror
: Emitted when an error occurreddata
: Emitted when the stream is flowing and the next doc is readyend
: Emitted when the stream is exhausted
show codeQueryCursors 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.
UseQuery#cursor()
instead.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);
- cursor/AggregationCursor.js
AggregationCursor#addCursorFlag(
flag
,value
)Adds a cursor flag.
Useful for setting thenoCursorTimeout
andtailable
flags.Returns:
- <AggregationCursor> this
AggregationCursor(
agg
,options
)An AggregationCursor is a concurrency primitive for processing aggregation
results one document at a time. It is analogous to QueryCursor.Inherits:
Events:
cursor
: Emitted when the cursor is createderror
: Emitted when an error occurreddata
: Emitted when the stream is flowing and the next doc is readyend
: Emitted when the stream is exhausted
show codeAn AggregationCursor fulfills the Node.js streams3 API,
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.
UseAggregate#cursor()
instead.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:
callback
<Function>
Returns:
- <Promise>
See:
AggregationCursor#eachAsync(
fn
,[callback]
)Execute
fn
for every document in the cursor. Iffn
returns a promise,
will wait for the promise to resolve before iterating on to the next one.
Returns a promise that resolves when done.Returns:
- <Promise>
AggregationCursor#map(
fn
)Registers a transform function which subsequently maps documents retrieved
via the streams interface or.next()
Parameters:
fn
<Function>
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:
callback
<Function>
Returns:
- <Promise>
- schema/boolean.js
SchemaBoolean#cast(
value
,model
)Casts to boolean
show codeSchemaBoolean.prototype.cast = function(value, model) { if (value === null) { return value; } 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; } 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; } if (value === 'true') { return true; } if (value === 'false') { return false; } return !!value; } }; SchemaBoolean.$conditionalHandlers = utils.options(SchemaType.prototype.$conditionalHandlers, {});
SchemaBoolean#castForQuery(
$conditional
,val
)Casts contents for queries.
show codeParameters:
$conditional
<String>val
<T>
SchemaBoolean.prototype.castForQuery = function($conditional, val) { var handler; if (arguments.length === 2) { handler = SchemaBoolean.$conditionalHandlers[$conditional]; if (handler) { return handler.call(this, val); } return this._castForQuery(val); } 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:
value
<Any>
show codeReturns:
- <Boolean>
SchemaBoolean.prototype.checkRequired = function(value) { return value === true || value === false; };
SchemaBoolean(
path
,options
)Boolean SchemaType constructor.
show codeInherits:
function SchemaBoolean(path, options) { SchemaType.call(this, path, options, 'Boolean'); }
SchemaBoolean.schemaName
This schema type's name, to defend against minifiers that mangle
show code
function names.SchemaBoolean.schemaName = 'Boolean';
- schema/documentarray.js
DocumentArray#cast(
value
,document
)Casts contents
show codeDocumentArray.prototype.cast = function(value, doc, init, prev, options) { // lazy load MongooseDocumentArray || (MongooseDocumentArray = require('../types/documentarray')); 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 // 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); } 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); } i = value.length; while (i--) { 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 Document) && 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; } 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 (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); } } } } } return value; };
DocumentArray(
key
,schema
,options
)SubdocsArray SchemaType constructor
show codeInherits:
function DocumentArray(key, schema, options) { var EmbeddedDocument = _createConstructor(schema, options); EmbeddedDocument.prototype.$basePath = key; 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; }); } }
DocumentArray#doValidate()
Performs local validations first, then validations on each embedded doc
show codeDocumentArray.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) { return fn(err); } var count = array && array.length; var error; if (!count) { return fn(); } 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 // 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]; if (!doc) { --count || fn(error); 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) { 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.
Returns:
show codeNote:
This method ignores the asynchronous validators.
DocumentArray.prototype.doValidateSync = function(array, scope) { var schemaTypeError = SchemaType.prototype.doValidateSync.call(this, array, scope); if (schemaTypeError) { return schemaTypeError; } var count = array && array.length, resultError = null; if (!count) { return; } // 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) { // only first error if (resultError) { break; } // sidestep sparse entries var doc = array[i]; if (!doc) { 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) { resultError = subdocValidateError; } } return resultError; };
DocumentArray.schemaName
This schema type's name, to defend against minifiers that mangle
show code
function names.DocumentArray.schemaName = 'DocumentArray';
- schema/array.js
SchemaArray#applyGetters(
value
,scope
)Overrides the getters application for the population special-case
show codeSchemaArray.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); };
SchemaArray#cast(
value
,doc
,init
)Casts values for set().
show codeParameters:
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(); for (var i = 0, l = indexes.length; i < l; ++i) { var pathIndex = indexes[i][0][this.path]; if (pathIndex === '2dsphere' || pathIndex === '2d') { return; } } } 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) { 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); } } 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.
show codeParameters:
$conditional
<String>[value]
<T>
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 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) { method = Constructor.castForQuery; } var caster = this.caster; 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); } } return val; }; function cast$all(val) { if (!Array.isArray(val)) { val = [val]; } 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); return this.castForQuery(val); } 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); } } return cast(this.casterConstructor.schema, val); } var handle = SchemaArray.prototype.$conditionalHandlers = {}; 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'); } var ret = []; for (var i = 0; i < val.length; ++i) { ret.push(cast(this.casterConstructor.schema, val[i])); } return ret; }; handle.$near = handle.$nearSphere = geospatial.cast$near; handle.$within = handle.$geoWithin = geospatial.cast$within; handle.$size = handle.$minDistance = handle.$maxDistance = castToNumber; handle.$exists = $exists; handle.$type = $type; 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:
value
<Any>
show codeReturns:
- <Boolean>
SchemaArray.prototype.checkRequired = function(value) { return !!(value && value.length); };
SchemaArray(
key
,cast
,options
)Array SchemaType constructor
Parameters:
key
<String>cast
<SchemaType>options
<Object>
show codeInherits:
function SchemaArray(key, cast, options, schemaOptions) { // lazy load EmbeddedDoc || (EmbeddedDoc = require('../types').Embedded); var typeKey = 'type'; if (schemaOptions && schemaOptions.typeKey) { typeKey = schemaOptions.typeKey; } if (cast) { var castOptions = {}; 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; } } // support { type: 'String' } var name = typeof cast === 'string' ? cast : utils.getFunctionName(cast); var caster = name in Types ? Types[name] : cast; this.casterConstructor = caster; if (typeof caster === 'function' && !caster.$isArraySubdocument) { this.caster = new caster(null, castOptions); } else { this.caster = caster; } if (!(this.caster instanceof EmbeddedDoc)) { this.caster.path = key; } } this.$isMongooseArray = true; SchemaType.call(this, key, options, 'Array'); var defaultArr; var fn; if (this.defaultValue != null) { defaultArr = this.defaultValue; fn = typeof defaultArr === 'function'; } if (!('defaultValue' in this) || this.defaultValue !== void 0) { this.default(function() { var arr = []; if (fn) { arr = defaultArr(); } else if (defaultArr != null) { arr = arr.concat(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
show code
function names.SchemaArray.schemaName = 'Array';
- schema/decimal128.js
Decimal128#cast(
value
,doc
,init
)Casts to Decimal128
show codeDecimal128.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) { return value; } if (typeof value === 'object' && typeof value.$numberDecimal === 'string') { return Decimal128Type.fromString(value.$numberDecimal); } 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); };
Decimal128#checkRequired(
value
,doc
)Check if the given value satisfies a required validator.
show codeReturns:
- <Boolean>
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.
show codeInherits:
function Decimal128(key, options) { SchemaType.call(this, key, options, 'Decimal128'); }
Decimal128.schemaName
This schema type's name, to defend against minifiers that mangle
show code
function names.Decimal128.schemaName = 'Decimal128';
- schema/number.js
SchemaNumber#cast(
value
,doc
,init
)Casts to number
show codeParameters:
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 === undefined) { return value; } // lazy load Document || (Document = require('./../document')); if (value instanceof Document) { value.$__.wasPopulated = true; return value; } // 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); } // 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; } var val = value && typeof value._id !== 'undefined' ? value._id : // documents value; 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); } } throw new CastError('number', value, this.path); };
SchemaNumber#castForQuery(
$conditional
,[value]
)Casts contents for queries.
show codeParameters:
$conditional
<String>[value]
<T>
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.
show codeReturns:
- <Boolean>
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.
Returns:
- <SchemaType> this
show codeExample:
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 }) // 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). })
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 }); } return this; };
SchemaNumber#min(
value
,[message]
)Sets a minimum number validator.
Returns:
- <SchemaType> this
show codeExample:
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 }) // 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). })
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 }); } return this; };
SchemaNumber(
key
,options
)Number SchemaType constructor.
show codeInherits:
function SchemaNumber(key, options) { SchemaType.call(this, key, options, 'Number'); }
SchemaNumber.schemaName
This schema type's name, to defend against minifiers that mangle
show code
function names.SchemaNumber.schemaName = 'Number';
- schema/objectid.js
ObjectId#auto(
turnOn
)Adds an auto-generated ObjectId default if turnOn is true.
Parameters:
turnOn
<Boolean> auto generated ObjectId defaults
show codeReturns:
- <SchemaType> this
ObjectId.prototype.auto = function(turnOn) { if (turnOn) { this.default(defaultId); this.set(resetId); } return this; };
ObjectId#cast(
value
,doc
,init
)Casts to ObjectId
show codeObjectId.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 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); } // 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 oid) { return value; } 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) { } } } if (value.toString instanceof Function) { try { return new oid(value.toString()); } catch (err) { throw new CastError('ObjectId', value, this.path); } } throw new CastError('ObjectId', value, this.path); };
ObjectId#castForQuery(
$conditional
,[val]
)Casts contents for queries.
show codeParameters:
$conditional
<String>[val]
<T>
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.
show codeReturns:
- <Boolean>
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.
show codeInherits:
function ObjectId(key, options) { 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 ' + '`Mongoose.Types.ObjectId` instead of using ' + '`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'); }
ObjectId.schemaName
This schema type's name, to defend against minifiers that mangle
show code
function names.ObjectId.schemaName = 'ObjectId';
- schema/string.js
SchemaString#cast()
Casts to String
show codeSchemaString.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 (typeof value === 'string') { return value; } else if (Buffer.isBuffer(value) || !utils.isObject(value)) { throw new CastError('string', 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 = new pop.options.model(value); ret.$__.wasPopulated = true; return ret; } // If null or undefined if (value === null || value === undefined) { return value; } if (typeof value !== 'undefined') { // handle documents being passed if (value._id && typeof value._id === 'string') { return value._id; } // 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(); } } throw new CastError('string', value, this.path); };
SchemaString#castForQuery(
$conditional
,[val]
)Casts contents for queries.
show codeParameters:
$conditional
<String>[val]
<T>
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; } 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, notnull
orundefined
) and
has positive length. Therequired
validator will fail for empty
strings.show codeReturns:
- <Boolean>
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
Returns:
- <SchemaType> this
show codeExample:
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 }) // 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 })
SchemaString.prototype.enum = function() { if (this.enumValidator) { this.validators = this.validators.filter(function(v) { return v.validator !== this.enumValidator; }, this); this.enumValidator = false; } if (arguments[0] === void 0 || arguments[0] === false) { return this; } var values; var errorMessage; 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])); } } 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; };
SchemaString#lowercase()
Adds a lowercase setter.
Returns:
- <SchemaType> this
show codeExample:
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
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 });
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:
Returns:
- <SchemaType> this
show codeAny 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: '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)" })
Empty strings,
undefined
, andnull
values always pass the match validator. If you require these values, enable therequired
validator also.var s = new Schema({ name: { type: String, match: /^a/, required: true }})
SchemaString.prototype.match = function match(regExp, message) { // yes, we allow multiple match validators var msg = message || MongooseError.messages.String.match; var matchValidator = function(v) { if (!regExp) { return false; } var ret = ((v != null && v !== '') ? regExp.test(v) : true); return ret; }; this.validators.push({ validator: matchValidator, message: msg, type: 'regexp', regexp: regExp }); return this; };
SchemaString#maxlength(
value
,[message]
)Sets a maximum length validator.
Returns:
- <SchemaType> this
show codeExample:
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 }) // 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). })
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; };
SchemaString#minlength(
value
,[message]
)Sets a minimum length validator.
Returns:
- <SchemaType> this
show codeExample:
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). })
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 }); } return this; };
SchemaString(
key
,options
)String SchemaType constructor.
show codeInherits:
function SchemaString(key, options) { this.enumValues = []; this.regExp = null; SchemaType.call(this, key, options, 'String'); }
SchemaString#trim()
Adds a trim setter.
Returns:
- <SchemaType> this
show codeThe 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
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 });
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:
- <SchemaType> this
show codeExample:
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
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 });
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
show code
function names.SchemaString.schemaName = 'String';
- schema/date.js
SchemaDate#cast(
value
)Casts to date
show codeParameters:
value
<Object> to cast
SchemaDate.prototype.cast = function(value) { // If null or undefined if (value === null || value === void 0 || value === '') { return null; } if (value instanceof Date) { if (isNaN(value.valueOf())) { throw new CastError('date', value, this.path); } return 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 date = new Date(Number(value)); } else if (value.valueOf) { // support for moment.js date = new Date(value.valueOf()); } if (!isNaN(date.valueOf())) { return date; } throw new CastError('date', value, this.path); };
SchemaDate#castForQuery(
$conditional
,[value]
)Casts contents for queries.
show codeParameters:
$conditional
<String>[value]
<T>
SchemaDate.prototype.castForQuery = function($conditional, val) { var handler; if (arguments.length !== 2) { return this._castForQuery($conditional); } handler = this.$conditionalHandlers[$conditional]; if (!handler) { throw new Error('Can\'t use ' + $conditional + ' with Date.'); } 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 ofDate
.show codeReturns:
- <Boolean>
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.
Returns:
- <SchemaType> this
show codeThis sets the
expireAfterSeconds
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 thems
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');
SchemaDate.prototype.expires = function(when) { if (!this._index || this._index.constructor.name !== 'Object') { this._index = {}; } this._index.expires = when; utils.expires(this._index); return this; };
SchemaDate#max(
maximum
,[message]
)Sets a maximum date validator.
Returns:
- <SchemaType> this
show codeExample:
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 }) // 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). })
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 }); } return this; };
SchemaDate#min(
value
,[message]
)Sets a minimum date validator.
Returns:
- <SchemaType> this
show codeExample:
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). })
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.
show codeInherits:
function SchemaDate(key, options) { SchemaType.call(this, key, options, 'Date'); }
SchemaDate.schemaName
This schema type's name, to defend against minifiers that mangle
show code
function names.SchemaDate.schemaName = 'Date';
- schema/embedded.js
Embedded#cast(
value
)Casts contents
show codeParameters:
value
<Object>
Embedded.prototype.cast = function(val, doc, init, priorVal) { if (val && val.$isSingleNested) { 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 Constructor(void 0, doc ? doc.$__.selected : void 0, doc); subdoc.init(val); } else { if (Object.keys(val).length === 0) { return new Constructor({}, doc ? doc.$__.selected : void 0, doc); } return new Constructor(val, doc ? doc.$__.selected : void 0, doc, undefined, { priorDoc: priorVal }); } return subdoc; };
Embedded#castForQuery(
[$conditional]
,value
)Casts contents for query
show codeParameters:
[$conditional]
<string> optional query operator (like$eq
or$in
)value
<T>
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; } if (this.options.runSetters) { val = this._applySetters(val); } return new this.caster(val); };
Embedded#discriminator(
name
,schema
)Adds a discriminator to this property
show codeParameters:
Embedded.prototype.discriminator = function(name, schema) { discriminator(this.caster, name, schema); this.caster.discriminators[name] = _createConstructor(schema); return this.caster.discriminators[name]; };
Embedded#doValidate()
Async validation on this single nested doc.
show codeEmbedded.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); } 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 codeEmbedded.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
show codeInherits:
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'); }
- schema/buffer.js
SchemaBuffer#cast(
value
,doc
,init
)Casts contents
show codeSchemaBuffer.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; } // lazy load Document || (Document = require('./../document')); if (value instanceof Document) { value.$__.wasPopulated = true; return value; } // setting a populated path if (Buffer.isBuffer(value)) { return value; } else if (!utils.isObject(value)) { throw new CastError('buffer', 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); ret = new pop.options.model(value); ret.$__.wasPopulated = true; return ret; } // documents if (value && value._id) { value = value._id; } if (value && value.isMongooseBuffer) { return value; } 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; } 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; } if (value === null) { return value; } var type = typeof value; if (type === 'string' || type === 'number' || Array.isArray(value)) { if (type === 'number') { 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); };
SchemaBuffer#castForQuery(
$conditional
,[value]
)Casts contents for queries.
show codeParameters:
$conditional
<String>[value]
<T>
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); } 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.show codeReturns:
- <Boolean>
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
show codeInherits:
function SchemaBuffer(key, options) { SchemaType.call(this, key, options, 'Buffer'); }
SchemaBuffer#subtype(
subtype
)Sets the default subtype
for this buffer. You can find a list of allowed subtypes here.Parameters:
subtype
<Number> the default subtype
Returns:
- <SchemaType> this
show codeExample:
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
SchemaBuffer.prototype.subtype = function(subtype) { this.options.subtype = subtype; return this; };
SchemaBuffer.schemaName
This schema type's name, to defend against minifiers that mangle
show code
function names.SchemaBuffer.schemaName = 'Buffer';
- schema/mixed.js
Mixed#cast(
value
)Casts
val
for Mixed.Parameters:
value
<Object> to cast
show codethis is a no-op
Mixed.prototype.cast = function(val) { return val; };
Mixed#castForQuery(
$cond
,[val]
)Casts contents for queries.
show codeParameters:
$cond
<String>[val]
<T>
Mixed.prototype.castForQuery = function($cond, val) { if (arguments.length === 2) { return val; } return $cond; };
Mixed(
path
,options
)Mixed SchemaType constructor.
show codeInherits:
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 {}; }; } } SchemaType.call(this, path, options, 'Mixed'); }
Mixed.schemaName
This schema type's name, to defend against minifiers that mangle
show code
function names.Mixed.schemaName = 'Mixed';
- services/cursor/eachAsync.js
module.exports(
next
,fn
,options
,[callback]
)Execute
fn
for every document in the cursor. Iffn
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:
- <Promise>
- services/updateValidators.js
module.exports(
query
,schema
,castedDoc
,options
)Applies validators and defaults to update and findOneAndUpdate operations,
specifically passing a null doc asthis
to validators and defaults - services/setDefaultsOnInsert.js
module.exports(
filter
,schema
,castedDoc
,options
)Applies defaults to update and findOneAndUpdate operations.
- connection.js
Connection#_close(
force
,callback
)Handles closing the connection
show codeConnection.prototype._close = function(force, callback) { var _this = this; this._closeCalled = true; switch (this.readyState) { case 0: // disconnected callback && callback(); break; case 1: // connected case 4: // unauthorized this.readyState = STATES.disconnecting; this.doClose(force, function(err) { if (err) { _this.error(err, callback); } else { _this.onClose(force); callback && callback(); } }); break; case 2: // connecting this.once('open', function() { _this.close(callback); }); break; case 3: // disconnecting if (!callback) { break; } this.once('close', function() { callback(); }); break; } return this; };
Connection#_open(
callback
)Handles opening the connection with the appropriate method based on connection type.
show codeParameters:
callback
<Function>
Connection.prototype._open = function(emit, callback) { this.readyState = STATES.connecting; this._closeCalled = false; var _this = this; var method = this.replica ? 'doOpenSet' : 'doOpen'; // 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; } _this.onOpen(callback); }); };
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.show codeReturns:
- <Boolean> true if the authentication mechanism specified in the options object requires
Connection.prototype.authMechanismDoesNotRequirePassword = function() { if (this.options && this.options.auth) { return authMechanismsWhichDontRequirePassword.indexOf(this.options.auth.authMechanism) >= 0; } return true; };
Connection#close(
[force]
,[callback]
)Closes the connection
show codeReturns:
- <Connection> self
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(force, function(error) { callback && callback(error); if (error) { reject(error); return; } resolve(); }); }); };
Connection#collection(
name
,[options]
)Retrieves a collection, creating it if not cached.
Returns:
- <Collection> collection instance
show codeNot typically needed by applications. Just talk to your collection through your model.
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); } return this.collections[name]; };
Connection(
base
)Connection constructor
Parameters:
base
<Mongoose> a mongoose instance
Inherits:
Events:
connecting
: Emitted whenconnection.{open,openSet}()
is executed on this connection.connected
: Emitted when this connection successfully connects to the db. May be emitted multiple times inreconnected
scenarios.open
: Emitted after weconnected
andonOpen
is executed on all of this connections models.disconnecting
: Emitted whenconnection.close()
was executed.disconnected
: Emitted after getting disconnected from the db.close
: Emitted after wedisconnected
andonClose
executed on all of this connections models.reconnected
: Emitted after weconnected
and subsequentlydisconnected
, 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.
show codeFor practical reasons, a Connection equals a Db.
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.states = STATES; this._readyState = STATES.disconnected; this._closeCalled = false; this._hasOpened = false; }
(
collection
,[options]
,[callback]
)Helper for
createCollection()
. Will explicitly create the given collection
with specified options. Used to create capped collections
and views from mongoose.Parameters:
collection
<string> The collection to delete[options]
<Object> see MongoDB driver docs[callback]
<Function>
Returns:
- <Promise>
show codeOptions are passed down without modification to the MongoDB driver's
createCollection()
functionConnection.prototype.createCollection = _wrapConnHelper(function createCollection(collection, options, cb) { if (typeof options === 'function') { cb = options; options = {}; } this.db.createCollection(collection, options, cb); });
(
collection
,[callback]
)Helper for
dropCollection()
. Will delete the given collection, including
all documents and indexes.show codeReturns:
- <Promise>
Connection.prototype.dropCollection = _wrapConnHelper(function dropCollection(collection, cb) { this.db.dropCollection(collection, cb); });
(
[callback]
)Helper for
dropDatabase()
. Deletes the given database, including all
collections, documents, and indexes.Parameters:
[callback]
<Function>
show codeReturns:
- <Promise>
Connection.prototype.dropDatabase = _wrapConnHelper(function dropDatabase(cb) { this.db.dropDatabase(cb); });
Connection#error(
err
,callback
)error
show codeGraceful error handling, passes error to callback
if available, else emits error on the connection.Connection.prototype.error = function(err, callback) { if (callback) { return callback(err); } this.emit('error', err); };
Connection#model(
name
,[schema]
,[collection]
)Defines or retrieves a model.
Parameters:
Returns:
- <Model> The compiled model
See:
show codevar 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 modelname
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.prototype.model = function(name, schema, collection) { // collection name discovery if (typeof schema === 'string') { collection = schema; schema = false; } 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 (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]; } var opts = {cache: false, connection: this}; var model; if (schema && schema.instanceOfSchema) { // 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; } this.models[name] = model.__subclass(this, schema, collection); return this.models[name]; };
Connection#modelNames()
Returns an array of model names created on this connection.
show codeReturns:
- <Array>
Connection.prototype.modelNames = function() { return Object.keys(this.models); };
Connection#onClose()
Called when the connection closes
show codeConnection.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(force); } } this.emit('close', force); };
Connection#onOpen()
Called when the connection is opened
show codeConnection.prototype.onOpen = function(callback) { var _this = this; function open(err, isAuth) { if (err) { _this.readyState = isAuth ? STATES.unauthorized : STATES.disconnected; _this.error(err, callback); return; } _this.readyState = STATES.connected; // 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(); } } callback && callback(); _this.emit('open'); } // 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_string
,[database]
,[port]
,[options]
,[callback]
)Opens the connection to MongoDB.
Parameters:
See:
show codeoptions
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 serverauto_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.prototype.open = util.deprecate(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) { 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(); }); }); // 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; }, '`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');
(
uris
,[database]
,[options]
,[callback]
)Opens the connection to a replica set.
Parameters:
See:
show codeExample:
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.
Theoptions
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 serverauto_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.prototype.openSet = util.deprecate(function(uris, database, options, callback) { var Promise = PromiseProvider.get(); try { callback = this._handleOpenSetArgs.apply(this, arguments); } catch (err) { return new Promise.ES6(function(resolve, reject) { reject(err); }); } 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(); }); }); // 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; }, '`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');
Connection#openUri(
uri
,[options]
,[callback]
)Opens the connection with a URI using
MongoClient.connect()
.show codeParameters:
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; } var Promise = PromiseProvider.get(); var _this = this; if (options) { options = utils.clone(options, { retainKeyOrder: true }); delete options.useMongoClient; 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 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; } if (options.bufferCommands != null) { options.bufferMaxEntries = 0; this.config.bufferCommands = options.bufferCommands; delete options.bufferCommands; } } this._connectionOptions = options; 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); } callback && callback(error); return reject(error); } // 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() { _this.emit('reconnectFailed'); }); db.s.topology.on('close', function() { // Implicitly emits 'disconnected' _this.readyState = STATES.disconnected; }); db.on('timeout', function() { _this.emit('timeout'); }); delete _this.then; delete _this.catch; _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'); }); }); this.then = function(resolve, reject) { return promise.then(resolve, reject); }; this.catch = function(reject) { return promise.catch(reject); }; return this; };
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.
show codeReturns:
- <Boolean> true if the provided options object provides enough data to authenticate with,
Connection.prototype.optionsProvideAuthenticationData = function(options) { return (options) && (options.user) && ((options.pass) || this.authMechanismDoesNotRequirePassword()); };
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.show codeReturns:
- <Boolean> true if the connection should be authenticated after it is opened, otherwise false.
Connection.prototype.shouldAuthenticate = function() { return (this.user !== null && this.user !== void 0) && ((this.pass !== null || this.pass !== void 0) || this.authMechanismDoesNotRequirePassword()); };
Connection#collections
A hash of the collections associated with this connection
show codeConnection.prototype.collections;
Connection#config
A hash of the global options that are associated with this connection
show codeConnection.prototype.config;
Connection#db
The mongodb.Db instance, set when the connection is opened
show codeConnection.prototype.db;
Connection#readyState
Connection ready state
- 0 = disconnected
- 1 = connected
- 2 = connecting
- 3 = disconnecting
Each state change emits its associated event name.
Example
show codeconn.on('connected', callback); conn.on('disconnected', callback);
Object.defineProperty(Connection.prototype, 'readyState', { get: function() { return this._readyState; }, set: function(val) { if (!(val in STATES)) { throw new Error('Invalid connection state: ' + val); } 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; } if (STATES.connected === val) { this._hasOpened = true; } this.emit(STATES[val]); } } });
- drivers/node-mongodb-native/collection.js
NativeCollection#getIndexes(
callback
)Retreives information about this collections indexes.
Parameters:
callback
<Function>
NativeCollection()
A node-mongodb-native collection implementation.
Inherits:
show codeAll methods methods from the node-mongodb-native driver are copied and wrapped in queue management.
function NativeCollection() { this.collection = null; MongooseCollection.apply(this, arguments); }
NativeCollection#onClose()
Called when the connection closes
show codeNativeCollection.prototype.onClose = function(force) { MongooseCollection.prototype.onClose.call(this, force); };
NativeCollection#onOpen()
Called when the connection opens.
show codeNativeCollection.prototype.onOpen = function() { 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 (!_this.opts.capped.size) { // non-capped callback(null, _this.conn.db.collection(_this.name)); return _this.collection; } // capped 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) { if (err) { return callback(err); } var doc = docs[0]; var exists = !!doc; if (exists) { if (doc.options && doc.options.capped) { callback(null, c); } else { var msg = 'A non-capped collection exists with the name: ' + _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(_this.opts.capped); opts.capped = true; _this.conn.db.createCollection(_this.name, opts, callback); } }); }); function callback(err, collection) { if (err) { // likely a strict mode error _this.conn.emit('error', err); } else { _this.collection = collection; MongooseCollection.prototype.onOpen.call(_this); } } };
- drivers/node-mongodb-native/connection.js
NativeConnection#doClose(
[force]
,[fn]
)Closes the connection
show codeReturns:
- <Connection> this
NativeConnection.prototype.doClose = function(force, fn) { this.db.close(force, fn); return this; };
NativeConnection#doOpen(
fn
)Opens the connection to MongoDB.
Parameters:
fn
<Function>
show codeReturns:
- <Connection> this
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) { 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) { 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(); }); return this; };
NativeConnection#doOpenSet(
fn
)Opens a connection to a MongoDB ReplicaSet.
Parameters:
fn
<Function>
Returns:
- <Connection> this
show codeSee description of doOpen for server options. In this case
options.replset
is also passed to ReplSetServers.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)); }); 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); 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'); }); this.db.on('all', function() { _this.emit('all'); }); this.db.open(function(err) { if (err) return fn(err); fn(); listen(_this); }); return this; };
NativeConnection()
A node-mongodb-native connection implementation.
show codeInherits:
function NativeConnection() { MongooseConnection.apply(this, arguments); this._listening = false; }
NativeConnection#parseOptions(
passed
,[connStrOptions]
)Prepares default connection options for the node-mongodb-native driver.
Parameters:
show codeNOTE:
passed
options take precedence over connection string options.NativeConnection.prototype.parseOptions = function(passed, connStrOpts) { var o = passed ? require('../../utils').clone(passed) : {}; 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]; } 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; } // 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; } if (o.promiseLibrary) { o.db.promiseLibrary = o.promiseLibrary; } validate(o); return o; };
NativeConnection#useDb(
name
)Switches to a different database using the same connection pool.
Parameters:
name
<String> The database name
Returns:
- <Connection> New Connection Object
show codeReturns a new connection object, with the new db.
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); } function wireup() { newConn.db = _this.db.db(name); newConn.onOpen(); // setup the events appropriately listen(newConn); } newConn.name = name; // push onto the otherDbs stack, this is used when state changes this.otherDbs.push(newConn); newConn.otherDbs.push(this); return newConn; };
NativeConnection.STATES
Expose the possible connection states.
show codeNativeConnection.STATES = STATES;
- error/messages.js
MongooseError.messages()
The default built-in validator error messages. These may be customized.
show codevar 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.'; 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}).'; 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}).'; 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}.";
As you might have noticed, error messages support basic templating
{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
Click the "show code" link below to see all defaults.
- error/cast.js
CastError(
type
,value
)Casting Error constructor.
show codeInherits:
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/objectExpected.js
ObjectExpectedError(
type
,value
)Strict mode error constructor
show codeInherits:
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/disconnected.js
DisconnectedError(
type
,value
)Casting Error constructor.
show codeInherits:
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; } }
- error/objectParameter.js
ObjectParameterError(
value
,paramName
,fnName
)Constructor for errors that happen when a parameter that's expected to be
an object isn't an objectshow codeInherits:
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; } }
- error/validation.js
ValidationError#toString()
Console.log helper
show codeValidationError.prototype.toString = function() { return this.name + ': ' + _generateMessage(this); };
ValidationError(
instance
)Document Validation Error
Parameters:
instance
<Document>
show codeInherits:
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 { 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/validator.js
ValidatorError(
properties
)Schema validator error
Parameters:
properties
<Object>
show codeInherits:
function ValidatorError(properties) { var msg = properties.message; if (!msg) { msg = MongooseError.messages.general.default; } 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/index.js
MongooseError(
msg
)MongooseError constructor
Parameters:
msg
<String> Error message
show codeInherits:
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
show codesave()
fails because the underlying
document was not found. The constructor takes one parameter, the
conditions that mongoose passed toupdate()
when trying to update
the document.MongooseError.DocumentNotFoundError = require('./notFound');
MongooseError.messages
The default built-in validator error messages.
show codeMongooseError.messages = require('./messages'); // backward compat MongooseError.Messages = MongooseError.messages;
See:
- error/version.js
VersionError()
Version Error constructor.
show codeInherits:
function VersionError(doc, currentVersion, modifiedPaths) { var modifiedPathsStr = modifiedPaths.join(', '); MongooseError.call(this, 'No matching document found for id "' + doc._id + '" version ' + currentVersion + ' modifiedPaths "' + modifiedPathsStr + '"'); this.name = 'VersionError'; this.version = currentVersion; this.modifiedPaths = modifiedPaths; }
- error/strict.js
StrictModeError(
type
,value
)Strict mode error constructor
show codeInherits:
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.path = path; }
- aggregate.js
Aggregate#addCursorFlag(
flag
,value
)Adds a cursor flag
See:
show codeExample:
Model.aggregate(..).addCursorFlag('noCursorTimeout', true).exec();
Aggregate.prototype.addCursorFlag = function(flag, value) { if (!this.options) { this.options = {}; } this.options[flag] = value; return this; };
Aggregate#addFields(
arg
)Appends a new $addFields operator to this aggregate pipeline.
Requires MongoDB v3.4+ to workParameters:
arg
<Object> field specification
Returns:
See:
show codeExamples:
// 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 ] } });
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}); };
Aggregate(
[ops]
)Aggregate constructor used for building aggregation pipelines.
show codeExample:
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 }]);
Returned when calling Model.aggregate().
Example:
Model .aggregate({ $match: { age: { $gte: 21 }}}) .unwind('tags') .exec(callback)
Note:
- 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. Usenew Aggregate({ $match: { _id: mongoose.Types.ObjectId('00000000000000000000000a') } });
instead.
function Aggregate() { this._pipeline = []; this._model = undefined; this.options = {}; 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:
See:
show codeExample:
Model.aggregate(..).allowDiskUse(true).exec(callback)
Aggregate.prototype.allowDiskUse = function(value) { this.options.allowDiskUse = value; return this; };
Aggregate#append(
ops
)Appends new operators to this aggregate pipeline
Parameters:
ops
<Object> operator(s) to append
Returns:
show codeExamples:
aggregate.append({ $project: { field: 1 }}, { $limit: 2 }); // or pass an array var pipeline = [{ $match: { daw: 'Logic Audio X' }} ]; aggregate.append(pipeline);
Aggregate.prototype.append = function() { var args = (arguments.length === 1 && util.isArray(arguments[0])) ? arguments[0] : utils.args(arguments); if (!args.every(isOperator)) { throw new Error('Arguments must be aggregate pipeline operators'); } this._pipeline = this._pipeline.concat(args); return this; };
Aggregate#collation(
collation
)Adds a collation
Parameters:
collation
<Object> options
See:
show codeExample:
Model.aggregate(..).collation({ locale: 'en_US', strength: 1 }).exec();
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:
See:
show codeExample:
var cursor = Model.aggregate(..).cursor({ batchSize: 1000, useMongooseAggCursor: true }).exec(); cursor.each(function(error, doc) { // use doc });
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:
[callback]
<Function>
Returns:
- <Promise>
See:
show codeExample:
aggregate.exec(callback); // Because a promise is returned, the `callback` is optional. var promise = aggregate.exec(); promise.then(..);
Aggregate.prototype.exec = function(callback) { if (!this._model) { 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; var collection = this._model.collection; if (options && options.cursor) { if (options.cursor.async) { delete options.cursor.async; return new Promise.ES6(function(resolve) { if (!collection.buffer) { process.nextTick(function() { var cursor = collection.aggregate(pipeline, options); decorateCursor(cursor); resolve(cursor); callback && callback(null, cursor); }); return; } collection.emitter.once('queue', function() { var cursor = collection.aggregate(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 = collection.aggregate(pipeline, options); decorateCursor(cursor); return cursor; } return new Promise.ES6(function(resolve, reject) { if (!pipeline.length) { var err = new Error('Aggregate has empty pipeline'); if (callback) { callback(err); } reject(err); return; } prepareDiscriminatorPipeline(_this); model.hooks.execPre('aggregate', _this, function(error) { if (error) { var _opts = { error: error }; return model.hooks.execPost('aggregate', _this, [null], _opts, function(error) { if (callback) { callback(error); } reject(error); }); } 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); }); }); }); }); };
Aggregate#explain(
callback
)Execute the aggregation with explain
Parameters:
callback
<Function>
Returns:
- <Promise>
show codeExample:
Model.aggregate(..).explain(callback)
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; } prepareDiscriminatorPipeline(_this); _this._model .collection .aggregate(_this._pipeline, _this.options || {}) .explain(function(error, result) { if (error) { if (callback) { callback(error); } reject(error); return; } if (callback) { callback(null, result); } resolve(result); }); }); };
Aggregate#facet(
facet
)Combines multiple aggregation pipelines.
Parameters:
facet
<Object> options
Returns:
- <Aggregate> this
See:
show codeExample:
Model.aggregate(...) .facet({ books: [{ groupBy: '$author' }], price: [{ $bucketAuto: { groupBy: '$price', buckets: 2 } }] }) .exec(); // Output: { books: [...], price: [{...}, {...}] }
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:
See:
show codeNote 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' }` 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) { var cloneOptions = {}; if (options) { if (!utils.isObject(options)) { throw new TypeError('Invalid graphLookup() argument. Must be an object.'); } utils.mergeClone(cloneOptions, 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 }); };
Aggregate#group(
arg
)Appends a new custom $group operator to this aggregate pipeline.
Parameters:
arg
<Object> $group operator contents
Returns:
See:
Examples:
aggregate.group({ _id: "$department" });
isOperator(
obj
)Checks whether an object is likely a pipeline operator
Parameters:
obj
<Object> object to check
show codeReturns:
- <Boolean>
function isOperator(obj) { var k; if (typeof obj !== 'object') { return false; } k = Object.keys(obj); 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:
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:
See:
show codeExamples:
aggregate.lookup({ from: 'users', localField: 'userId', foreignField: '_id', as: 'users' });
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:
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
show codeReturns:
Aggregate.prototype.model = function(model) { this._model = model; 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; };
Aggregate#near(
parameters
)Appends a new $geoNear operator to this aggregate pipeline.
Parameters:
parameters
<Object>
Returns:
See:
NOTE:
MUST be used as the first operator in the pipeline.
Examples:
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#option(
options
,number
,boolean
,object
)Lets you set arbitrary options, for middleware or plugins.
Parameters:
options
<Object> keys to merge into current optionsnumber
<[options.maxTimeMS]> limits the time this aggregation will run, see MongoDB docs onmaxTimeMS
boolean
<[options.allowDiskUse]> if true, the MongoDB server will use the hard drive to store data during this aggregationobject
<[options.collation]> seeAggregate.prototype.collation()
Returns:
- <Aggregate> this
See:
show codeExample:
var agg = Model.aggregate(..).option({ allowDiskUse: true }); // Set the `allowDiskUse` option agg.options; // `{ allowDiskUse: true }`
Aggregate.prototype.option = function(value) { for (var key in value) { this.options[key] = value[key]; } return this; };
Aggregate#pipeline()
Returns the current pipeline
Returns:
- <Array>
show codeExample:
MyModel.aggregate().match({ test: 1 }).pipeline(); // [{ $match: { test: 1 } }]
Aggregate.prototype.pipeline = function() { return this._pipeline; };
Aggregate#project(
arg
)Appends a new $project operator to this aggregate pipeline.
Returns:
See:
show codeMongoose query selection syntax is also supported.
Examples:
// include a, include b, exclude _id aggregate.project("a b -_id"); // 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' } }) // etc aggregate.project({ salary_k: { $divide: [ "$salary", 1000 ] } });
Aggregate.prototype.project = function(arg) { var fields = {}; 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'); } return this.append({$project: fields}); };
Aggregate#read(
pref
,[tags]
)Sets the readPreference option for the aggregation query.
Parameters:
show codeExample:
Model.aggregate(..).read('primaryPreferred').exec(callback)
Aggregate.prototype.read = function(pref, tags) { if (!this.options) { this.options = {}; } read.call(this, pref, tags); return this; };
Aggregate#sample(
size
)Appepnds new custom $sample operator(s) to this aggregate pipeline.
Parameters:
size
<Number> number of random documents to pick
Returns:
See:
show codeExamples:
aggregate.sample(3); // Add a pipeline that picks 3 random documents
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:
aggregate.skip(10);
Aggregate#sort(
arg
)Appends a new $sort operator to this aggregate pipeline.
Returns:
- <Aggregate> this
See:
show codeIf 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.Examples:
// these are equivalent aggregate.sort({ field: 'asc', test: -1 }); aggregate.sort('field -test');
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; } 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; } 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.'); } return this.append({$sort: sort}); };
Aggregate#then(
[resolve]
,[reject]
)Provides promise for aggregate.
Returns:
- <Promise>
See:
show codeExample:
Model.aggregate(..).then(successCallback, errorCallback);
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:
See:
show codeNote that the
$unwind
operator requires the path name to start with '$'.
Mongoose will prepend '$' if the specified field doesn't start '$'.Examples:
aggregate.unwind("tags"); aggregate.unwind("a", "b", "c");
Aggregate.prototype.unwind = function() { var args = utils.args(arguments); 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); };
- ES6Promise.js
ES6Promise(
fn
)ES6 Promise wrapper constructor.
Parameters:
fn
<Function> a function which will be called when the promise is resolved that acceptsfn(err, ...){}
as signature
show codePromises are returned from executed queries. Example:
var query = Candy.find({ bar: true }); var promise = query.exec();
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.function ES6Promise() { throw new Error('Can\'t use ES6 promise with mpromise style constructor'); } ES6Promise.use = function(Promise) { ES6Promise.ES6 = Promise; }; module.exports = ES6Promise;
- utils.js
exports.each(
arr
,fn
)Executes a function on each element of an array (like _.each)
show codeexports.each = function(arr, fn) { for (var i = 0; i < arr.length; ++i) { fn(arr[i]); } };
exports.mergeClone(
to
,fromObj
)merges to with a copy of from
show codeexports.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 }); } } } };
exports.pluralization
Pluralization rules.
show codeexports.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 codeexports.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.Schema()
The Mongoose Schema constructor
Example:
var mongoose = require('mongoose'); var Schema = mongoose.Schema; var CatSchema = new Schema(..);
exports#SchemaTypes
The various Mongoose SchemaTypes.
Note:
Alias of mongoose.Schema.Types for backwards compatibility.
show codeexports.SchemaType = require('./schematype.js');
exports#Types
The various Mongoose Types.
Example:
var mongoose = require('mongoose'); var array = mongoose.Types.Array;
Types:
Using this exposed access to the
ObjectId
type, we can construct ids on demand.
show codevar ObjectId = mongoose.Types.ObjectId; var id1 = new ObjectId;
exports.Types = require('./types');
- promise.js
Promise#addBack(
listener
)Adds a single function as a listener to both err and complete.
Parameters:
listener
<Function>
Returns:
- <Promise> this
It will be executed with traditional node.js argument position when the promise is resolved.
promise.addBack(function (err, args...) { if (err) return handleError(err); console.log('success'); })
Alias of mpromise#onResolve.
Deprecated. Use
onResolve
instead.Promise#addCallback(
listener
)Adds a listener to the
complete
(success) event.Parameters:
listener
<Function>
Returns:
- <Promise> this
Alias of mpromise#onFulfill.
Deprecated. Use
onFulfill
instead.Promise#addErrback(
listener
)Adds a listener to the
err
(rejected) event.Parameters:
listener
<Function>
Returns:
- <Promise> this
Alias of mpromise#onReject.
Deprecated. Use
onReject
instead.Promise#catch(
onReject
)ES6-style
.catch()
shorthandParameters:
onReject
<Function>
Returns:
- <Promise>
Promise#end()
Signifies that this promise was the last in a chain of
then()s
: if a handler passed to the call tothen
which produced this promise throws, the exception will go uncaught.See:
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);
Promise#error(
err
)Rejects this promise with
err
.Returns:
- <Promise> this
show codeIf the promise has already been fulfilled or rejected, not action is taken.
Differs from #reject by first casting
err
to anError
if it is notinstanceof Error
.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 theevent
.Returns:
- <Promise> this
See:
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 acceptsfn(err, ...){}
as signature
Inherits:
Events:
err
: Emits when the promise is rejectedcomplete
: Emits when the promise is fulfilled
show codePromises are returned from executed queries. Example:
var query = Candy.find({ bar: true }); var promise = query.exec();
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.function Promise(fn) { MPromise.call(this, fn); }
Promise#reject(
reason
)Rejects this promise with
reason
.Returns:
- <Promise> this
See:
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 noerr
is passed.show codeIf the promise has already been fulfilled or rejected, not action is taken.
err
will be cast to an Error if not already instanceof Error.NOTE: overrides mpromise#resolve to provide error casting.
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
oronReject
are passed, they are added as SUCCESS/ERROR callbacks to this promise after the nextTick.Returns:
- <Promise> newPromise
Conforms to promises/A+ specification.
Example:
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 < 10000) { throw new Error('Too few people!!!'); } else { throw new Error('Still need more people!!!'); } }).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.
Deprecated. Use
fulfill
instead.Promise.ES6(
resolver
)ES6-style promise constructor wrapper around mpromise.
show codePromise.ES6 = function(resolver) { var promise = new Promise(); // No try/catch for backwards compatibility resolver( function() { promise.complete.apply(promise, arguments); }, function(e) { promise.error(e); }); return promise; };
Parameters:
resolver
<Function>
Returns:
- <Promise> new promise
- schematype.js
SchemaType#applyGetters(
value
,scope
)Applies getters to a value
show codeSchemaType.prototype.applyGetters = function(value, scope) { var v = value, getters = this.getters, len = getters.length; if (!len) { return v; } while (len--) { v = getters[len].call(scope, v, this); } return v; };
SchemaType#applySetters(
value
,scope
,init
)Applies setters
show codeSchemaType.prototype.applySetters = function(value, scope, init, priorVal, options) { var v = this._applySetters(value, scope, init, priorVal, options); if (v == null) { return v; } // do not cast until all setters are applied #665 v = this.cast(v, scope, init, priorVal, options); return v; };
SchemaType#castForQuery(
[$conditional]
,val
)Cast the given value with the given optional query operator.
show codeParameters:
[$conditional]
<String> query operator, like$eq
or$in
val
<T>
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); } return handler.call(this, val); } val = $conditional; return this._castForQuery(val); };
SchemaType#checkRequired(
val
)Default check for if this path satisfies the
required
validator.show codeParameters:
val
<T>
SchemaType.prototype.checkRequired = function(val) { return val != null; };
SchemaType#default(
val
)Sets a default value for this SchemaType.
Parameters:
val
<Function, T> the default value
Returns:
show codeExample:
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: { 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 }
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
show codevalue
using the validators declared for this SchemaType.SchemaType.prototype.doValidate = function(value, fn, scope) { var err = false; var path = this.path; var count = this.validators.length; if (!count) { return fn(null); } 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 _this = this; this.validators.forEach(function(v) { if (err) { return; } var validator = v.validator; var ok; 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; } 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); } 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:
value
<T>scope
<Object>
Returns:
show codeNote:
This method ignores the asynchronous validators.
SchemaType.prototype.doValidateSync = function(value, scope) { var err = null, path = this.path, count = this.validators.length; if (!count) { return null; } var validate = function(ok, validatorProperties) { if (err) { return; } if (ok !== undefined && !ok) { var ErrorConstructor = validatorProperties.ErrorConstructor || ValidatorError; err = new ErrorConstructor(validatorProperties); err.$isValidatorError = true; } }; 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; } } validators.forEach(function(v) { if (err) { return; } var validator = v.validator; 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 && !validatorProperties.isAsync) { try { ok = validator.call(scope, value); } catch (error) { ok = false; validatorProperties.reason = error; } validate(ok, validatorProperties); } } }); return err; };
SchemaType#get(
fn
)Adds a getter to this schematype.
Parameters:
fn
<Function>
Returns:
- <SchemaType> this
show codeExample:
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.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
show codeSchemaType.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 = 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.
Returns:
- <SchemaType> this
show codeExample:
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 });
NOTE:
Indexes are created in the background by default. Specify
background: false
to override.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 usingunshift()
.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:
- <SchemaType> this
See:
show codeExample:
var s = new Schema({ born: { type: Date, required: true }) // or with custom error message 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); // with custom error messaging 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 ifval != null
(that is, if
the value is not null nor undefined). However, most built-in mongoose schema
types override the defaultcheckRequired
function: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; }, this); this.isRequired = false; return 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(_this.path) && !this.isModified(_this.path)) { return true; } return ((typeof required === 'function') && !required.apply(this)) || _this.checkRequired(v, this); }; this.originalRequiredValue = required; if (typeof required === 'string') { message = required; required = undefined; } var msg = message || MongooseError.messages.general.required; this.validators.unshift(utils.assign({}, customOptions, { validator: this.requiredValidator, message: msg, type: 'required' })); return this; };
SchemaType(
path
,[options]
,[instance]
)SchemaType constructor
show codefunction 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 prop in options) { if (this[prop] && typeof this[prop] === 'function') { // { unique: true, index: true } if (prop === 'index' && this._index) { continue; } 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[prop].apply(this, opts); } } Object.defineProperty(this, '$$context', { enumerable: false, configurable: false, writable: true, value: null }); }
SchemaType#select(
val
)Sets default
select()
behavior for this path.Parameters:
val
<Boolean>
Returns:
- <SchemaType> this
show codeSet 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.prototype.select = function select(val) { this.selected = !!val; return this; };
SchemaType#set(
fn
)Adds a setter to this schematype.
Parameters:
fn
<Function>
Returns:
- <SchemaType> this
show codeExample:
function capitalize (val) { if (typeof val !== 'string') 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 stored in MongoDB.
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 onUser.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.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.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:
bool
<Boolean>
Returns:
- <SchemaType> this
show codeExample:
var s = new Schema({ name: { type: String, sparse: true }) Schema.path('name').index({ sparse: true });
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}; } this._index.sparse = bool; return this; };
SchemaType#text(
bool
)Declares a full text index.
Parameters:
bool
<Boolean>
Returns:
- <SchemaType> this
show codeExample:
var s = new Schema({name : {type: String, text : true }) Schema.path('name').index({text : true});
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}; } this._index.text = bool; return this; };
SchemaType#unique(
bool
)Declares an unique index.
Parameters:
bool
<Boolean>
Returns:
- <SchemaType> this
show codeExample:
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.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}; } this._index.unique = bool; return this; };
SchemaType#validate(
obj
,[errorMsg]
,[type]
)Adds validator(s) for this document path.
Parameters:
Returns:
- <SchemaType> this
show codeValidators always receive the value to validate as their first argument and must return
Boolean
. Returningfalse
means validation failed.The error message argument is optional. If not passed, the default generic error message template will be used.
Examples:
// make sure every value is equal to "something" function validator (val) { return val == 'something'; } new Schema({ name: { type: String, validate: validator }}); // with a custom error message var custom = [validator, 'Uh oh, {PATH} does not equal "something".'] new Schema({ name: { type: String, validate: custom }}); // adding many validators at a time var many = [ { validator: validator, msg: 'uh oh' } , { validator: anotherValidator, 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 of `{PATH}` failed with value `{VALUE}`');
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 hereAsynchronous validation:
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
orfalse
to communicate either success or failure respectively.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({ validator: function (value) { return new Promise(function (resolve, reject) { 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.
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, anerror
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.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; } var i, length, arg; 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'; throw new Error(msg); } this.validate(arg.validator, arg); } return this; };
SchemaType._isRef(
self
,value
,doc
,init
)Determines if value is a valid Reference.
show codeSchemaType._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; } } return false; };
Parameters:
self
<SchemaType>value
<Object>doc
<Document>init
<Boolean>
Returns:
- <Boolean>
- querystream.js
QueryStream#__next()
Pulls the next doc from the cursor.
show codeQueryStream.prototype.__next = function() { if (this.paused || this._destroyed) { this._running = false; return this._running; } var _this = this; _this._inline = T_INIT; _this._cursor.nextObject(function cursorcb(err, doc) { _this._onNextObject(err, doc); }); // 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 codeQueryStream.prototype._init = function() { if (this._destroyed) { return; } var query = this.query, model = query.model, options = query._optionsForExec(model), _this = this; try { query.cast(model); } catch (err) { return _this.destroy(err); } _this._fields = utils.clone(query._fields); options.fields = query._castFields(_this._fields); 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 codeQueryStream.prototype._next = function _next() { if (this.paused || this._destroyed) { this._running = false; return this._running; } this._running = true; 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); } } // avoid stack overflows with large result sets. // trampoline instead of recursion. while (this.__next()) { } };
QueryStream#_onNextObject(
err
,doc
)Transforms raw
show codedoc
s returned from the cursor into a model instance.QueryStream.prototype._onNextObject = function _onNextObject(err, doc) { if (this._destroyed) { return; } if (this.paused) { this._buffer || (this._buffer = []); this._buffer.push([err, doc]); this._running = false; return this._running; } 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(); } var opts = this.query._mongooseOptions; if (!opts.populate) { return opts.lean === true ? emit(this, doc) : createAndEmit(this, null, doc); } var _this = this; var pop = helpers.preparePopulationOptionsMQ(_this.query, _this.query._mongooseOptions); // Hack to work around gh-3108 pop.forEach(function(option) { delete option.model; }); 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); }); }; function createAndEmit(self, populatedIds, doc) { var instance = helpers.createModel(self.query.model, doc, self._fields); var opts = populatedIds ? {populated: populatedIds} : undefined; 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.
show codeParameters:
[err]
<Error>
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'); };
QueryStream#pause()
Pauses this stream.
show codeQueryStream.prototype.pause = function() { this.paused = true; };
QueryStream#pipe()
Pipes this query stream into another stream. This method is inherited from NodeJS Streams.
See:
Example:
query.stream().pipe(writeStream [, options])
QueryStream(
query
,[options]
)Provides a Node.js 0.8 style ReadStream interface for Queries.
Inherits:
Events:
data
: emits a single Mongoose documenterror
: emits when an error occurs during streaming. This will emit before theclose
event.close
: emits when the stream reaches the end of the cursor or an error occurs, or the stream is manuallydestroy
ed. After this event, no more events are emitted.
show codevar 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);
Valid options
transform
: optional function which accepts a mongoose document. The return value of the function will be emitted ondata
.
Example
// JSON.stringify all documents before emitting var stream = Thing.find().stream({ transform: JSON.stringify }); 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.
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 && typeof options.transform === 'function' ? options.transform : K; // give time to hook up events var _this = this; process.nextTick(function() { _this._init(); }); }
QueryStream#resume()
Resumes this stream.
show codeQueryStream.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#paused
Flag stating whether or not this stream is paused.
show codeQueryStream.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 codeQueryStream.prototype.readable;
- model.js
Model#$where(
argument
)Creates a
Query
and specifies a$where
condition.Returns:
- <Query>
See:
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.username.indexOf("val") !== -1').exec(function (err, docs) {});
Model#increment()
Signal that we desire an increment of this documents version.
See:
show codeExample:
Model.findById(id, function (err, doc) { doc.increment(); doc.save(function (err) { .. }) })
Model.prototype.increment = function increment() { this.$__.version = VERSION_ALL; return this; };
Model#model(
name
)Returns another Model instance.
Parameters:
name
<String> model name
show codeExample:
var doc = new Tank; doc.model('User').findById(id, callback);
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 anerror
occurred. If not listening, the event bubbles to the connection used to create this Model.index
: Emitted afterModel#ensureIndexes
completes. If an error occurred it is passed with the event.index-single-start
: Emitted when an individual index starts withinModel#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 withinModel#ensureIndexes
. If an error occurred it is passed with the event. The fields, options, and index name are also passed.
show codeProvides the interface to MongoDB collections as well as creates document instances.
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); }
Model#remove(
[fn]
)Removes this document from the db.
Parameters:
[fn]
<function(err, product)> optional callback
Returns:
- <Promise> Promise
show codeExample:
product.remove(function (err, product) { if (err) return handleError(err); Product.findById(product._id, function (err, product) { console.log(product) // null }) })
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 errorsExample:
product.remove().then(function (product) { ... }).catch(function (err) { assert.ok(err) })
Model.prototype.remove = function remove(options, fn) { if (typeof options === 'function') { fn = options; options = undefined; } var _this = this; if (!options) { options = {}; } if (this.$__.removing) { if (fn) { this.$__.removing.then( function(res) { fn(null, res); }, function(err) { fn(err); }); } return this; } if (this.$__.isDeleted) { setImmediate(function() { fn(null, _this); }); return 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) { reject(where); fn && fn(where); return; } if (!options.safe && _this.schema.options.safe) { options.safe = _this.schema.options.safe; } _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); }); }); return this.$__.removing; };
Model#save(
[options]
,[options.safe]
,[options.validateBeforeSave]
,[fn]
)Saves this document.
Parameters:
[options]
<Object> options optional options[options.safe]
<Object> overrides schema's safe option[options.validateBeforeSave]
<Boolean> set to false to save without validating.[fn]
<Function> optional callback
Returns:
- <Promise> Promise
See:
show codeExample:
product.sold = Date.now(); product.save(function (err, product, numAffected) { if (err) .. })
The callback will receive three parameters
err
if an error occurredproduct
which is the savedproduct
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 - checkingerr
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
thetoObject.retainKeyOrder
option
to true on your schema.Model.prototype.save = function(options, fn) { if (typeof options === 'function') { fn = options; options = undefined; } if (!options) { options = {}; } if (fn) { fn = this.constructor.$wrapCallback(fn); } return this.$__save(options, fn); };
Model.aggregate(
[...]
,[callback]
)Performs aggregations on the models collection.
show codeModel.aggregate = function aggregate() { var args = [].slice.call(arguments), aggregate, callback; if (typeof args[args.length - 1] === 'function') { callback = args.pop(); } if (args.length === 1 && util.isArray(args[0])) { aggregate = new Aggregate(args[0]); } else { aggregate = new Aggregate(args); } aggregate.model(this); if (typeof callback === 'undefined') { return aggregate; } if (callback) { callback = this.$wrapCallback(callback); } aggregate.exec(callback); };
Parameters:
If a
callback
is passed, theaggregate
is executed and aPromise
is returned. If a callback is not passed, theaggregate
itself is returned.This function does not trigger any middleware.
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 } ] }); // 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 } ] });
NOTE:
- 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
show codeinsertOne
,updateOne
,updateMany
,replaceOne
,deleteOne
, and/ordeleteMany
operations to the MongoDB server in one
command. This is faster than sending multiple independent operations (like)
if you usecreate()
) because withbulkWrite()
there is only one round
trip to MongoDB.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']) { op = op['updateOne']; return function(callback) { try { 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); } callback(null); }; } else if (op['updateMany']) { op = op['updateMany']; return function(callback) { try { 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); } callback(null); }; } else if (op['replaceOne']) { return function(callback) { try { op['replaceOne']['filter'] = cast(_this.schema, op['replaceOne']['filter']); } catch (error) { return callback(error); } // 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); } 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 { 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; };
Parameters:
Returns:
- <Promise> resolves to a `BulkWriteOpResult` if the operation succeeds
See:
Mongoose will perform casting on all operations you provide.
This function does not trigger any middleware, not
save()
norupdate()
.
If you need to triggersave()
middleware for every document usecreate()
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 codeModel.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); } return mq.count(conditions, callback); };
Returns:
- <Query>
Example:
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.
show codeMyModel.create(docs)
doesnew MyModel(doc).save()
for every doc in
docs.Model.create = function create(doc, callback) { var args; var cb; var discriminatorKey = this.schema.options.discriminatorKey; 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); } } 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; } 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; var callbackWrapper = function(error, doc) { if (error) { if (!firstError) { firstError = error; } return callback(null, { error: error }); } 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) { toSave.$__original_save({ __noPromise: true }, callbackWrapper); } else { toSave.save({ __noPromise: true }, callbackWrapper); } }); }); 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(firstError, savedDocs); } else { reject(firstError); } return; } 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 promise; };
Returns:
- <Promise>
This function triggers the following middleware
save()
Example:
// pass individual docs Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) { if (err) // ... }); // pass an array var array = [{ type: 'jelly bean' }, { type: 'snickers' }]; Candy.create(array, function (err, candies) { if (err) // ... var jellybean = candies[0]; var snickers = candies[1]; // ... }); // callback is optional; use the returned promise if you like: var promise = Candy.create({ type: 'jawbreaker' }); promise.then(function (jawbreaker) { // ... })
Model.createIndexes(
[options]
,[cb]
)Similar to
show codeensureIndexes()
, except for it uses thecreateIndex
function. TheensureIndex()
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.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) { 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. 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 create = function() { if (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 indexOptions = index[1]; _handleSafe(options); indexSingleStart(indexFields, options); 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); } 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; } } }
Returns:
- <Promise>
Model.deleteMany(
conditions
,[callback]
)Deletes all of the documents that match
show codeconditions
from the collection.
Behaves likeremove()
, but deletes all documents that matchconditions
regardless of thesingle
option.Model.deleteMany = function deleteMany(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.deleteMany(callback); };
Returns:
- <Query>
Example:
Character.deleteMany({ name: /Stark/, age: { $gte: 18 } }, function (err) {});
Note:
Like
Model.remove()
, this function does not triggerpre('remove')
orpost('remove')
hooks.Model.deleteOne(
conditions
,[callback]
)Deletes the first document that matches
show codeconditions
from the collection.
Behaves likeremove()
, but deletes at most one document regardless of thesingle
option.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); };
Returns:
- <Query>
Example:
Character.deleteOne({ name: 'Eddard Stark' }, function (err) {});
Note:
Like
Model.remove()
, this function does not triggerpre('remove')
orpost('remove')
hooks.Model.discriminator(
name
,schema
)Adds a discriminator type.
show codeModel.discriminator = function(name, schema) { var model; if (typeof name === 'function') { model = name; name = utils.getFunctionName(model); if (!(model.prototype instanceof Model)) { throw new Error('The provided class ' + name + ' must extend Model'); } } schema = discriminator(this, name, schema); if (this.db.models[name]) { throw new OverwriteModelError(name); } schema.$isRootDiscriminator = true; model = this.db.model(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 }); // apply methods and statics applyMethods(d, schema); applyStatics(d, schema); return d; }; // Model (class) features
Example:
function BaseSchema() { Schema.apply(this, arguments); this.add({ name: String, createdAt: Date }); } util.inherits(BaseSchema, Schema); var PersonSchema = new BaseSchema(); var BossSchema = new BaseSchema({ department: String }); var Person = mongoose.model('Person', PersonSchema); var Boss = Person.discriminator('Boss', BossSchema);
Model.distinct(
field
,[conditions]
,[callback]
)Creates a Query for a
show codedistinct
operation.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 = {}; } if (callback) { callback = this.$wrapCallback(callback); } return mq.distinct(field, conditions, callback); };
Returns:
- <Query>
Passing a
callback
immediately executes the query.Example
Link.distinct('url', { clicks: {$gt: 100}}, function (err, result) { if (err) return handleError(err); assert(Array.isArray(result)); console.log('unique urls with more than 100 clicks', result); }) var query = Link.distinct('url'); query.exec(callback);
Model.ensureIndexes(
[options]
,[cb]
)Sends
show codecreateIndex
commands to mongo for each index declared in the schema.
ThecreateIndex
commands are sent in series.Model.ensureIndexes = function ensureIndexes(options, callback) { if (typeof options === 'function') { callback = options; options = null; } if (options && options.__noPromise) { _ensureIndexes(this, options, callback); return; } if (callback) { callback = this.$wrapCallback(callback); } 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(); }); }); };
Returns:
- <Promise>
Example:
Event.ensureIndexes(function (err) { if (err) return handleError(err); });
After completion, an
index
event is emitted on thisModel
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.
Model.find(
conditions
,[projection]
,[options]
,[callback]
)Finds documents
show codeModel.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; } 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); } if (callback) { callback = this.$wrapCallback(callback); } return mq.find(conditions, callback); };
Parameters:
Returns:
- <Query>
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.findById(
id
,[projection]
,[options]
,[callback]
)Finds a single document by its _id field.
show codefindById(id)
is almost*
equivalent tofindOne({ _id: id })
. If you want to query by a document's_id
, usefindById()
instead offindOne()
.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); };
Parameters:
id
<Object, String, Number> value of <code>_id</code> to query by[projection]
<Object> optional fields to return (http://bit.ly/1HotzBo)[options]
<Object> optional see <a href="http://mongoosejs.com/docs/api.html#query_Query-setOptions"><code>Query.prototype.setOptions()</code></a>[callback]
<Function>
Returns:
- <Query>
The
id
is cast based on the Schema before sending the command.This function triggers the following middleware
findOne()
* Except for how it treats
undefined
. If you usefindOne()
, you'll see
thatfindOne(undefined)
andfindOne({ _id: undefined })
are equivalent
tofindOne({})
and return arbitrary documents. However, mongoose
translatesfindById(undefined)
intofindOne({ _id: null })
.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.findByIdAndRemove(
id
,[options]
,[callback]
)Issue a mongodb findAndModify remove command by a document's _id field.
show codefindByIdAndRemove(id, ...)
is equivalent tofindOneAndRemove({ _id: id }, ...)
.Model.findByIdAndRemove = function(id, options, callback) { if (arguments.length === 1 && typeof id === 'function') { 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); } if (callback) { callback = this.$wrapCallback(callback); } return this.findOneAndRemove({_id: id}, options, callback); };
Parameters:
Returns:
- <Query>
Finds a matching document, removes it, passing the found document (if any) to the callback.
Executes immediately if
callback
is passed, else aQuery
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 updateselect
: sets the document fields to returnpassRawResult
: if true, passes the raw result from the MongoDB driver as the third callback parameterstrict
: overwrites the schema's strict mode option for this update
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.findByIdAndUpdate(
id
,[update]
,[options]
,[options.lean]
,[callback]
)Issues a mongodb findAndModify update command by a document's _id field.
show codefindByIdAndUpdate(id, ...)
is equivalent tofindOneAndUpdate({ _id: id }, ...)
.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. ' + ' ' + this.modelName + '.findByIdAndUpdate(id, callback) ' + ' ' + this.modelName + '.findByIdAndUpdate(id) ' + ' ' + this.modelName + '.findByIdAndUpdate() '; throw new TypeError(msg); } return this.findOneAndUpdate({_id: id}, undefined); } // if a model is passed in instead of an id if (id instanceof Document) { id = id._id; } return this.findOneAndUpdate.call(this, {_id: id}, update, options, callback); };
Parameters:
id
<Object, Number, String> value of <code>_id</code> to query by[update]
<Object>[options]
<Object> optional see <a href="http://mongoosejs.com/docs/api.html#query_Query-setOptions"><code>Query.prototype.setOptions()</code></a>[options.lean]
<Object> if truthy, mongoose will return the document as a plain JavaScript object rather than a mongoose document. See <a href="http://mongoosejs.com/docs/api.html#query_Query-lean"><code>Query.lean()</code></a>.[callback]
<Function>
Returns:
- <Query>
Finds a matching document, updates it according to the
update
arg,
passing anyoptions
, and returns the found document (if any) to the
callback. The query executes immediately ifcallback
is passed else a
Query object is returned.This function triggers the following middleware
findOneAndUpdate()
Options:
new
: bool - true to return the modified document rather than the original. defaults to falseupsert
: 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 andupsert
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 updateselect
: sets the document fields to returnpassRawResult
: if true, passes the raw result from the MongoDB driver as the third callback parameterstrict
: overwrites the schema's strict mode option for this updaterunSettersOnQuery
: 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.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
Note:
All top level update keys which are not
atomic
operation names are treated as set operations:Example:
Model.findByIdAndUpdate(id, { name: 'jason bourne' }, options, callback) // is sent as Model.findByIdAndUpdate(id, { $set: { name: 'jason bourne' }}, options, callback)
This helps prevent accidentally overwriting your document with
{ name: 'jason bourne' }
.Note:
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 therunValidators
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 bourne'; doc.save(callback); });
Model.findOne(
[conditions]
,[projection]
,[options]
,[callback]
)Finds one document.
show codeModel.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; } // 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); } if (callback) { callback = this.$wrapCallback(callback); } return mq.findOne(conditions, callback); };
Parameters:
Returns:
- <Query>
The
conditions
are cast to their respective SchemaTypes before the command is sent.Note:
conditions
is optional, and ifconditions
is null or undefined,
mongoose will send an emptyfindOne
command to MongoDB, which will return
an arbitrary document. If you're querying by_id
, usefindById()
instead.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.findOneAndRemove(
conditions
,[options]
,[callback]
)Issue a mongodb findAndModify remove command.
show codeModel.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); } if (typeof options === 'function') { callback = options; options = undefined; } if (callback) { callback = this.$wrapCallback(callback); } var fields; if (options) { fields = options.select; options.select = undefined; } var mq = new this.Query({}, {}, this, this.collection); mq.select(fields); return mq.findOneAndRemove(conditions, options, callback); };
Parameters:
Returns:
- <Query>
See:
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.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 updatemaxTimeMS
: puts a time limit on the query - requires mongodb >= 2.6.0select
: sets the document fields to returnpassRawResult
: if true, passes the raw result from the MongoDB driver as the third callback parameterstrict
: overwrites the schema's strict mode option for this update
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 therunValidators
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 bourne'; doc.save(callback); });
Model.findOneAndUpdate(
[conditions]
,[update]
,[options]
,[options.lean]
,[callback]
)Issues a mongodb findAndModify update command.
show codeModel.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); } var fields; if (options && options.fields) { fields = options.fields; } 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; } else { if (!update.$setOnInsert) { update.$setOnInsert = {}; } update.$setOnInsert[this.schema.options.versionKey] = 0; } } var mq = new this.Query({}, {}, this, this.collection); mq.select(fields); return mq.findOneAndUpdate(conditions, update, options, callback); };
Parameters:
[conditions]
<Object>[update]
<Object>[options]
<Object> optional see <a href="http://mongoosejs.com/docs/api.html#query_Query-setOptions"><code>Query.prototype.setOptions()</code></a>[options.lean]
<Object> if truthy, mongoose will return the document as a plain JavaScript object rather than a mongoose document. See <a href="http://mongoosejs.com/docs/api.html#query_Query-lean"><code>Query.lean()</code></a>.[callback]
<Function>
Returns:
- <Query>
See:
Finds a matching document, updates it according to the
update
arg, passing anyoptions
, and returns the found document (if any) to the callback. The query executes immediately ifcallback
is passed else a Query object is returned.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()
maxTimeMS
: puts a time limit on the query - requires mongodb >= 2.6.0sort
: if multiple docs are found by the conditions, sets the sort order to choose which doc to updaterunValidators
: if true, runs update validators on this command. Update validators validate the update operation against the model's schema.setDefaultsOnInsert
: if this andupsert
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 parameterstrict
: overwrites the schema's strict mode option for this updaterunSettersOnQuery
: 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 bourne' }, options, callback) // is sent as Model.findOneAndUpdate(query, { $set: { name: 'jason bourne' }}, options, callback)
This helps prevent accidentally overwriting your document with
{ name: 'jason bourne' }
.Note:
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 therunValidators
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 bourne'; doc.save(callback); });
Model.geoNear(
GeoJSON
,options
,[callback]
)geoNear support for Mongoose
show codeModel.geoNear = function(near, options, callback) { if (typeof options === 'function') { callback = options; options = {}; } if (callback) { callback = this.$wrapCallback(callback); } 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); }); } var x; var y; var schema = this.schema; 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; } 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; } 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, init); } }; 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 ' + '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; } _this.collection.geoNear(near, options, handler); } }); };
Parameters:
Returns:
- <Promise>
See:
This function does not trigger any middleware. In particular, this
bypassesfind()
middleware.Options:
lean
{Boolean} return the raw object- All options supported by the driver are also supported
Example:
// Legacy point Model.geoNear([1,3], { maxDistance : 5, spherical : true }, function(err, results, stats) { console.log(results); }); // 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]
,[options.lean]
,[callback]
)Implements
show code$geoSearch
functionality for MongooseModel.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]'); } if (error) { callback && callback(error); reject(error); return; } // send the conditions in the options object options.search = conditions; _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 count = res.results.length; if (options.lean || count === 0) { callback && callback(null, res.results, res.stats); resolve(res.results, res.stats); return; } 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, {}, init); } }); }); };
Parameters:
conditions
<Object> an object that specifies the match condition (required)[options]
<Object> for the geoSearch, some (near, maxDistance) are required[options.lean]
<Object> if truthy, mongoose will return the document as a plain JavaScript object rather than a mongoose document. See <a href="http://mongoosejs.com/docs/api.html#query_Query-lean"><code>Query.lean()</code></a>.[callback]
<Function> optional callback
Returns:
- <Promise>
See:
This function does not trigger any middleware
Example:
var options = { near: [10, 10], maxDistance: 5 }; Locations.geoSearch({ type : "house" }, options, function(err, res) { console.log(res); });
Options:
near
{Array} x,y point to search formaxDistance
{Number} the maximum distance from the point near that a result can belimit
{Number} The maximum number of results to returnlean
{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.
show code
The document returned has no paths marked as modified initially.Model.hydrate = function(obj) { var model = require('./queryhelpers').createModel(this, obj); model.init(obj); return model; };
Parameters:
obj
<Object>
Returns:
- <Document>
Example:
// hydrate previous data into a Mongoose document var mongooseCandy = Candy.hydrate({ _id: '54108337212ffb6d459f854c', type: 'jelly bean' });
Model.init(
[callback]
)Performs any async initialization of this model against MongoDB. Currently,
show code
this function is only responsible for building indexes,
unlessautoIndex
is turned off.Model.init = function init(callback) { this.schema.emit('init', this); if (this.$init) { return this.$init; } 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); }); } else { resolve(_this); } }); return this.$init; };
Parameters:
[callback]
<Function>
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
toMyModel.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!'); });
Model.insertMany(
doc(s)
,[options]
,[options.ordered
,[options.rawResult
,[callback]
)Shortcut for validating an array of documents and inserting them into
show code
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.Model.insertMany = function(arr, options, callback) { var _this = this; if (typeof options === 'function') { callback = options; options = null; } if (callback) { callback = this.$wrapCallback(callback); } 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); 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 (ordered === false) { validationErrors.push(error); return callback(null, null); } return callback(error); } callback(null, doc); }); }); }); parallelLimit(toExecute, limit, function(error, docs) { if (error) { callback && callback(error); return; } // 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(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); }); _this.collection.insertMany(docObjects, options, function(error, res) { 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); } 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); }); }); };
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>[options.ordered
<Boolean> = 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 <code>insertMany()</code> with <code>ordered = false</code> is called an "unordered" <code>insertMany()</code>.[options.rawResult
<Boolean> = false] if false, the returned promise resolves to the documents that passed mongoose document validation. If <code>false</code>, will return the <a href="http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~insertWriteOpCallback">raw result from the MongoDB driver</a> with a <code>mongoose</code> property that contains <code>validationErrors</code> if this is an unordered <code>insertMany</code>.[callback]
<Function> callback
Returns:
- <Promise>
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
theordered
option to false.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' }]; Movies.insertMany(arr, function(error, docs) {});
Model.mapReduce(
o
,[callback]
)Executes a mapReduce command.
show codeModel.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 (!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.collection.mapReduce(null, null, o, function(err, ret, stats) { if (err) { callback && callback(err); reject(err); return; } 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); } callback && callback(null, ret, stats); if (resolveToObject) { return resolve({ model: ret, stats: stats }); } resolve(ret, stats); }); }); };
Parameters:
Returns:
- <Promise>
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.This function does not trigger any middleware.
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.sort
{Object} sort input objects using this keylimit
{Number} max number of documentskeeptemp
{Boolean, default:false} keep temporary datafinalize
{Function} finalize functionscope
{Object} scope variables exposed to map/reduce/finalize during executionjsMode
{Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.Xverbose
{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.
* 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 toreplace
,merge
, orreduce
, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with thelean
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); }); }) // `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 codeModel.populate = function(docs, paths, callback) { var _this = this; if (callback) { callback = this.$wrapCallback(callback); } // normalized paths var noPromise = paths && !!paths.__noPromise; paths = utils.populate(paths); // data that should persist across subPopulate calls var cache = {}; 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:
Returns:
- <Promise>
Available options:
- 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
Examples:
// 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' } ] User.populate(user, opts, function (err, user) { console.log(user); }); }); // populates an array of objects User.find(match, function (err, users) { var opts = [{ path: 'company', match: { x: 1 }, select: 'name' }] var promise = User.populate(users, opts); promise.then(console.log).end(); }) // 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 }) // 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
show codeconditions
from the collection.
To remove just the first document that matchesconditions
, set thesingle
option to true.Model.remove = function remove(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); } return mq.remove(conditions, callback); };
Returns:
- <Query>
Example:
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.Model.replaceOne(
conditions
,doc
,[options]
,[callback]
)Same as
show codeupdate()
, except MongoDB replace the existing document with the
given document (no atomic operators like$set
).Model.replaceOne = function replaceOne(conditions, doc, options, callback) { return _update(this, 'replaceOne', conditions, doc, options, callback); };
Parameters:
Returns:
- <Query>
This function triggers the following middleware
replaceOne()
Model.translateAliases(
raw
)Translate any aliases fields/conditions so the final query or document object is pure
show codeModel.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]; } } return fields; } else { // 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:
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
Model.update(
conditions
,doc
,[options]
,[callback]
)Updates one document in the database without returning it.
show codeModel.update = function update(conditions, doc, options, callback) { return _update(this, 'update', conditions, doc, options, callback); };
Parameters:
Returns:
- <Query>
This function triggers the following middleware
update()
Examples:
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); });
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 on this command. Update validators validate the update operation against the model's schema.setDefaultsOnInsert
: if this andupsert
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 thestrict
option for this updateoverwrite
(boolean) disables update-only mode, allowing you to overwrite the doc (false)
All
update
values are cast to their appropriate SchemaTypes before being sent.The
callback
function receives(err, rawResponse)
.err
is the error if any occurredrawResponse
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 bourne' }, options, callback) // is sent as 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 bourne' }
.Note:
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.
Note:
To update documents without waiting for a response from MongoDB, do not pass a
callback
, then callexec
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 bourne'; doc.save(callback); })
Model.updateMany(
conditions
,doc
,[options]
,[callback]
)Same as
show codeupdate()
, except MongoDB will update all documents that matchcriteria
(as opposed to just the first one) regardless of the value of
themulti
option.Model.updateMany = function updateMany(conditions, doc, options, callback) { return _update(this, 'updateMany', conditions, doc, options, callback); };
Parameters:
Returns:
- <Query>
Note updateMany will not fire update middleware. Use
pre('updateMany')
andpost('updateMany')
instead.This function triggers the following middleware
updateMany()
Model.updateOne(
conditions
,doc
,[options]
,[callback]
)Same as
show codeupdate()
, except MongoDB will update only the first document that
matchescriteria
regardless of the value of themulti
option.Model.updateOne = function updateOne(conditions, doc, options, callback) { return _update(this, 'updateOne', conditions, doc, options, callback); };
Parameters:
Returns:
- <Query>
This function triggers the following middleware
updateOne()
Model.where(
path
,[val]
)Creates a Query, applies the passed conditions, and returns the Query.
show codeModel.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); };
Returns:
- <Query>
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 chainingUser .where('age').gte(21).lte(65) .where('name', /^b/i) ... etc
Model#$where
Additional properties to attach to the query when calling
show codesave()
andisNew
is false.Model.prototype.$where;
Model#baseModelName
If this is a discriminator model,
show codebaseModelName
is the name of
the base model.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 (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; } 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); callback(err); return; } 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; 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; } this.emit('isNew', false); this.constructor.emit('isNew', false); } };
- query.js
Query#_applyPaths()
Applies schematype selected options to this query.
show codeQuery.prototype._applyPaths = function applyPaths() { this._fields = this._fields || {}; helpers.applyPaths(this._fields, this.model.schema); selectPopulatedFields(this); };
Query#_castFields(
fields
)Casts selected field arguments for field selection with mongo 2.2
Parameters:
fields
<Object>
See:
show codequery.select({ ids: { $elemMatch: { $in: [hexString] }})
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:
[callback]
<Function>
show codeSee:
Query.prototype._count = function(callback) { try { this.cast(this.model); } catch (err) { this.error(err); } if (this.error()) { return callback(this.error()); } var conds = this._conditions; var options = this._optionsForExec(); this._collection.count(conds, options, utils.tick(callback)); };
Query#_find(
[callback]
)Thunk around find()
Parameters:
[callback]
<Function>
show codeReturns:
- <Query> this
Query.prototype._find = function(callback) { this._castConditions(); if (this.error() != null) { callback(this.error()); return this; } this._applyPaths(); this._fields = this._castFields(this._fields); var fields = this._fieldsForExec(); var mongooseOptions = 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 (!mongooseOptions.populate) { return !!mongooseOptions.lean === true ? callback(null, docs) : completeMany(_this.model, docs, fields, userProvidedFields, null, callback); } var pop = helpers.preparePopulationOptionsMQ(_this, mongooseOptions); pop.__noPromise = true; _this.model.populate(docs, pop, function(err, docs) { if (err) return callback(err); return !!mongooseOptions.lean === true ? callback(null, docs) : completeMany(_this.model, docs, fields, userProvidedFields, pop, callback); }); }; var options = this._optionsForExec(); options.fields = this._fieldsForExec(); var filter = this._conditions; return this._collection.find(filter, options, cb); };
Query#_findOne(
[callback]
)Thunk around findOne()
Parameters:
[callback]
<Function>
show codeSee:
Query.prototype._findOne = function(callback) { this._castConditions(); if (this.error()) { return callback(this.error()); } 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.
show codeParameters:
model
<Model>
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; } if (options.upsert !== void 0) { options.upsert = !!options.upsert; } return options; };
Query#$where(
js
)Specifies a javascript function or expression to pass to MongoDBs query system.
Returns:
- <Query> this
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.
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:
- <Query> this
See:
Example
query.and([{ color: 'green' }, { status: 'ok' }])
Query#batchSize(
val
)Specifies the batchSize option.
Parameters:
val
<Number>
See:
Example
query.batchSize(100)
Note
Cannot be used with
distinct()
Query#box(
val
,Upper
)Specifies a $box condition
Returns:
- <Query> this
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 usingmquery().merge()
Parameters:
conds
<Object>
Returns:
- <Boolean>
Query#cast(
model
,[obj]
)Casts this query to the schema of
model
Returns:
- <Object>
show codeNote
If
obj
is present, it is cast instead of this query.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:
[reject]
<Function>
show codeReturns:
- <Promise>
Query.prototype.catch = function(reject) { return this.exec().then(null, reject); };
Query#centerSphere(
[path]
,val
)DEPRECATED Specifies a $centerSphere condition
Returns:
- <Query> this
show codeDeprecated. Use circle instead.
Example
var area = { center: [50, 50], radius: 10 }; query.where('loc').within().centerSphere(area);
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.
Returns:
- <Query> this
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:
value
<Object>
Returns:
- <Query> this
show codeSee:
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:
val
<Number>
See:
Example
query.comment('login query')
Note
Cannot be used with
distinct()
Query#count(
[criteria]
,[callback]
)Specifying this query as a
count
query.Parameters:
Returns:
- <Query> this
See:
show codePassing a
callback
executes the query.This function triggers the following middleware
count()
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); })
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:
[options]
<Object>
Returns:
See:
show codeThe
.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 ondata
and returned by.next()
.
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 matchescriteria
in the
collection, regardless of the value ofsingle
.Parameters:
Returns:
- <Query> this
show codeThis function does not trigger any middleware
Example
Character.deleteMany({ name: /Stark/, age: { $gte: 18 } }, callback) Character.deleteMany({ name: /Stark/, age: { $gte: 18 } }).then(next)
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.error(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 thesingle
option.Parameters:
Returns:
- <Query> this
show codeThis function does not trigger any middleware.
Example
Character.deleteOne({ name: 'Eddard Stark' }, callback) Character.deleteOne({ name: 'Eddard Stark' }).then(next)
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.error(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:
- <Query> this
See:
show codePassing a
callback
executes the query.This function does not trigger any middleware.
Example
distinct(field, conditions, callback) distinct(field, conditions) distinct(field, callback) distinct(field) distinct(callback) distinct()
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
conditionReturns:
- <Query> this
See:
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:
val
<Object>
Returns:
- <Query> this
Example
User.where('age').equals(49); // is the same as User.where('age', 49);
Query#error(
err
)Gets/sets the error flag on this query. If this flag is not null or
undefined, theexec()
promise will reject without executing.show codeExample:
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')); } });
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 });
Query.prototype.error = function error(err) { if (arguments.length === 0) { return this._error; } this._error = err; return this; };
Query#exec(
[operation]
,[callback]
)Executes the query
Parameters:
Returns:
- <Promise>
show codeExamples:
var promise = query.exec(); var promise = query.exec('update'); query.exec(callback); query.exec('find', callback);
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
conditionReturns:
- <Query> this
See:
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(
[filter]
,[callback]
)Finds documents.
Returns:
- <Query> this
show codeWhen 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)
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); } 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) { return Query.base.find.call(this); } this._find(callback); return this; };
Query#findOne(
[filter]
,[projection]
,[options]
,[callback]
)Declares the query a findOne operation. When executed, the first found document is passed to the callback.
Parameters:
[filter]
<Object> mongodb selector[projection]
<Object> optional fields to return[options]
<Object> seesetOptions()
[callback]
<Function> optional params are (error, document)
Returns:
- <Query> this
show codePassing a
callback
executes the query. The result of the query is a single document.- Note:
conditions
is optional, and ifconditions
is null or undefined, mongoose will send an emptyfindOne
command to MongoDB, which will return an arbitrary document. If you're querying by_id
, useModel.findById()
instead.
This function triggers the following middleware
findOne()
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 } });
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); prepareDiscriminatorCriteria(this); 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) { // 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:
[conditions]
<Object>[options]
<Object>[options.passRawResult]
<Boolean> if true, passes the raw result from the MongoDB driver as the third callback parameter[options.strict]
<Boolean, String> overwrites the schema's strict mode option[callback]
<Function> optional params are (error, document)
Returns:
- <Query> this
See:
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 updatemaxTimeMS
: puts a time limit on the query - requires mongodb >= 2.6.0passRawResult
: if true, passes the raw result from the MongoDB driver as the third callback parameter
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]
,[options.multipleCastError]
,[callback]
)Issues a mongodb findAndModify update command.
Parameters:
[query]
<Object, Query>[doc]
<Object>[options]
<Object>[options.passRawResult]
<Boolean> if true, passes the raw result from the MongoDB driver as the third callback parameter[options.strict]
<Boolean, String> overwrites the schema's strict mode option[options.multipleCastError]
<Boolean> by default, mongoose only returns the first error that occurred in casting the query. Turn on this option to aggregate all the cast errors.[callback]
<Function> optional params are (error, doc), unlesspassRawResult
is used, in which case params are (error, doc, writeOpResult)
Returns:
- <Query> this
Finds a matching document, updates it according to the
update
arg, passing anyoptions
, and returns the found document (if any) to the callback. The query executes immediately ifcallback
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)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 updatemaxTimeMS
: puts a time limit on the query - requires mongodb >= 2.6.0runValidators
: if true, runs update validators on this command. Update validators validate the update operation against the model's schema.setDefaultsOnInsert
: if this andupsert
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 parametercontext
(string) if set to 'query' andrunValidators
is on,this
will refer to the query in custom validator functions that update validation runs. Does nothing ifrunValidators
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
conditionParameters:
object
<Object> Must contain atype
property which is a String and acoordinates
property which is an Array. See the examples.
Returns:
- <Query> this
See:
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 eitherintersects()
orwithin()
.The
object
argument must containtype
andcoordinates
properties.
- type {String}
- coordinates {Array}Query#getQuery()
Returns the current query conditions as a JSON object.
Returns:
- <Object> current query conditions
show codeExample:
var query = new Query(); query.find({ a: 1 }).where('b').gt(2); query.getQuery(); // { a: 1, b: { $gt: 2 } }
Query.prototype.getQuery = function() { return this._conditions; };
Query#getUpdate()
Returns the current update operations as a JSON object.
Returns:
- <Object> current update operations
show codeExample:
var query = new Query(); query.update({}, { $set: { a: 5 } }); query.getUpdate(); // { $set: { a: 5 } }
Query.prototype.getUpdate = function() { return this._update; };
Query#gt(
[path]
,val
)Specifies a $gt query condition.
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.
See:
When called with one argument, the most recent path passed to
where()
is used.Query#hint(
val
)Sets query hints.
Parameters:
val
<Object> a hint object
Returns:
- <Query> this
See:
Example
query.hint({ indexA: 1, indexB: -1})
Note
Cannot be used with
distinct()
Query#in(
[path]
,val
)Specifies an $in query condition.
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:
[arg]
<Object>
Returns:
- <Query> this
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.
Returns:
- <Query> this
show codeDocuments returned from queries with the
lean
option enabled are plain javascript objects, not MongooseDocuments. They have nosave
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.
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:
val
<Number>
Example
query.limit(20)
Note
Cannot be used with
distinct()
Query#lt(
[path]
,val
)Specifies a $lt query condition.
See:
When called with one argument, the most recent path passed to
where()
is used.Query#lte(
[path]
,val
)Specifies a $lte query condition.
See:
When called with one argument, the most recent path passed to
where()
is used.Query#maxDistance(
[path]
,val
)Specifies a $maxDistance query condition.
See:
When called with one argument, the most recent path passed to
where()
is used.Query#maxScan(
val
)Specifies the maxScan option.
Parameters:
val
<Number>
See:
Example
query.maxScan(100)
Note
Cannot be used with
distinct()
Query#merge(
source
)Merges another Query or conditions object into this one.
Returns:
- <Query> this
show codeWhen a Query is passed, conditions, field selection and options are merged.
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.
Returns:
- <Query> this
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, filters documents for documents whosepath
property is a number that is equal toremainder
modulodivisor
.Parameters:
Returns:
- <Query> this
See:
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);
Query#mongooseOptions(
options
)Getter/setter around the current mongoose-specific options for this query
(populate, lean, etc.)show codeParameters:
options
<Object> if specified, overwrites the current options
Query.prototype.mongooseOptions = function(v) { if (arguments.length > 0) { this._mongooseOptions = v; } return this._mongooseOptions; };
Query#ne(
[path]
,val
)Specifies a $ne query condition.
See:
When called with one argument, the most recent path passed to
where()
is used.Query#near(
[path]
,val
)Specifies a
$near
or$nearSphere
conditionReturns:
- <Query> this
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
conditionshow codeExample
query.where('loc').nearSphere({ center: [10, 10], maxDistance: 5 });
Deprecated. Use
query.near()
instead with thespherical
option set totrue
.Example
query.where('loc').near({ center: [10, 10], spherical: true });
Query.prototype.nearSphere = function() { this._mongooseOptions.nearSphere = true; this.near.apply(this, arguments); return this; };
Query#nin(
[path]
,val
)Specifies an $nin query condition.
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:
- <Query> this
See:
Example
query.nor([{ color: 'green' }, { status: 'ok' }])
Query#or(
array
)Specifies arguments for an
$or
condition.Parameters:
array
<Array> array of conditions
Returns:
- <Query> this
See:
Example
query.or([{ color: 'red' }, { status: 'emergency' }])
Query#polygon(
[path]
,[coordinatePairs...]
)Specifies a $polygon condition
Returns:
- <Query> this
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'sref
field.[match]
<Object> Conditions for the population query[options]
<Object> Options for the population query (sort, etc)
Returns:
- <Query> this
show codeExample:
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.
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:
show codeExample:
var query = new Query(); query.setOptions({ lean : true }); query.collection(model.collection); query.where('age').gte(21).exec(callback);
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); } 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, 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:
Returns:
- <Query> this
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 }])
Query#regex(
[path]
,val
)Specifies a $regex query condition.
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:
Returns:
- <Query> this
show codeThis function does not trigger any middleware
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 theexec()
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()
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.error(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:
Returns:
- <Query> this
show codeNote replaceOne will not fire update middleware. Use
pre('replaceOne')
andpost('replaceOne')
instead.This function triggers the following middleware
replaceOne()
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")
Returns:
- <Query> this
See:
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#selectedExclusively()
Determines if exclusive field selection has been made.
Returns:
- <Boolean>
query.selectedExclusively() // false query.select('-name') query.selectedExclusively() // true query.selectedInclusively() // false
Query#selectedInclusively()
Determines if inclusive field selection has been made.
Returns:
- <Boolean>
query.selectedInclusively() // false query.select('name') query.selectedInclusively() // true
Query#setOptions(
options
)Sets query options. Some options only make sense for certain operations.
Parameters:
options
<Object>
show codeOptions:
The following options are only for
find()
:
- tailable
- sort
- limit
- skip
- maxscan
- batchSize
- comment
- snapshot
- readPreference
- hintThe following options are only for
update()
,updateOne()
,updateMany()
,replaceOne()
,findOneAndUpdate()
, andfindByIdAndUpdate()
:
- upsert
- writeConcernThe following options are only for
find()
,findOne()
,findById()
,findOneAndUpdate()
, andfindByIdAndUpdate()
:
- leanThe following options are only for all operations except
update()
,updateOne()
,updateMany()
,remove()
,deleteOne()
, anddeleteMany()
:
- maxTimeMSThe following options are for all operations
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 || {}; if ('populate' in options) { this.populate(this._mongooseOptions); } return this; } if (options == null) { return this; } if (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.
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:
val
<Number>
See:
Example
query.skip(100).limit(20)
Note
Cannot be used with
distinct()
Query#slaveOk(
v
)DEPRECATED Sets the slaveOk option.
Parameters:
v
<Boolean> defaults to true
Returns:
- <Query> this
Deprecated in MongoDB 2.2 in favor of read preferences.
Example:
query.slaveOk() // true query.slaveOk(true) query.slaveOk(false)
Query#slice(
[path]
,val
)Specifies a $slice projection for an array.
Returns:
- <Query> this
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#slice(
[path]
,[val]
)Specifies a
path
for use with chaining.Returns:
- <Query> this
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#snapshot()
Specifies this query as a
snapshot
query.Returns:
- <Query> this
See:
Example
query.snapshot() // true query.snapshot(true) query.snapshot(false)
Note
Cannot be used with
distinct()
Query#sort(
arg
)Sets the sort order
Returns:
- <Query> this
See:
show codeIf 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
// sort by "field" ascending and "test" descending query.sort({ field: 'asc', test: -1 }); // equivalent query.sort('field -test');
Note
Cannot be used with
distinct()
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:
[options]
<Object>
Returns:
See:
show codeExample
// 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 ondata
.
Example
// JSON.stringify all documents before emitting var stream = Thing.find().stream({ transform: JSON.stringify }); stream.pipe(writeStream);
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).