#
Mongoose

- home
- plugins
- change log
- support
- fork
- guide
- api docs
- quick start
- contributors
- prior releases

index.js

- Mongoose
- set
- get
- createConnection
- connect
- disconnect
- model
- plugin
- exports
- Collection
- Connection
- version
- Mongoose
- Schema
- SchemaType
- SchemaTypes
- VirtualType
- Types
- Query
- Promise
- Model
- Document
- Error
- mongo
- connection

collection.js

- Collection
- onOpen
- onClose
- addQueue
- doQueue
- ensureIndex
- findAndModify
- findOne
- find
- insert
- save
- update
- getIndexes
- mapReduce
- conn
- name

connection.js

- Connection
- open
- openSet
- error
- _open
- onOpen
- close
- onClose
- collection
- model
- setProfiling
- defaultOptions
- db
- collections
- readyState

document.js

- Document
- _buildDoc
- init
- _storeShard
- update
- set
- _set
- getValue
- setValue
- get
- _path
- markModified
- try
- modifiedPaths
- isModified
- isDirectModified
- isInit
- isSelected
- validate
- invalidate
- _reset
- _dirty
- _setSchema
- _registerHooks
- _error
- _doQueue
- toObject
- toJSON
- inspect
- toString
- equals
- errors
- isNew
- schema

drivers/node-mongodb-native/collection.js

- NativeCollection
- onOpen
- onClose
- getIndexes

drivers/node-mongodb-native/connection.js

- NativeConnection
- doOpen
- doOpenSet
- doClose

error.js

- MongooseError

errors/cast.js

- CastError

errors/document.js

- DocumentError

errors/validation.js

- ValidationError
- toString

errors/validator.js

- ValidatorError

model.js

- Model
- _getPopulationKeys
- _populate
- init
- save
- _delta
- _version
- increment
- _where
- remove
- _registerHooks
- model
- $where
- init
- ensureIndexes
- remove
- find
- _applyNamedScope
- findById
- findOne
- count
- distinct
- where
- findOneAndUpdate
- findByIdAndUpdate
- findOneAndRemove
- findByIdAndRemove
- create
- update
- mapReduce
- base
- collection
- db
- schema
- modelName
- collection
- db

namedscope.js

- decorate

promise.js

- Promise
- on
- emit
- complete
- error
- addCallback
- addErrback
- addBack
- resolve

query.js

- Query
- setOptions
- bind
- exec
- find
- cast
- _optionsForExec
- _applyPaths
- $where
- where
- equals
- or
- nor
- gt
- gte
- lt
- lte
- ne
- in
- nin
- all
- size
- regex
- maxDistance
- near
- nearSphere
- mod
- exists
- elemMatch
- box
- center
- centerSphere
- polygon
- select
- slice
- sort
- limit
- skip
- maxscan
- batchSize
- comment
- snapshot
- hint
- slaveOk
- lean
- tailable
- execFind
- findOne
- count
- distinct
- update
- _castUpdate
- _walkUpdatePath
- _castUpdateVal
- _getSchema
- remove
- findOneAndUpdate
- findOneAndRemove
- _findAndModify
- populate
- stream
- within

querystream.js

- QueryStream
- _init
- _next
- __next
- _onNextObject
- pause
- resume
- destroy
- pipe
- paused
- readable

schema/array.js

- SchemaArray
- checkRequired
- applyGetters
- cast
- castForQuery

schema/boolean.js

- SchemaBoolean
- checkRequired
- cast
- castForQuery

schema/buffer.js

- SchemaBuffer
- checkRequired
- cast
- castForQuery

schema/date.js

- SchemaDate
- checkRequired
- cast
- castForQuery

schema/documentarray.js

- DocumentArray
- doValidate
- cast

schema/mixed.js

- Mixed
- checkRequired
- cast
- castForQuery

schema/number.js

- SchemaNumber
- checkRequired
- min
- max
- cast
- castForQuery

schema/objectid.js

- ObjectId
- checkRequired
- cast
- castForQuery
- auto

schema/string.js

- SchemaString
- enum
- lowercase
- uppercase
- trim
- match
- checkRequired
- cast
- castForQuery

schema.js

- Schema
- add
- path
- eachPath
- requiredPaths
- pathType
- queue
- pre
- post
- plugin
- method
- static
- index
- set
- indexes
- virtual
- virtualpath
- namedScope
- reserved
- interpretAsType
- Types
- tree
- paths

schemadefault.js

- system.profile

schematype.js

- SchemaType
- default
- index
- unique
- sparse
- expires
- set
- get
- validate
- required
- getDefault
- applySetters
- applyGetters
- select
- doValidate
- _isRef

types/array.js

- MongooseArray
- _cast
- _markModified
- _registerAtomic
- hasAtomics
- push
- nonAtomicPush
- $pop
- pop
- $shift
- shift
- remove
- pull
- splice
- unshift
- sort
- addToSet
- toObject
- inspect
- indexOf
- _parent
- _atomics

types/buffer.js

- MongooseBuffer
- _markModified
- write
- copy
- toObject
- _parent

types/documentarray.js

- MongooseDocumentArray
- _cast
- id
- toObject
- inspect
- create
- notify

types/embedded.js

- EmbeddedDocument
- markModified
- save
- remove
- update
- inspect
- invalidate
- ownerDocument
- parent
- parentArray

types/objectid.js

- ObjectId
- fromString
- toString

utils.js

- toCollectionName
- pluralization
- uncountables
- deepEqual
- clone
- options
- random
- merge
- args
- tick
- isMongooseObject
- expires

virtualtype.js

- VirtualType
- get
- set
- applyGetters
- applySetters

private

- index.js

  ### Mongoose()

  Mongoose constructor.

  show code

      function Mongoose () {
        this.connections = [];
        this.plugins = [];
        this.models = {};
        this.modelSchemas = {};
        this.options = {};
        this.createConnection(); // default connection
      };

  The exports object of the `mongoose` module is an instance of this class.
  Most apps will only use this one instance.

  ### Mongoose#set(`key`, `value`)

  Sets mongoose options

  show code

      Mongoose.prototype.set = function (key, value) {
        if (arguments.length == 1)
          return this.options[key];
        this.options[key] = value;
        return this;
      };

  #### Parameters:

  - `key` <String>
  - `value` <String>

  #### Example:

      mongoose.set('test', value) // sets the 'test' option to `value`

  ### Mongoose#get(`key`)

  Gets mongoose options

  #### Parameters:

  - `key` <String>

  #### Example:

      mongoose.get('test') // returns the 'test' value

  ### Mongoose#createConnection(`[uri]`)

  Creates a Connection instance.

  show code

      Mongoose.prototype.createConnection = function () {
        var conn = new Connection(this);
        this.connections.push(conn);

        if (arguments.length) {
          if (rgxReplSet.test(arguments[0])) {
            conn.openSet.apply(conn, arguments);
          } else {
            conn.open.apply(conn, arguments);
          }
        }

        return conn;
      };

  #### Parameters:

  - `[uri]` <String> a mongodb:// URI

  #### Returns:

  - <Connection> the created Connection object

  #### Example:

      // with mongodb:// URI
      db = mongoose.createConnection('mongodb://localhost:port/database');

      // replica sets
      db = mongoose.createConnection('mongodb://localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');

      // with [host, database_name[, port] signature
      db = mongoose.createConnection('localhost', 'database', port)

      // initialize now, connect later
      db = mongoose.createConnection();
      db.open('localhost', 'database', port);

  ### Mongoose#connect()

  Opens the default mongoose connection.

  show code

      Mongoose.prototype.connect = function () {
        var conn = this.connection;

        if (rgxReplSet.test(arguments[0])) {
          conn.openSet.apply(conn, arguments);
        } else {
          conn.open.apply(conn, arguments);
        }

        return this;
      };

  #### Returns:

  - <Mongoose> this

  #### See:

  - Mongoose#createConnection

  If arguments are passed, they are proxied to either Connection#open or Connection#openSet appropriately.

  ### Mongoose#disconnect(`[fn]`)

  Disconnects all connections.

  show code

      Mongoose.prototype.disconnect = function (fn) {
        var count = this.connections.length
          , error

        this.connections.forEach(function(conn){
          conn.close(function(err){
            if (error) return;

            if (err) {
              error = err;
              if (fn) return fn(err);
              throw err;
            }

            if (fn)
              --count || fn();
          });
        });
        return this;
      };

  #### Parameters:

  - `[fn]` <Function> called after all connection close.

  #### Returns:

  - <Mongoose> this

  ### Mongoose#model(`name`, `[schema]`, `[collection]`, `[skipInit]`)

  Defines a model or retrieves it.

  show code

      Mongoose.prototype.model = function (name, schema, collection, skipInit) {
        // normalize collection
        if (!(schema instanceof Schema)) {
          collection = schema;
          schema = false;
        }

        if ('boolean' === typeof collection) {
          skipInit = collection;
          collection = null;
        }

        // look up models for the collection
        if (!this.modelSchemas[name]) {
          if (!schema && name in SchemaDefaults) {
            schema = SchemaDefaults[name];
          }

          if (schema) {
            this.modelSchemas[name] = schema;
            for (var i = 0, l = this.plugins.length; i < l; i++) {
              schema.plugin(this.plugins[i][0], this.plugins[i][1]);
            }
          } else {
            throw new Error('Schema hasn\'t been registered for model "' + name + '".
      '
                          + 'Use mongoose.model(name, schema)');
          }
        }

        if (!this.models[name]) {
          schema || (schema = this.modelSchemas[name]);
          collection || (collection = schema.set('collection') || format(name));

          var model = Model.compile(name
                              , this.modelSchemas[name]
                              , collection
                              , this.connection
                              , this);

          if (!skipInit) model.init();

          this.models[name] = model;
        }

        return this.models[name];
      };

  #### Parameters:

  - `name` <String> model name
  - `[schema]` <Schema>
  - `[collection]` <String> name (optional, induced from model name)
  - `[skipInit]` <Boolean> whether to skip initialization (defaults to false)

  Models defined on the `mongoose` instance are available to all connection created by the same `mongoose` instance.

  #### Example:

      var mongoose = require('mongoose');

      // define an Actor model with this mongoose instance
      mongoose.model('Actor', new Schema({ name: String }));

      // create a new connection
      var conn = mongoose.createConnection(..);

      // retrieve the Actor model
      var Actor = conn.model('Actor');

  When no `collection` argument is passed, Mongoose produces a collection name by passing the model `name` to the utils.toCollectionName method. This method pluralizes the name. Collection names can also be declared through schema options.

  #### Example:

      var schema = new Schema({ name: String });
      schema.set('collection', 'actor');

  ### Mongoose#plugin(`fn`, `[opts]`)

  Declares a global plugin executed on all Schemas.

  show code

      Mongoose.prototype.plugin = function (fn, opts) {
        this.plugins.push([fn, opts]);
        return this;
      };

  #### Parameters:

  - `fn` <Function> plugin callback
  - `[opts]` <Object> optional options

  #### Returns:

  - <Mongoose> this

  Equivalent to calling `.plugin(fn)` on each Schema you create.

  ### module.exports

  The exports object is an instance of Mongoose.

  show code

      module.exports = exports = new Mongoose;
      var mongoose = module.exports;

  ### mongoose.Collection

  The Mongoose Collection constructor

  show code

      mongoose.Collection = Collection;

  ### mongoose.Connection

  The Mongoose Connection constructor

  show code

      mongoose.Connection = Connection;

  ### mongoose.version

  Mongoose version

  show code

      mongoose.version = JSON.parse(
        require('fs').readFileSync(__dirname + '/../package.json', 'utf8')
      ).version;

  ### mongoose.Mongoose

  The Mongoose constructor

  show code

      mongoose.Mongoose = Mongoose;

  The exports of the mongoose module is an instance of this class.

  #### Example:

      var mongoose = require('mongoose');
      var mongoose2 = new mongoose.Mongoose();

  ### mongoose.Schema

  The Mongoose Schema constructor

  show code

      mongoose.Schema = Schema;

  #### Example:

      var mongoose = require('mongoose');
      var Schema = mongoose.Schema;
      var CatSchema = new Schema(..);

  ### mongoose.SchemaType

  The Mongoose SchemaType constructor.

  show code

      mongoose.SchemaType = SchemaType;

  ### mongoose.SchemaTypes

  The various Mongoose SchemaTypes.

  show code

      mongoose.SchemaTypes = Schema.Types;

  #### See:

  - Schema.SchemaTypes

  #### Note:

  Alias of mongoose.Schema.Types for backwards compatibility.

  ### mongoose.VirtualType

  The Mongoose VirtualType constructor.

  show code

      mongoose.VirtualType = VirtualType;

  ### mongoose.Types

  The various Mongoose Types.

  show code

      mongoose.Types = Types;

  #### Example:

      var mongoose = require('mongoose');
      var array = mongoose.Types.Array;

  #### Types:

  - Array
  - Buffer
  - Document
  - Embedded
  - DocumentArray
  - ObjectId

  Using this exposed access to the `ObjectId` type, we can construct ids on demand.

      var ObjectId = mongoose.Types.ObjectId;
      var id1 = new ObjectId;

  ### mongoose.Query

  The Mongoose Query constructor.

  show code

      mongoose.Query = Query;

  ### mongoose.Promise

  The Mongoose Promise constructor.

  show code

      mongoose.Promise = Promise;

  ### mongoose.Model

  The Mongoose Model constructor.

  show code

      mongoose.Model = Model;

  ### mongoose.Document

  The Mongoose Document constructor.

  show code

      mongoose.Document = Document;

  ### mongoose.Error

  The MongooseError constructor.

  show code

      mongoose.Error = require('./error');

  ### mongoose.mongo

  The node-mongodb-native driver Mongoose uses.

  show code

      mongoose.mongo = require('mongodb');

  ### Mongoose#connection

  The default connection of the mongoose module.

  #### Example:

      var mongoose = require('mongoose');
      mongoose.connect(...);
      mongoose.connection.on('error', cb);

  This is the connection used by default for every model created using mongoose.model.

  #### Returns:

  - <Connection>

- collection.js

  ### Collection(`name`, `conn`, `opts`)

  Abstract Collection constructor

  show code

      function Collection (name, conn, opts) {
        this.name = name;
        this.conn = conn;
        this.buffer = true;
        this.queue = [];

        if ('number' == typeof opts) opts = { size: opts };
        this.opts = opts || {};

        if (STATES.connected == this.conn.readyState) {
          this.onOpen();
        }
      };

  #### Parameters:

  - `name` <String> name of the collection
  - `conn` <Connection> A MongooseConnection instance
  - `opts` <Object> optional collection options

  This is the base class that drivers inherit from and implement.

  ### Collection#onOpen()

  Called when the database connects

  show code

      Collection.prototype.onOpen = function () {
        var self = this;
        this.buffer = false;
        self.doQueue();
      };

  ### Collection#onClose()

  Called when the database disconnects

  show code

      Collection.prototype.onClose = function () {
        this.buffer = true;
      };

  ### Collection#addQueue(`name`, `args`)

  Queues a method for later execution when its
  database connection opens.

  show code

      Collection.prototype.addQueue = function (name, args) {
        this.queue.push([name, args]);
        return this;
      };

  #### Parameters:

  - `name` <String> name of the method to queue
  - `args` <Array> arguments to pass to the method when executed

  ### Collection#doQueue()

  Executes all queued methods and clears the queue.

  show code

      Collection.prototype.doQueue = function () {
        for (var i = 0, l = this.queue.length; i < l; i++){
          this[this.queue[i][0]].apply(this, this.queue[i][1]);
        }
        this.queue = [];
        return this;
      };

  ### Collection#ensureIndex()

  Abstract method that drivers must implement.

  show code

      Collection.prototype.ensureIndex = function(){
        throw new Error('Collection#ensureIndex unimplemented by driver');
      };

  ### Collection#findAndModify()

  Abstract method that drivers must implement.

  show code

      Collection.prototype.findAndModify = function(){
        throw new Error('Collection#findAndModify unimplemented by driver');
      };

  ### Collection#findOne()

  Abstract method that drivers must implement.

  show code

      Collection.prototype.findOne = function(){
        throw new Error('Collection#findOne unimplemented by driver');
      };

  ### Collection#find()

  Abstract method that drivers must implement.

  show code

      Collection.prototype.find = function(){
        throw new Error('Collection#find unimplemented by driver');
      };

  ### Collection#insert()

  Abstract method that drivers must implement.

  show code

      Collection.prototype.insert = function(){
        throw new Error('Collection#insert unimplemented by driver');
      };

  ### Collection#save()

  Abstract method that drivers must implement.

  show code

      Collection.prototype.save = function(){
        throw new Error('Collection#save unimplemented by driver');
      };

  ### Collection#update()

  Abstract method that drivers must implement.

  show code

      Collection.prototype.update = function(){
        throw new Error('Collection#update unimplemented by driver');
      };

  ### Collection#getIndexes()

  Abstract method that drivers must implement.

  show code

      Collection.prototype.getIndexes = function(){
        throw new Error('Collection#getIndexes unimplemented by driver');
      };

  ### Collection#mapReduce()

  Abstract method that drivers must implement.

  show code

      Collection.prototype.mapReduce = function(){
        throw new Error('Collection#mapReduce unimplemented by driver');
      };

  ### Collection#conn

  The Connection instance

  ### Collection#name

  The collection name

- connection.js

  ### Connection(`base`)

  Connection constructor

  show code

      function Connection (base) {
        this.base = base;
        this.collections = {};
        this.models = {};
        this.replica = false;
        this.host = null;
        this.port = null;
        this.user = null;
        this.pass = null;
        this.name = null;
        this.options = null;
        this._readyState = STATES.disconnected;
        this._closeCalled = false;
        this._hasOpened = false;
      };

  #### Parameters:

  - `base` <Mongoose> a mongoose instance

  #### Inherits:

  - NodeJS EventEmitter

  #### Events:

  - `connecting`: Emitted when `connection.{open,openSet}()` is executed on this connection.

  - `connected`: Emitted when this connection successfully connects to the db. May be emitted multiple times in `reconnected` scenarios.

  - `open`: Emitted after we `connected` and `onOpen` is executed on all of this connections models.

  - `disconnecting`: Emitted when `connection.close()` was executed.

  - `disconnected`: Emitted after getting disconnected from the db.

  - `close`: Emitted after we `disconnected` and `onClose` executed on all of this connections models.

  - `reconnected`: Emitted after we `connected` and subsequently `disconnected`, followed by successfully another successfull connection.

  - `error`: Emitted when an error occurs on this connection.

  - `fullsetup`: Emitted in a replica-set scenario, when all nodes specified in the connection string are connected.

  For practical reasons, a Connection equals a Db.

  ### Connection#open(`connection_string`, `[database]`, `[port]`, `[options]`, `[callback]`)

  Opens the connection to MongoDB.

  show code

      Connection.prototype.open = function (host, database, port, options, callback) {
        var self = this
          , uri;

        if ('string' === typeof database) {
          switch (arguments.length) {
            case 2:
              port = 27017;
            case 3:
              switch (typeof port) {
                case 'function':
                  callback = port, port = 27017;
                  break;
                case 'object':
                  options = port, port = 27017;
                  break;
              }
              break;
            case 4:
              if ('function' === typeof options)
                callback = options, options = {};
          }
        } else {
          switch (typeof database) {
            case 'function':
              callback = database, database = undefined;
              break;
            case 'object':
              options = database;
              database = undefined;
              callback = port;
              break;
          }

          if (!rgxProtocol.test(host)) {
            host = 'mongodb://' + host;
          }

          uri = url.parse(host);
          host = uri.hostname;
          port = uri.port || 27017;
          database = uri.pathname && uri.pathname.replace(/\//g, '');
        }

        this.options = this.defaultOptions(options);

        // make sure we can open
        if (STATES.disconnected !== this.readyState) {
          var err = new Error('Trying to open unclosed connection.');
          err.state = this.readyState;
          this.error(err, callback);
          return this;
        }

        if (!host) {
          this.error(new Error('Missing connection hostname.'), callback);
          return this;
        }

        if (!database) {
          this.error(new Error('Missing connection database.'), callback);
          return this;
        }

        // handle authentication
        if (uri && uri.auth) {
          var auth = uri.auth.split(':');
          this.user = auth[0];
          this.pass = auth[1];

        // Check hostname for user/pass
        } else if (/@/.test(host) && /:/.test(host.split('@')[0])) {
          host = host.split('@');
          var auth = host.shift().split(':');
          host = host.pop();
          this.user = auth[0];
          this.pass = auth[1];

        // user/pass options
        } else if (options && options.user && options.pass) {
          this.user = options.user;
          this.pass = options.pass;

        } else {
          this.user = this.pass = undefined;
        }

        this.name = database;
        this.host = host;
        this.port = port;

        this._open(callback);
        return this;
      };

  #### Parameters:

  - `connection_string` <String> mongodb://uri or the host to which you are connecting
  - `[database]` <String> database name
  - `[port]` <Number> database port
  - `[options]` <Object> options
  - `[callback]` <Function>

  #### See:

  - node-mongodb-native

  `options` is a hash with the following possible properties:

      db      - passed to the connection db instance
      server  - passed to the connection server instance(s)
      replset - passed to the connection ReplSetServer instance
      user    - username for authentication
      pass    - password for authentication

  #### Notes:

  Mongoose forces the db option `forceServerObjectId` false and cannot be overridden.
  Mongoose defaults the server `auto_reconnect` options to true which can be overridden.
  See the node-mongodb-native driver instance for options that it understands.

  ### Connection#openSet(`uris`, `[database]`, `[options]`, `[callback]`)

  Connects to a replica set.

  show code

      Connection.prototype.openSet = function (uris, database, options, callback) {
        var uris = uris.split(',')
          , self = this;

        switch (arguments.length) {
          case 3:
            this.name = database;
            if ('function' === typeof options) callback = options, options = {};
            break;
          case 2:
            switch (typeof database) {
              case 'string':
                this.name = database;
              case 'function':
                callback = database, database = null;
                break;
              case 'object':
                options = database, database = null;
                break;
            }
        }

        this.options = options = this.defaultOptions(options);

        if (uris.length < 2) {
          this.error(new Error('Please provide comma-separated URIs'), callback);
          return this;
        }

        this.replica = true;
        this.host = [];
        this.port = [];

        uris.forEach(function (uri) {
          // handle missing protocols
          if (!rgxProtocol.test(uri))
            uri = 'mongodb://' + uri;

          var uri = url.parse(uri);

          self.host.push(uri.hostname);
          self.port.push(uri.port || 27017);

          if (!self.name && uri.pathname && uri.pathname.replace(/\//g, ''))
            self.name = uri.pathname.replace(/\//g, '');

          if (!self.user && uri.auth) {
            var auth = uri.auth.split(':');
            self.user = auth[0];
            self.pass = auth[1];
          }
        });

        if (!this.name) {
          this.error(new Error('No database name provided for replica set'), callback);
          return this;
        }

        this._open(callback);
        return this;
      };

  #### Parameters:

  - `uris` <String> comma-separated mongodb:// `URI`s
  - `[database]` <String> database name if not included in `uris`
  - `[options]` <Object> passed to the internal driver
  - `[callback]` <Function>

  #### See:

  - node-mongodb-native

  #### Example:

      var db = mongoose.createConnection();
      db.openSet("mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019");

  The database name and/or auth need only be included in one URI.
  The `options` are passed to the internal driver connection object.

  ### Connection#error(`err`, `callback`)

  error

  show code

      Connection.prototype.error = function (err, callback) {
        if (callback) return callback(err);
        this.emit('error', err);
      }

  #### Parameters:

  - `err` <Error>
  - `callback` <Function> optional

  Graceful error handling, passes error to callback
  if available, else emits error on the connection.

  ### Connection#_open(`callback`)

  Handles opening the connection with the appropriate method based on connection type.

  show code

      Connection.prototype._open = function (callback) {
        this.readyState = STATES.connecting;
        this._closeCalled = false;

        var self = this;

        var method = this.replica
          ? 'doOpenSet'
          : 'doOpen';

        // open connection
        this[method](function (err) {
          if (err) {
            self.readyState = STATES.disconnected;
            if (self._hasOpened) {
              if (callback) callback(err);
            } else {
              self.error(err, callback);
            }
            return;
          }

          self.onOpen();
          callback && callback();
        });
      }

  #### Parameters:

  - `callback` <Function>

  ### Connection#onOpen()

  Called when the connection is opened

  show code

      Connection.prototype.onOpen = function () {
        var self = this;

        function open () {
          self.readyState = STATES.connected;

          // avoid having the collection subscribe to our event emitter
          // to prevent 0.3 warning
          for (var i in self.collections)
            self.collections[i].onOpen();

          self.emit('open');
        };

        // re-authenticate
        if (self.user && self.pass)
          self.db.authenticate(self.user, self.pass, open);
        else
          open();
      };

  ### Connection#close(`[callback]`)

  Closes the connection

  show code

      Connection.prototype.close = function (callback) {
        var self = this;
        this._closeCalled = true;

        switch (this.readyState){
          case 0: // disconnected
            callback && callback();
            break;

          case 1: // connected
            this.readyState = STATES.disconnecting;
            this.doClose(function(err){
              if (err){
                self.error(err, callback);
              } else {
                self.onClose();
                callback && callback();
              }
            });
            break;

          case 2: // connecting
            this.once('open', function(){
              self.close(callback);
            });
            break;

          case 3: // disconnecting
            if (!callback) break;
            this.once('close', function () {
              callback();
            });
            break;
        }

        return this;
      };

  #### Parameters:

  - `[callback]` <Function> optional

  #### Returns:

  - <Connection> self

  ### Connection#onClose()

  Called when the connection closes

  show code

      Connection.prototype.onClose = function () {
        this.readyState = STATES.disconnected;

        // avoid having the collection subscribe to our event emitter
        // to prevent 0.3 warning
        for (var i in this.collections)
          this.collections[i].onClose();

        this.emit('close');
      };

  ### Connection#collection(`name`, `[options]`)

  Retrieves a collection, creating it if not cached.

  show code

      Connection.prototype.collection = function (name, options) {
        if (!(name in this.collections))
          this.collections[name] = new Collection(name, this, options);
        return this.collections[name];
      };

  #### Parameters:

  - `name` <String> of the collection
  - `[options]` <Object> optional collection options

  #### Returns:

  - <Collection> collection instance

  ### Connection#model(`name`, `[schema]`, `[collection]`)

  Defines or retrieves a model.

  show code

      Connection.prototype.model = function (name, schema, collection) {
        if (!this.models[name]) {
          var model = this.base.model(name, schema, collection, true)
            , Model

          if (this != model.prototype.db) {
            // subclass model using this connection and collection name
            Model = function Model (doc, fields, skipId) {
              if (!(this instanceof Model))
                return new Model(doc, fields, skipId);
              model.call(this, doc, fields, skipId);
            };

            Model.__proto__ = model;
            Model.prototype.__proto__ = model.prototype;
            Model.db = Model.prototype.db = this;

            // collection name discovery
            if ('string' === typeof schema) {
              collection = schema;
            }

            if (!collection) {
              collection = model.prototype.schema.set('collection') || utils.toCollectionName(name);
            }

            var s = 'string' != typeof schema
              ? schema
              : model.prototype.schema;

            Model.prototype.collection = this.collection(collection, s && s.options.capped);
            Model.collection = Model.prototype.collection;
            Model.init();
          }

          this.models[name] = Model || model;
        }

        return this.models[name];
      };

  #### Parameters:

  - `name` <String> the model name
  - `[schema]` <Schema> a schema. necessary when defining a model
  - `[collection]` <String> name of mongodb collection (optional) if not given it will be induced from model name

  #### Returns:

  - <Model> The compiled model

  #### See:

  - Mongoose#model

      var mongoose = require('mongoose');
      var db = mongoose.createConnection(..);
      db.model('Venue', new Schema(..));
      var Ticket = db.model('Ticket', new Schema(..));
      var Venue = db.model('Venue');

  ### Connection#setProfiling(`level`, `[ms]`, `callback`)

  Set profiling level.

  show code

      Connection.prototype.setProfiling = function (level, ms, callback) {
        if (STATES.connected !== this.readyState) {
          return this.on('open', this.setProfiling.bind(this, level, ms, callback));
        }

        if (!callback) callback = ms, ms = 100;

        var cmd = {};

        switch (level) {
          case 0:
          case 'off':
            cmd.profile = 0;
            break;
          case 1:
          case 'slow':
            cmd.profile = 1;
            if ('number' !== typeof ms) {
              ms = parseInt(ms, 10);
              if (isNaN(ms)) ms = 100;
            }
            cmd.slowms = ms;
            break;
          case 2:
          case 'all':
            cmd.profile = 2;
            break;
          default:
            return callback(new Error('Invalid profiling level: '+ level));
        }

        this.db.executeDbCommand(cmd, function (err, resp) {
          if (err) return callback(err);

          var doc = resp.documents[0];

          err = 1 === doc.ok
            ? null
            : new Error('Could not set profiling level to: '+ level)

          callback(err, doc);
        });
      };

  #### Parameters:

  - `level` <Number, String> either off (0), slow (1), or all (2)
  - `[ms]` <Number> the threshold in milliseconds above which queries will be logged when in `slow` mode. defaults to 100.
  - `callback` <Function>

  ### Connection#defaultOptions(`options`)

  Prepares default connection options.

  show code

      Connection.prototype.defaultOptions = function (options) {
        var o = options || {};

        o.server = o.server || {};

        if (!('auto_reconnect' in o.server)) {
          o.server.auto_reconnect = true;
        }

        o.db = o.db || {};
        o.db.forceServerObjectId = false;

        return o;
      }

  #### Parameters:

  - `options` <Object>

  ### Connection#db

  The mongodb.Db instance, set when the connection is opened

  ### Connection#collections

  A hash of the collections associated with this connection

  ### Connection#readyState

  Connection ready state

  - 0 = disconnected
  - 1 = connected
  - 2 = connecting
  - 3 = disconnecting

  Each state change emits its associated event name.

  #### Example

      conn.on('connected', callback);
      conn.on('disconnected', callback);

- document.js

  ### Document(`obj`, `[fields]`, `[skipId]`)

  Document constructor.

  show code

      function Document (obj, fields, skipId) {
        // node <0.4.3 bug
        if (!this._events) this._events = {};
        this.setMaxListeners(0);

        if ('boolean' === typeof fields) {
          this._strictMode = fields;
          this._selected = fields = undefined;
        } else {
          this._strictMode = this.schema.options && this.schema.options.strict;
          this._selected = fields;
        }

        this.isNew = true;
        this.errors = undefined;
        this._shardval = undefined;
        this._saveError = undefined;
        this._validationError = undefined;
        this._adhocPaths = undefined;
        this._removing = undefined;
        this._inserting = undefined;
        this.__version = undefined;
        this.__getters = {};
        this.__id = undefined;

        this._activePaths = new ActiveRoster;

        var required = this.schema.requiredPaths();
        for (var i = 0; i < required.length; ++i) {
          this._activePaths.require(required[i]);
        }

        this._doc = this._buildDoc(obj, fields, skipId);
        if (obj) this.set(obj, undefined, true);
        this._registerHooks();
      };

  #### Parameters:

  - `obj` <Object> the values to set
  - `[fields]` <Object> the fields which were selected in the query returning this document
  - `[skipId]` <Boolean> bool, should we auto create an ObjectId _id

  #### Inherits:

  - NodeJS EventEmitter

  #### Events:

  - `init`: Emitted on a document after it has was retreived from the db and fully hydrated by Mongoose.

  - `save`: Emitted when the document is successfully saved

  ### Document#_buildDoc(`obj`, `[fields]`, `[skipId]`)

  Builds the default doc structure

  show code

      Document.prototype._buildDoc = function (obj, fields, skipId) {
        var doc = {}
          , self = this
          , exclude
          , keys
          , key
          , ki

        // determine if this doc is a result of a query with
        // excluded fields
        if (fields && 'Object' === fields.constructor.name) {
          keys = Object.keys(fields);
          ki = keys.length;

          while (ki--) {
            if ('_id' !== keys[ki]) {
              exclude = 0 === fields[keys[ki]];
              break;
            }
          }
        }

        var paths = Object.keys(this.schema.paths)
          , plen = paths.length
          , ii = 0

        for (; ii < plen; ++ii) {
          var p = paths[ii];

          if ('_id' == p) {
            if (skipId) continue;
            if (obj && '_id' in obj) continue;
          }

          var type = this.schema.paths[p]
            , path = p.split('.')
            , len = path.length
            , last = len-1
            , doc_ = doc
            , i = 0

          for (; i < len; ++i) {
            var piece = path[i]
              , def

            if (i === last) {
              if (fields) {
                if (exclude) {
                  // apply defaults to all non-excluded fields
                  if (p in fields) continue;

                  def = type.getDefault(self, true);
                  if ('undefined' !== typeof def) {
                    doc_[piece] = def;
                    self._activePaths.default(p);
                  }

                } else if (p in fields) {
                  // selected field
                  def = type.getDefault(self, true);
                  if ('undefined' !== typeof def) {
                    doc_[piece] = def;
                    self._activePaths.default(p);
                  }
                }
              } else {
                def = type.getDefault(self, true);
                if ('undefined' !== typeof def) {
                  doc_[piece] = def;
                  self._activePaths.default(p);
                }
              }
            } else {
              doc_ = doc_[piece] || (doc_[piece] = {});
            }
          }
        };

        return doc;
      };

  #### Parameters:

  - `obj` <Object>
  - `[fields]` <Object>
  - `[skipId]` <Boolean>

  #### Returns:

  - <Object>

  ### Document#init(`doc`, `fn`)

  Initializes the document without setters or marking anything modified.

  show code

      Document.prototype.init = function (doc, fn) {
        this.isNew = false;

        init(this, doc, this._doc);
        this._storeShard();

        this.emit('init');
        if (fn) fn(null);
        return this;
      };

  #### Parameters:

  - `doc` <Object> document returned by mongo
  - `fn` <Function> callback

  Called internally after a document is returned from mongodb.

  ### Document#_storeShard()

  Stores the current values of the shard keys.

  show code

      Document.prototype._storeShard = function _storeShard () {
        // backwards compat
        var key = this.schema.options.shardKey || this.schema.options.shardkey;
        if (!(key && 'Object' == key.constructor.name)) return;

        var orig = this._shardval = {}
          , paths = Object.keys(key)
          , len = paths.length
          , val

        for (var i = 0; i < len; ++i) {
          val = this.getValue(paths[i]);
          if (isMongooseObject(val)) {
            orig[paths[i]] = val.toObject({ depopulate: true })
          } else if (null != val && val.valueOf) {
            orig[paths[i]] = val.valueOf();
          } else {
            orig[paths[i]] = val;
          }
        }
      }

  #### Note:

  Shard key values do not / are not allowed to change.

  ### Document#update(`doc`, `options`, `callback`)

  Sends an update command with this document `_id` as the query selector.

  show code

      Document.prototype.update = function update () {
        var args = utils.args(arguments);
        args.unshift({_id: this._id});
        this.constructor.update.apply(this.constructor, args);
      }

  #### Parameters:

  - `doc` <Object>
  - `options` <Object>
  - `callback` <Function>

  #### Returns:

  - <Query>

  #### Example:

      weirdCar.update({$inc: {wheels:1}, { safe: true }, callback);

  #### Valid options:

  - `safe` safe mode (defaults to value set in schema (true))
  - `upsert` (boolean) whether to create the doc if it doesn't match (false)

  ### Document#set(`path`, `val`, `[type]`)

  Sets the value of a path, or many paths.

  show code

      Document.prototype.set = function (path, val, type) {
        var constructing = true === type
          , adhoc = type && true !== type
          , adhocs

        if (adhoc) {
          adhocs = this._adhocPaths || (this._adhocPaths = {});
          adhocs[path] = Schema.interpretAsType(path, type);
        }

        if ('string' !== typeof path) {
          // new Document({ key: val })

          if (null === path || undefined === path) {
            var _ = path;
            path = val;
            val = _;

          } else {
            var prefix = val
              ? val + '.'
              : '';

            if (path instanceof Document) path = path._doc;

            var keys = Object.keys(path)
              , i = keys.length
              , pathtype
              , key

            while (i--) {
              key = keys[i];
              if (null != path[key] && 'Object' === path[key].constructor.name
                && !(this._path(prefix + key) instanceof MixedSchema)) {
                this.set(path[key], prefix + key, constructing);
              } else if (this._strictMode) {
                pathtype = this.schema.pathType(prefix + key);
                if ('real' === pathtype || 'virtual' === pathtype) {
                  this.set(prefix + key, path[key], constructing);
                } else if ('throw' == this._strictMode) {
                  throw new Error("Field `" + key + "` is not in schema.");
                }
              } else if (undefined !== path[key]) {
                this.set(prefix + key, path[key], constructing);
              }
            }

            return this;
          }
        }

        // ensure _strict is honored for obj props
        // docschema = new Schema({ path: { nest: 'string' }})
        // doc.set('path', obj);
        var pathType = this.schema.pathType(path);
        if ('nested' == pathType && val && 'Object' == val.constructor.name) {
          this.set(val, path, constructing);
          return this;
        }

        var schema;
        if ('adhocOrUndefined' == pathType && this._strictMode) {
          return this;
        } else if ('virtual' == pathType) {
          schema = this.schema.virtualpath(path);
          schema.applySetters(val, this);
          return this;
        } else {
          schema = this._path(path);
        }

        var parts = path.split('.')
          , pathToMark

        // When using the $set operator the path to the field must already exist.
        // Else mongodb throws: "LEFT_SUBFIELD only supports Object"

        if (parts.length <= 1) {
          pathToMark = path;
        } else {
          for (var i = 0; i < parts.length; ++i) {
            var part = parts[i];
            var subpath = parts.slice(0, i).concat(part).join('.');
            if (this.isDirectModified(subpath) // earlier prefixes that are already
                                               // marked as dirty have precedence
                || this.get(subpath) === null) {
              pathToMark = subpath;
              break;
            }
          }

          if (!pathToMark) pathToMark = path;
        }

        if (!schema || null === val || undefined === val) {
          this._set(pathToMark, path, constructing, parts, schema, val);
          return this;
        }

        var self = this;

        // if this doc is being constructed we should not
        // trigger getters.
        var priorVal = constructing
          ? undefined
          : this.get(path);

        var shouldSet = this.try(function(){
          var casted = schema.cast(val, self, false, priorVal);
          val = schema.applySetters(casted, self);
        });

        if (shouldSet) {
          this._set(pathToMark, path, constructing, parts, schema, val, priorVal);
        }

        return this;
      }

  #### Parameters:

  - `path` <String, Object> path or object of key/vals to set
  - `val` <Any> the value to set
  - `[type]` <Schema, String, Number, Buffer, etc..> optionally specify a type for "on-the-fly" attributes

  #### Example:

      // path, value
      doc.set(path, value)

      // object
      doc.set({
          path  : value
        , path2 : {
             path  : value
          }
      })

      // only-the-fly cast to number
      doc.set(path, value, Number)

      // only-the-fly cast to string
      doc.set(path, value, String)

  ### Document#_set()

  Handles the actual setting of the value and marking the path modified if appropriate.

  show code

      Document.prototype._set = function (pathToMark, path, constructing, parts, schema, val, priorVal) {
        if (this.isNew) {
          this.markModified(pathToMark);
        } else {

          priorVal || (priorVal = this.get(path));

          if (!this.isDirectModified(pathToMark)) {
            if (undefined === val && !this.isSelected(path)) {
              // special case:
              // when a path is not selected in a query its initial
              // value will be undefined.
              this.markModified(pathToMark, priorVal);
            } else if (undefined === val && path in this._activePaths.states.default) {
              // do nothing
              // unsetting the default value which was never saved
            } else if (!deepEqual(val, priorVal)) {
              this.markModified(pathToMark, priorVal);
            } else if (!constructing &&
                       null != val &&
                       path in this._activePaths.states.default &&
                       deepEqual(val, schema.getDefault(this, constructing))) {
              // special case:
              // a path with a default was $unset on the server
              // and the user is setting it to the same value again
              this.markModified(pathToMark, priorVal);
            }
          }
        }

        var obj = this._doc
          , i = 0
          , l = parts.length

        for (; i < l; i++) {
          var next = i + 1
            , last = next === l;

          if (last) {
            obj[parts[i]] = val;
          } else {
            if (obj[parts[i]] && 'Object' === obj[parts[i]].constructor.name) {
              obj = obj[parts[i]];
            } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {
              obj = obj[parts[i]];
            } else {
              obj = obj[parts[i]] = {};
            }
          }
        }
      };

  ### Document#getValue(`path`)

  Gets a raw value from a path (no getters)

  show code

      Document.prototype.getValue = function (path) {
        var parts = path.split('.')
          , obj = this._doc
          , part;

        for (var i = 0, l = parts.length; i < l; i++) {
          part = parts[i];
          obj = obj.getValue
              ? obj.getValue(part) // If we have an embedded array document member
              : obj[part];
          if (!obj) return obj;
        }

        return obj;
      }

  #### Parameters:

  - `path` <String>

  ### Document#setValue(`path`, `value`)

  Sets a raw value for a path (no casting, setters, transformations)

  show code

      Document.prototype.setValue = function (path, val) {
        var parts = path.split('.')
          , obj = this._doc;

        for (var i = 0, len = parts.length-1; i < len; i++) {
          obj = obj[parts[i]];
        }

        obj[parts[len]] = val;
        return this;
      };

  #### Parameters:

  - `path` <String>
  - `value` <Object>

  ### Document#get(`path`, `[type]`)

  Returns the value of a path.

  show code

      Document.prototype.get = function (path, type) {
        var adhocs;
        if (type) {
          adhocs = this._adhocPaths || (this._adhocPaths = {});
          adhocs[path] = Schema.interpretAsType(path, type);
        }

        var schema = this._path(path) || this.schema.virtualpath(path)
          , pieces = path.split('.')
          , obj = this._doc;

        for (var i = 0, l = pieces.length; i < l; i++) {
          obj = null == obj ? null : obj[pieces[i]];
        }

        if (schema) {
          obj = schema.applyGetters(obj, this);
        }

        return obj;
      };

  #### Parameters:

  - `path` <String>
  - `[type]` <Schema, String, Number, Buffer, etc..> optionally specify a type for on-the-fly attributes

  #### Example

      // path
      doc.get('age') // 47

      // dynamic casting to a string
      doc.get('age', String) // "47"

  ### Document#_path(`path`)

  Returns the schematype for the given `path`.

  show code

      Document.prototype._path = function (path) {
        var adhocs = this._adhocPaths
          , adhocType = adhocs && adhocs[path];

        if (adhocType) {
          return adhocType;
        } else {
          return this.schema.path(path);
        }
      };

  #### Parameters:

  - `path` <String>

  ### Document#markModified(`path`)

  Marks the path as having pending changes to write to the db.

  show code

      Document.prototype.markModified = function (path) {
        this._activePaths.modify(path);
      };

  #### Parameters:

  - `path` <String> the path to mark modified

  Very helpful when using Mixed types.

  #### Example:

      doc.mixed.type = 'changed';
      doc.markModified('mixed.type');
      doc.save() // changes to mixed.type are now persisted

  ### Document#try(`fn`, `scope`)

  Catches errors that occur during execution of `fn` and stores them to later be passed when `save()` is executed.

  show code

      Document.prototype.try = function (fn, scope) {
        var res;
        try {
          fn.call(scope);
          res = true;
        } catch (e) {
          this._error(e);
          res = false;
        }
        return res;
      };

  #### Parameters:

  - `fn` <Function> function to execute
  - `scope` <Object> the scope with which to call fn

  ### Document#modifiedPaths()

  Returns the list of paths that have been modified.

  show code

      Document.prototype.modifiedPaths = function () {
        var directModifiedPaths = Object.keys(this._activePaths.states.modify);

        return directModifiedPaths.reduce(function (list, path) {
          var parts = path.split('.');
          return list.concat(parts.reduce(function (chains, part, i) {
            return chains.concat(parts.slice(0, i).concat(part).join('.'));
          }, []));
        }, []);
      };

  #### Returns:

  - <Array>

  ### Document#isModified(`[path]`)

  Returns true if this document was modified, else false.

  show code

      Document.prototype.isModified = function (path) {
        return path
          ? !!~this.modifiedPaths().indexOf(path)
          : this._activePaths.some('modify');
      };

  #### Parameters:

  - `[path]` <String> optional

  #### Returns:

  - <Boolean>

  If `path` is given, checks if a path or any full path containing `path` as part of its path chain has been modified.

  #### Example

      doc.set('documents.0.title', 'changed');
      doc.isModified()                    // true
      doc.isModified('documents')         // true
      doc.isModified('documents.0.title') // true
      doc.isDirectModified('documents')   // false

  ### Document#isDirectModified(`path`)

  Returns true if `path` was directly set and modified, else false.

  show code

      Document.prototype.isDirectModified = function (path) {
        return (path in this._activePaths.states.modify);
      };

  #### Parameters:

  - `path` <String>

  #### Returns:

  - <Boolean>

  #### Example

      doc.set('documents.0.title', 'changed');
      doc.isDirectModified('documents.0.title') // true
      doc.isDirectModified('documents') // false

  ### Document#isInit(`path`)

  Checks if `path` was initialized.

  show code

      Document.prototype.isInit = function (path) {
        return (path in this._activePaths.states.init);
      };

  #### Parameters:

  - `path` <String>

  #### Returns:

  - <Boolean>

  ### Document#isSelected(`path`)

  Checks if `path` was selected in the source query which initialized this document.

  show code

      Document.prototype.isSelected = function isSelected (path) {
        if (this._selected) {

          if ('_id' === path) {
            return 0 !== this._selected._id;
          }

          var paths = Object.keys(this._selected)
            , i = paths.length
            , inclusive = false
            , cur

          if (1 === i && '_id' === paths[0]) {
            // only _id was selected.
            return 0 === this._selected._id;
          }

          while (i--) {
            cur = paths[i];
            if ('_id' == cur) continue;
            inclusive = !! this._selected[cur];
            break;
          }

          if (path in this._selected) {
            return inclusive;
          }

          i = paths.length;
          var pathDot = path + '.';

          while (i--) {
            cur = paths[i];
            if ('_id' == cur) continue;

            if (0 === cur.indexOf(pathDot)) {
              return inclusive;
            }

            if (0 === pathDot.indexOf(cur)) {
              return inclusive;
            }
          }

          return ! inclusive;
        }

        return true;
      }

  #### Parameters:

  - `path` <String>

  #### Returns:

  - <Boolean>

  #### Example

      Thing.findOne().select('name').exec(function (err, doc) {
         doc.isSelected('name') // true
         doc.isSelected('age')  // false
      })

  ### Document#validate(`cb`)

  Executes registered validation rules for this document.

  show code

      Document.prototype.validate = function (cb) {
        var self = this

        // only validate required fields when necessary
        var paths = Object.keys(this._activePaths.states.require).filter(function (path) {
          if (!self.isSelected(path) && !self.isModified(path)) return false;
          return true;
        });

        paths = paths.concat(Object.keys(this._activePaths.states.init));
        paths = paths.concat(Object.keys(this._activePaths.states.modify));

        if (0 === paths.length) {
          complete();
          return this;
        }

        var validating = {}
          , total = 0;

        paths.forEach(validatePath);
        return this;

        function validatePath (path) {
          if (validating[path]) return;

          validating[path] = true;
          total++;

          process.nextTick(function(){
            var p = self.schema.path(path);
            if (!p) return --total || complete();

            p.doValidate(self.getValue(path), function (err) {
              if (err) self.invalidate(path, err, true);
              --total || complete();
            }, self);
          });
        }

        function complete () {
          var err = self._validationError;
          self._validationError = undefined;
          cb(err);
        }
      };

  #### Parameters:

  - `cb` <Function> called after validation completes, passing an error if one occurred

  #### Note:

  This method is called `pre` save and if a validation rule is violated, save is aborted and the error is returned to your `callback`.

  #### Example:

      doc.validate(function (err) {
        if (err) handleError(err);
        else // validation passed
      });

  ### Document#invalidate(`path`, `err`)

  Marks a path as invalid, causing validation to fail.

  show code

      Document.prototype.invalidate = function (path, err) {
        if (!this._validationError) {
          this._validationError = new ValidationError(this);
        }

        if (!err || 'string' === typeof err) {
          err = new ValidatorError(path, err);
        }

        this._validationError.errors[path] = err;
      }

  #### Parameters:

  - `path` <String> the field to invalidate
  - `err` <String, Error> the error which states the reason `path` was invalid

  ### Document#_reset()

  Resets the internal modified state of this document.

  show code

      Document.prototype._reset = function reset () {
        var self = this;
        DocumentArray || (DocumentArray = require('./types/documentarray'));

        this._activePaths
        .map('init', 'modify', function (i) {
          return self.getValue(i);
        })
        .filter(function (val) {
          return (val && val instanceof DocumentArray && val.length);
        })
        .forEach(function (array) {
          array.forEach(function (doc) {
            doc._reset();
          });
        });

        // clear atomics
        this._dirty().forEach(function (dirt) {
          var type = dirt.value;
          if (type && type._atomics) {
            type._atomics = {};
          }
        });

        // Clear 'modify'('dirty') cache
        this._activePaths.clear('modify');
        this._validationError = undefined;
        this.errors = undefined;
        var self = this;
        this.schema.requiredPaths().forEach(function (path) {
          self._activePaths.require(path);
        });

        return this;
      }

  #### Returns:

  - <Document>

  ### Document#_dirty()

  Returns this documents dirty paths / vals.

  show code

      Document.prototype._dirty = function _dirty () {
        var self = this;

        var all = this._activePaths.map('modify', function (path) {
          return { path: path
                 , value: self.getValue(path)
                 , schema: self._path(path) };
        });

        // Sort dirty paths in a flat hierarchy.
        all.sort(function (a, b) {
          return (a.path < b.path ? -1 : (a.path > b.path ? 1 : 0));
        });

        // Ignore "foo.a" if "foo" is dirty already.
        var minimal = []
          , lastPath
          , top;

        all.forEach(function (item, i) {
          if (item.path.indexOf(lastPath) !== 0) {
            lastPath = item.path + '.';
            minimal.push(item);
            top = item;
          } else {
            if (!(item.value && top.value)) return;

            // special case for top level MongooseArrays
            if (top.value._atomics && top.value.hasAtomics()) {
              // and the item is not a MongooseArray
              if (!(item.value._atomics && item.value.hasAtomics())) {
                // theres a sub path of top being explicitly set.
                // the only way to honor all of their modifications
                // is through a $set of entire array.
                // change top to a $set op
                top.value._atomics = {};
                top.value._atomics.$set = top.value;
              }
            }
          }
        });

        top = lastPath = null;
        return minimal;
      }

  ### Document#_setSchema(`schema`)

  Assigns/compiles `schema` into this documents prototype.

  show code

      Document.prototype._setSchema = function (schema) {
        compile(schema.tree, this);
        this.schema = schema;
      }

  #### Parameters:

  - `schema` <Schema>

  ### Document#_registerHooks()

  Register default hooks

  show code

      Document.prototype._registerHooks = function _registerHooks () {
        if (!this.save) return;

        DocumentArray || (DocumentArray = require('./types/documentarray'));

        this.pre('save', function (next) {
          // we keep the error semaphore to make sure we don't
          // call `save` unnecessarily (we only need 1 error)
          var subdocs = 0
            , error = false
            , self = this;

          // check for DocumentArrays
          var arrays = this._activePaths
          .map('init', 'modify', function (i) {
            return self.getValue(i);
          })
          .filter(function (val) {
            return (val && val instanceof DocumentArray && val.length);
          });

          if (!arrays.length)
            return next();

          arrays.forEach(function (array) {
            subdocs += array.length;
            array.forEach(function (value) {
              if (error) return;

              value.save(function (err) {
                if (error) return;

                if (err) {
                  error = true;
                  self._validationError = undefined;
                  return next(err);
                }

                --subdocs || next();
              });
            });
          });
        }, function (err) {
          // emit on the Model if listening
          if (this.constructor.listeners('error').length) {
            this.constructor.emit('error', err);
          } else {
            // emit on the connection
            if (!this.db.listeners('error').length) {
              err.stack = 'No listeners detected, throwing. '
                        + 'Consider adding an error listener to your connection.
      '
                        + err.stack
            }
            this.db.emit('error', err);
          }
        }).pre('save', function checkForExistingErrors (next) {
          // if any doc.set() calls failed
          if (this._saveError) {
            next(this._saveError);
            this._saveError = null;
          } else {
            next();
          }
        }).pre('save', function validation (next) {
          return this.validate(next);
        });

        // add user defined queues
        this._doQueue();
      };

  ### Document#_error(`err`)

  Registers an error

  show code

      Document.prototype._error = function (err) {
        this._saveError = err;
        return this;
      };

  #### Parameters:

  - `err` <Error>

  ### Document#_doQueue()

  Executes methods queued from the Schema definition

  show code

      Document.prototype._doQueue = function () {
        var q = this.schema && this.schema.callQueue;
        if (q) {
          for (var i = 0, l = q.length; i < l; i++) {
            this[q[i][0]].apply(this, q[i][1]);
          }
        }
        return this;
      };

  ### Document#toObject(`[options]`)

  Converts this document into a plain javascript object

  show code

      Document.prototype.toObject = function (options) {
        // When internally saving this document we always pass options,
        // bypassing the custom schema options.
        if (!(options && 'Object' == options.constructor.name)) {
          options = this.schema.options.toObject
            ? clone(this.schema.options.toObject)
            : {};
        }

        ;('minimize' in options) || (options.minimize = this.schema.options.minimize);

        var ret = clone(this._doc, options);

        if (options.virtuals || options.getters && false !== options.virtuals) {
          applyGetters(this, ret, 'virtuals', options);
        }

        if (options.getters) {
          applyGetters(this, ret, 'paths', options);
        }

        return ret;
      };

  #### Parameters:

  - `[options]` <Object>

  #### Returns:

  - <Object> js object

  Available options

  - `getters` apply all getters (path and virtual getters)
  - `virtuals` apply virtual getters (can override `getters` option)
  - `minimize` remove empty objects (defaults to true)

  Example of only applying path getters

      doc.toObject({ getters: true, virtuals: false })

  Example of only applying virtual getters

      doc.toObject({ virtuals: true })

  Example of applying both path and virtual getters

      doc.toObject({ getters: true })

  ### Document#toJSON(`options`)

  The return value of this method is used in calls to JSON.stringify(doc).

  show code

      Document.prototype.toJSON = function (options) {
        // check for object type since an array of documents
        // being stringified passes array indexes instead
        // of options objects. JSON.stringify([doc, doc])
        if (!(options && 'Object' == options.constructor.name)) {
          options = this.schema.options.toJSON
            ? clone(this.schema.options.toJSON)
            : {};
        }
        options.json = true;
        return this.toObject(options);
      };

  #### Parameters:

  - `options` <Object> same options as Document#toObject

  #### Returns:

  - <Object>

  #### See:

  - Document#toObject

  ### Document#inspect()

  Helper for console.log

  show code

      Document.prototype.inspect = function (options) {
        var opts = options && 'Object' == options.constructor.name
          ? options
          : undefined
        return inspect(this.toObject(opts));
      };

  ### Document#toString()

  Helper for console.log

  ### Document#equals(`doc`)

  Returns true if the Document stores the same data as doc.

  show code

      Document.prototype.equals = function (doc) {
        var tid = this.get('_id');
        var docid = doc.get('_id');
        return tid.equals
          ? tid.equals(docid)
          : tid === docid;
      };

  #### Parameters:

  - `doc` <Document> a document to compare

  #### Returns:

  - <Boolean>

  Documents are considered equal when they have matching `_id`s.

  ### Document#errors

  Hash containing current validation errors.

  ### Document#isNew

  Boolean flag specifying if the document is new.

  ### Document#schema

  The documents schema.

- drivers/node-mongodb-native/collection.js

  ### NativeCollection()

  A node-mongodb-native collection implementation.

  show code

      function NativeCollection () {
        this.collection = null;
        MongooseCollection.apply(this, arguments);
      }

  #### Inherits:

  - Collection

  All methods methods from the node-mongodb-native driver are copied and wrapped in queue management.

  ### NativeCollection#onOpen()

  Called when the connection opens.

  show code

      NativeCollection.prototype.onOpen = function () {
        var self = this;

        if (this.collection) {
          return MongooseCollection.prototype.onOpen.call(self);
        }

        if (!self.opts.size) {
          // non-capped
          return self.conn.db.collection(self.name, callback);
        }

        // capped
        return self.conn.db.collection(self.name, function (err, c) {
          if (err) return callback(err);

          // discover if this collection exists and if it is capped
          c.options(function (err, exists) {
            if (err) return callback(err);

            if (exists) {
              if (exists.capped) {
                callback(null, c);
              } else {
                var msg = 'A non-capped collection exists with this name.

      '
                        + ' To use this collection as a capped collection, please '
                        + 'first convert it.
      '
                        + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped'
                err = new Error(msg);
                callback(err);
              }
            } else {
              // create
              var opts = utils.clone(self.opts);
              opts.capped = true;
              self.conn.db.createCollection(self.name, opts, callback);
            }
          });
        });

        function callback (err, collection) {
          if (err) {
            // likely a strict mode error
            self.conn.emit('error', err);
          } else {
            self.collection = collection;
            MongooseCollection.prototype.onOpen.call(self);
          }
        };
      };

  ### NativeCollection#onClose()

  Called when the connection closes

  show code

      NativeCollection.prototype.onClose = function () {
        MongooseCollection.prototype.onClose.call(this);
      };

  ### NativeCollection#getIndexes(`callback`)

  Retreives information about this collections indexes.

  #### Parameters:

  - `callback` <Function>

- drivers/node-mongodb-native/connection.js

  ### NativeConnection()

  A node-mongodb-native connection implementation.

  show code

      function NativeConnection() {
        MongooseConnection.apply(this, arguments);
      };

  #### Inherits:

  - Connection

  ### NativeConnection#doOpen(`fn`)

  Opens the connection to MongoDB.

  show code

      NativeConnection.prototype.doOpen = function (fn) {
        var server
          , self = this;

        if (!this.db) {
          server = new mongo.Server(this.host, Number(this.port), this.options.server);
          this.db = new mongo.Db(this.name, server, this.options.db);
        }

        this.db.open(function (err) {
          if (err) return fn(err);
          fn();
          listen(self);
        });

        return this;
      };

      function listen (conn) {
        if (conn._listening) return;
        conn._listening = true;

        conn.db.on('close', function(){
          if (conn._closeCalled) return;

          // the driver never emits an `open` event. auto_reconnect still
          // emits a `close` event but since we never get another
          // `open` we can't emit close
          if (conn.options.server.auto_reconnect) {
            conn.readyState = STATES.disconnected;
            conn.emit('close');
            return;
          }
          conn.onClose();
        });
        conn.db.on('error', function(err){
          conn.emit('error', err);
        });
        conn.db.on('timeout', function(err){
          var error = new Error(err && err.err || 'connection timeout');
          conn.emit('error', error);
        });
        conn.db.on('open', function () {
          conn.emit('reconnected')
        })
        conn.db.on('fullsetup', function () {
          conn.emit('fullsetup')
        })
      }

  #### Parameters:

  - `fn` <Function>

  #### Returns:

  - <Connection> this

  ### NativeConnection#doOpenSet(`fn`)

  Opens a connection to a MongoDB ReplicaSet.

  show code

      NativeConnection.prototype.doOpenSet = function (fn) {
        if (!this.db) {
          var servers = []
            , ports = this.port
            , self = this

          this.host.forEach(function (host, i) {
            servers.push(new mongo.Server(host, Number(ports[i]), self.options.server));
          });

          var server = new ReplSetServers(servers, this.options.replset);
          this.db = new mongo.Db(this.name, server, this.options.db);
          listen(this);
        }

        this.db.open(fn);

        return this;
      };

  #### Parameters:

  - `fn` <Function>

  #### Returns:

  - <Connection> this

  See description of doOpen for server options. In this case `options.replset` is also passed to ReplSetServers.

  ### NativeConnection#doClose(`fn`)

  Closes the connection

  show code

      NativeConnection.prototype.doClose = function (fn) {
        this.db.close();
        if (fn) fn();
        return this;
      }

  #### Parameters:

  - `fn` <Function>

  #### Returns:

  - <Connection> this

- error.js

  ### MongooseError()

  Mongoose error

  show code

      function MongooseError (msg) {
        Error.call(this);
        Error.captureStackTrace(this, arguments.callee);
        this.message = msg;
        this.name = 'MongooseError';
      };

  #### Inherits:

  - Error

- errors/cast.js

  ### CastError(`type`, `value`)

  Casting Error constructor.

  show code

      function CastError (type, value) {
        MongooseError.call(this, 'Cast to ' + type + ' failed for value "' + value + '"');
        Error.captureStackTrace(this, arguments.callee);
        this.name = 'CastError';
        this.type = type;
        this.value = value;
      };

  #### Parameters:

  - `type` <String>
  - `value` <String>

  #### Inherits:

  - MongooseError

- errors/document.js

  ### DocumentError(`msg`)

  Document Error

  show code

      function DocumentError (msg) {
        MongooseError.call(this, msg);
        Error.captureStackTrace(this, arguments.callee);
        this.name = 'DocumentError';
      };

  #### Parameters:

  - `msg` <String>

  #### Inherits:

  - MongooseError

- errors/validation.js

  ### ValidationError(`instance`)

  Document Validation Error

  show code

      function ValidationError (instance) {
        MongooseError.call(this, "Validation failed");
        Error.captureStackTrace(this, arguments.callee);
        this.name = 'ValidationError';
        this.errors = instance.errors = {};
      };

  #### Parameters:

  - `instance` <Document>

  #### Inherits:

  - MongooseError

  ### ValidationError#toString()

  Console.log helper

  show code

      ValidationError.prototype.toString = function () {
        return this.name + ': ' + Object.keys(this.errors).map(function (key) {
          return String(this.errors[key]);
        }, this).join(', ');
      };

- errors/validator.js

  ### ValidatorError(`path`, `msg`)

  Schema validator error

  show code

      function ValidatorError (path, type) {
        var msg = type
          ? '"' + type + '" '
          : '';
        MongooseError.call(this, 'Validator ' + msg + 'failed for path ' + path);
        Error.captureStackTrace(this, arguments.callee);
        this.name = 'ValidatorError';
        this.path = path;
        this.type = type;
      };

  #### Parameters:

  - `path` <String>
  - `msg` <String>

  #### Inherits:

  - MongooseError

- model.js

  ### Model(`doc`)

  Model constructor

  show code

      function Model (doc, fields, skipId) {
        Document.call(this, doc, fields, skipId);
      };

  #### Parameters:

  - `doc` <Object> values to with which to create the document

  #### Inherits:

  - Document

  #### Events:

  - `error`: If listening to this Model event, it is emitted when a document was saved without passing a callback and an `error` occurred. If not listening, the event bubbles to the connection used to create this Model.

  - `index`: Emitted after `Model#ensureIndexes` completes. If an error occurred it is passed with the event.

  ### Model#_getPopulationKeys(`query`)

  Returns what paths can be populated

  show code

      Model.prototype._getPopulationKeys = function getPopulationKeys (query) {
        if (!(query && query.options.populate)) return;

        var names = Object.keys(query.options.populate)
          , n = names.length
          , name
          , paths = {}
          , hasKeys
          , schema

        while (n--) {
          name = names[n];
          schema = this.schema.path(name);
          hasKeys = true;

          if (!schema) {
            // if the path is not recognized, it's potentially embedded docs
            // walk path atoms from right to left to find a matching path
            var pieces = name.split('.')
              , i = pieces.length;

            while (i--) {
              var path = pieces.slice(0, i).join('.')
                , pathSchema = this.schema.path(path);

              // loop until we find an array schema
              if (pathSchema && pathSchema.caster) {
                if (!paths[path]) {
                  paths[path] = { sub: {} };
                }

                paths[path].sub[pieces.slice(i).join('.')] = query.options.populate[name];
                hasKeys || (hasKeys = true);
                break;
              }
            }
          } else {
            paths[name] = query.options.populate[name];
            hasKeys || (hasKeys = true);
          }
        }

        return hasKeys && paths;
      };

  #### Parameters:

  - `query` <Query> object

  #### Returns:

  - <Object, undefined> population paths

  ### Model#_populate(`schema`, `oid`, `query`, `fn`)

  Populates an object

  show code

      Model.prototype._populate = function populate (schema, oid, query, fn) {
        if (!Array.isArray(oid)) {
          var conditions = query.conditions || {};
          conditions._id = oid;

          return this
          .db.model(query.model || schema.options.ref)
          .findOne(conditions, query.fields, query.options, fn);
        }

        if (!oid.length) {
          return fn(null, oid);
        }

        var model = this.db.model(query.model || schema.caster.options.ref)
          , conditions = query && query.conditions || {};

        conditions._id || (conditions._id = { $in: oid });

        model.find(conditions, query.fields, query.options, function (err, docs) {
          if (err) return fn(err);

          // user specified sort order?
          if (query.options && query.options.sort) {
            return fn(null, docs);
          }

          // put back in original id order (using a hash reduces complexity from n*n to 2n)
          var docHash = {};
          docs.forEach(function (doc) {
            docHash[doc._id] = doc;
          });

          var arr = [];
          oid.forEach(function (id) {
            if (id in docHash) arr.push(docHash[id]);
          });

          fn(null, arr);
        });
      };

  #### Parameters:

  - `schema` <SchemaType> type for the oid
  - `oid` <Object> object id or array of object ids
  - `query` <Object> object specifying query conditions, fields, and options
  - `fn` <Function>

  ### Model#init(`doc`, `query`, `fn`)

  Performs auto-population of relations.

  show code

      Model.prototype.init = function init (doc, query, fn) {
        if ('function' == typeof query) {
          fn = query;
          query = null;
        }

        var populate = this._getPopulationKeys(query);

        if (!populate) {
          return Document.prototype.init.call(this, doc, fn);
        }

        // population from other models is necessary
        var self = this;

        init(doc, '', function (err) {
          if (err) return fn(err);
          Document.prototype.init.call(self, doc, fn);
        });

        return this;

        function init (obj, prefix, fn) {
          prefix = prefix || '';

          var keys = Object.keys(obj)
            , len = keys.length;

          function next () {
            if (--len < 0) return fn();

            var i = keys[len]
              , path = prefix + i
              , schema = self.schema.path(path)
              , total = 0
              , poppath

            if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {
              // assume nested object
              return init(obj[i], path + '.', next);
            }

            if (!(obj[i] && schema && populate[path])) return next();

            // this query object is re-used and passed around. we clone
            // it to prevent query condition contamination between
            // one populate call to the next.
            poppath = utils.clone(populate[path]);

            if (poppath.sub) {
              obj[i].forEach(function (subobj) {
                var pkeys = Object.keys(poppath.sub)
                  , pi = pkeys.length
                  , key

                while (pi--) {
                  key = pkeys[pi];

                  if (subobj[key]) (function (key) {

                    total++;
                    self._populate(schema.schema.path(key), subobj[key], poppath.sub[key], done);
                    function done (err, doc) {
                      if (err) return error(err);
                      subobj[key] = doc;
                      --total || next();
                    }
                  })(key);
                }
              });

              if (0 === total) return next();

            } else {
              self._populate(schema, obj[i], poppath, function (err, doc) {
                if (err) return error(err);
                obj[i] = doc;
                next();
              });
            }
          };

          next();
        };

        function error (err) {
          if (error.err) return;
          fn(error.err = err);
        }
      };

  #### Parameters:

  - `doc` <Object> document returned by mongo
  - `query` <Query> query that originated the initialization
  - `fn` <Function>

  ### Model#save(`[fn]`)

  Saves this document.

  show code

      Model.prototype.save = function save (fn) {
        var promise = new Promise(fn)
          , complete = handleSave(promise, this)
          , options = {}

        if (this.schema.options.safe) {
          options.safe = this.schema.options.safe;
        }

        if (this.isNew) {
          // send entire doc
          var obj = this.toObject({ depopulate: 1 });
          this._version(true, obj);
          this.collection.insert(obj, options, complete);
          this._reset();
          this.isNew = false;
          this.emit('isNew', false);
          // Make it possible to retry the insert
          this._inserting = true;

        } else {
          // Make sure we don't treat it as a new object on error,
          // since it already exists
          this._inserting = false;

          var delta = this._delta();
          if (delta) {
            var where = this._where(delta[0]);
            this.collection.update(where, delta[1], options, complete);
          } else {
            complete(null);
          }

          this._reset();
          this.emit('isNew', false);
        }
      };

  #### Parameters:

  - `[fn]` <Function> optional callback

  #### See:

  - middleware

  #### Example:

      product.sold = Date.now();
      product.save(function (err, product) {
        if (err) ..
      })

  The `fn` callback is optional. If no `fn` is passed and validation fails, the validation error will be emitted on the connection used to create this model.

      var db = mongoose.createConnection(..);
      var schema = new Schema(..);
      var Product = db.model('Product', schema);

      db.on('error', handleError);

  However, if you desire more local error handling you can add an `error` listener to the model and handle errors there instead.

      Product.on('error', handleError);

  ### Model#_delta()

  Produces a special query document of the modified properties used in updates.

  show code

      Model.prototype._delta = function _delta () {
        var dirty = this._dirty();
        if (!dirty.length) return;

        var self = this
          , where = {}
          , delta = {}
          , len = dirty.length
          , d = 0
          , val
          , obj

        for (; d < len; ++d) {
          var data = dirty[d]
          var value = data.value
          var schema = data.schema

          if (undefined === value) {
            operand(self, where, delta, data, 1, '$unset');

          } else if (null === value) {
            operand(self, where, delta, data, null);

          } else if (value._path && value._atomics) {
            handleAtomics(self, where, delta, data, value);

          } else if (value._path && Buffer.isBuffer(value)) {
            // MongooseBuffer
            value = value.toObject();
            operand(self, where, delta, data, value);

          } else {
            value = utils.clone(value);
            operand(self, where, delta, data, value);
          }
        }

        if (this.__version) {
          this._version(where, delta);
        }

        return [where, delta];
      }

  ### Model#_version()

  Appends versioning to the where and update clauses.

  show code

      Model.prototype._version = function _version (where, delta) {
        var key = this.schema.options.versionKey;

        if (true === where) {
          // this is an insert
          if (key) this.setValue(key, delta[key] = 0);
          return;
        }

        // updates

        // only apply versioning if our versionKey was selected. else
        // there is no way to select the correct version. we could fail
        // fast here and force them to include the versionKey but
        // thats a bit intrusive. can we do this automatically?
        // TODO fail fast option?
        if (!this.isSelected(key)) {
          return;
        }

        // $push $addToSet don't need the where clause set
        if (VERSION_WHERE === (VERSION_WHERE & this.__version)) {
          where[key] = this.getValue(key);
        }

        if (VERSION_INC === (VERSION_INC & this.__version)) {
          delta.$inc || (delta.$inc = {});
          delta.$inc[key] = 1;
        }
      }

  ### Model#increment()

  Signal that we desire an increment of this documents version.

  show code

      Model.prototype.increment = function increment () {
        this.__version = VERSION_ALL;
        return this;
      }

  #### See:

  - versionKeys

  ### Model#_where()

  Returns a query object which applies shardkeys if they exist.

  show code

      Model.prototype._where = function _where (where) {
        where || (where = {});

        var paths
          , len

        if (this._shardval) {
          paths = Object.keys(this._shardval)
          len = paths.length

          for (var i = 0; i < len; ++i) {
            where[paths[i]] = this._shardval[paths[i]];
          }
        }

        where._id = this._doc._id;
        return where;
      }

  ### Model#remove(`[fn]`)

  Removes this document from the db.

  show code

      Model.prototype.remove = function remove (fn) {
        if (this._removing) return this;

        var promise = this._removing = new Promise(fn)
          , where = this._where()
          , self = this
          , options = {}

        if (this.schema.options.safe) {
          options.safe = this.schema.options.safe;
        }

        this.collection.remove(where, options, tick(function (err) {
          if (err) {
            promise.error(err);
            promise = self = self._removing = where = options = null;
            return;
          }
          self.emit('remove', self);
          promise.complete();
          promise = self = where = options = null;
        }));

        return this;
      };

  #### Parameters:

  - `[fn]` <Function> optional callback

  #### Example:

      product.remove(function (err, product) {
        if (err) return handleError(err);
        Product.findById(product._id, function (err, product) {
          console.log(product) // null
        })
      })

  ### Model#_registerHooks()

  Register hooks override

  show code

      Model.prototype._registerHooks = function registerHooks () {
        Document.prototype._registerHooks.call(this);
      };

  ### Model#model(`name`)

  Returns another Model instance.

  show code

      Model.prototype.model = function model (name) {
        return this.db.model(name);
      };

  #### Parameters:

  - `name` <String> model name

  #### Example:

      var doc = new Tank;
      doc.model('User').findById(id, callback);

  ### Model#$where(`argument`)

  Creates a `Query` and specifies a `$where` condition.

  #### Parameters:

  - `argument` <String, Function> is a javascript string or anonymous function

  #### Returns:

  - <Query>

  #### See:

  - Query.$where

  Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via `find({ $where: javascript })`, or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.

      Blog.$where('this.comments.length &gt; 5');

  ### Model.init()

  Called when the model compiles.

  show code

      Model.init = function init () {
        if (this.schema.options.autoIndex)
          this.ensureIndexes();

        this.schema.emit('init', this);
      };

  ### Model.ensureIndexes(`[cb]`)

  Sends `ensureIndex` commands to mongo for each index declared in the schema.

  show code

      Model.ensureIndexes = function ensureIndexes (cb) {
        var indexes = this.schema.indexes();
        if (!indexes.length) {
          return cb && cb();
        }

        var self = this
          , safe = self.schema.options.safe
          , count = indexes.length
          , error

        indexes.forEach(function (index) {
          var options = index[1];
          options.safe = safe;
          self.collection.ensureIndex(index[0], options, tick(function (err) {
            if (err) error = err;
            if (--count) return;

            self.emit('index', error);
            cb && cb(error);
          }));
        });
      }

  #### Parameters:

  - `[cb]` <Function> optional callback

  After completion, an `index` event is emitted on this `Model` passing an error if one occurred.

  ### Model.remove(`conditions`, `[callback]`)

  Removes documents from the collection.

  show code

      Model.remove = function remove (conditions, callback) {
        if ('function' === typeof conditions) {
          callback = conditions;
          conditions = {};
        }

        var query = new Query(conditions).bind(this, 'remove');

        if ('undefined' === typeof callback)
          return query;

        this._applyNamedScope(query);
        return query.remove(callback);
      };

  #### Parameters:

  - `conditions` <Object>
  - `[callback]` <Function>

  #### Returns:

  - <Query>

  ### Model.find(`conditions`, `[fields]`, `[options]`, `[callback]`)

  Finds documents

  show code

      Model.find = function find (conditions, fields, options, callback) {
        if ('function' == typeof conditions) {
          callback = conditions;
          conditions = {};
          fields = null;
          options = null;
        } else if ('function' == typeof fields) {
          callback = fields;
          fields = null;
          options = null;
        } else if ('function' == typeof options) {
          callback = options;
          options = null;
        }

        var query = new Query(conditions, options);
        query.bind(this, 'find');
        query.select(fields);

        if ('undefined' === typeof callback)
          return query;

        this._applyNamedScope(query);
        return query.find(callback);
      };

  #### Parameters:

  - `conditions` <Object>
  - `[fields]` <Object> optional fields to select
  - `[options]` <Object> optional
  - `[callback]` <Function>

  #### Returns:

  - <Query>

  #### See:

  - field selection

  #### Examples:

      // retrieve only certain keys
      MyModel.find({ name: /john/i }, 'name friends', function () { })

      // pass options
      MyModel.find({ name: /john/i }, null, { skip: 10 } )

  ### Model._applyNamedScope(`query`)

  Merges the current named scope query into `query`.

  show code

      Model._applyNamedScope = function _applyNamedScope (query) {
        var cQuery = this._cumulativeQuery;

        if (cQuery) {
          merge(query._conditions, cQuery._conditions);
          if (query._fields && cQuery._fields)
            merge(query._fields, cQuery._fields);
          if (query.options && cQuery.options)
            merge(query.options, cQuery.options);
          delete this._cumulativeQuery;
        }

        return query;
      }

  #### Parameters:

  - `query` <Query>

  #### Returns:

  - <Query>

  ### Model.findById(`id`, `[fields]`, `[options]`, `[callback]`)

  Finds a single document by id.

  show code

      Model.findById = function findById (id, fields, options, callback) {
        return this.findOne({ _id: id }, fields, options, callback);
      };

  #### Parameters:

  - `id` <ObjectId, HexId> objectid, or a value that can be casted to one
  - `[fields]` <Object> optional fields to select
  - `[options]` <Object> optional
  - `[callback]` <Function>

  #### Returns:

  - <Query>

  #### See:

  - field selection

  The `id` is cast to an ObjectId before sending the command.

  #### Example:

      Adventure.findById(id, callback);

  ### Model.findOne(`conditions`, `[fields]`, `[options]`, `[callback]`)

  Finds one document.

  show code

      Model.findOne = function findOne (conditions, fields, options, callback) {
        if ('function' == typeof options) {
          // TODO Handle all 3 of the following scenarios
          // Hint: Only some of these scenarios are possible if cQuery is present
          // Scenario: findOne(conditions, fields, callback);
          // Scenario: findOne(fields, options, callback);
          // Scenario: findOne(conditions, options, callback);
          callback = options;
          options = null;
        } else if ('function' == typeof fields) {
          // TODO Handle all 2 of the following scenarios
          // Scenario: findOne(conditions, callback)
          // Scenario: findOne(fields, callback)
          // Scenario: findOne(options, callback);
          callback = fields;
          fields = null;
          options = null;
        } else if ('function' == typeof conditions) {
          callback = conditions;
          conditions = {};
          fields = null;
          options = null;
        }

        var query = new Query(conditions, options).select(fields).bind(this, 'findOne');

        if ('undefined' == typeof callback)
          return query;

        this._applyNamedScope(query);
        return query.findOne(callback);
      };

  #### Parameters:

  - `conditions` <Object>
  - `[fields]` <Object> optional fields to select
  - `[options]` <Object> optional
  - `[callback]` <Function>

  #### Returns:

  - <Query>

  #### See:

  - field selection

  The `conditions` are cast to their respective SchemaTypes before the command is sent.

  #### Example:

      Adventure.findOne({ type: 'iphone' }, 'name', { safe: true }, callback);

  ### Model.count(`conditions`, `[callback]`)

  Counts number of matching documents in a database collection.

  show code

      Model.count = function count (conditions, callback) {
        if ('function' === typeof conditions)
          callback = conditions, conditions = {};

        var query = new Query(conditions).bind(this, 'count');
        if ('undefined' == typeof callback)
          return query;

        this._applyNamedScope(query);
        return query.count(callback);
      };

  #### Parameters:

  - `conditions` <Object>
  - `[callback]` <Function>

  #### Returns:

  - <Query>

  #### Example:

      Adventure.count({ type: 'jungle' }, function (err, count) {
        if (err) ..
        console.log('there are %d jungle adventures', count);
      });

  ### Model.distinct(`field`, `[conditions]`, `[callback]`)

  Executes a DISTINCT command

  show code

      Model.distinct = function distinct (field, conditions, callback) {
        var query = new Query(conditions).bind(this, 'distinct');
        if ('undefined' == typeof callback) {
          query._distinctArg = field;
          return query;
        }

        this._applyNamedScope(query);
        return query.distinct(field, callback);
      };

  #### Parameters:

  - `field` <String>
  - `[conditions]` <Object> optional
  - `[callback]` <Function>

  #### Returns:

  - <Query>

  ### Model.where(`path`, `[val]`)

  Creates a Query, applies the passed conditions, and returns the Query.

  show code

      Model.where = function where (path, val) {
        var q = new Query().bind(this, 'find');
        return q.where.apply(q, arguments);
      };

  #### Parameters:

  - `path` <String>
  - `[val]` <Object> optional value

  #### 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 chaining

      User
      .where('age').gte(21).lte(65)
      .where('name', /^b/i)
      ... etc

  ### Model.findOneAndUpdate(`[conditions]`, `[update]`, `[options]`, `[callback]`)

  Issues a mongodb findAndModify update command.

  show code

      Model.findOneAndUpdate = function (conditions, update, options, callback) {
        if ('function' == typeof options) {
          callback = options;
          options = null;
        }
        else if (1 === arguments.length) {
          if ('function' == typeof conditions) {
            var msg = 'Model.findOneAndUpdate(): First argument must not be a function.

      '
                    + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)
      '
                    + '  ' + this.modelName + '.findOneAndUpdate(conditions, update, options)
      '
                    + '  ' + this.modelName + '.findOneAndUpdate(conditions, update)
      '
                    + '  ' + this.modelName + '.findOneAndUpdate(update)
      '
                    + '  ' + this.modelName + '.findOneAndUpdate()
      ';
            throw new TypeError(msg)
          }
          update = conditions;
          conditions = undefined;
        }

        var fields;
        if (options && options.fields) {
          fields = options.fields;
          options.fields = undefined;
        }

        var query = new Query(conditions, options);
        query.select(fields);
        query.bind(this, 'findOneAndUpdate', update);

        if ('undefined' == typeof callback)
          return query;

        this._applyNamedScope(query);
        return query.findOneAndUpdate(callback);
      }

  #### Parameters:

  - `[conditions]` <Object>
  - `[update]` <Object>
  - `[options]` <Object>
  - `[callback]` <Function>

  #### Returns:

  - <Query>

  #### See:

  - mongodb

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

  #### Options:

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

  #### 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

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

  Issues a mongodb findAndModify update command by a documents id.

  show code

      Model.findByIdAndUpdate = function (id, update, options, callback) {
        var args;

        if (1 === arguments.length) {
          if ('function' == typeof id) {
            var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.

      '
                      + '  ' + this.modelName + '.findByIdAndUpdate(id, callback)
      '
                      + '  ' + this.modelName + '.findByIdAndUpdate(id)
      '
                      + '  ' + this.modelName + '.findByIdAndUpdate()
      ';
            throw new TypeError(msg)
          }
          return this.findOneAndUpdate({_id: id }, undefined);
        }

        args = utils.args(arguments, 1);
        args.unshift({ _id: id });
        return this.findOneAndUpdate.apply(this, args);
      }

  #### Parameters:

  - `id` <ObjectId, HexId> an ObjectId or string that can be cast to one.
  - `[update]` <Object>
  - `[options]` <Object>
  - `[callback]` <Function>

  #### Returns:

  - <Query>

  #### See:

  - Model.findOneAndUpdate
  - mongodb

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

  #### Options:

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

  #### Examples:

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

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

  #### Options:

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

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

  Issue a mongodb findAndModify remove command.

  show code

      Model.findOneAndRemove = function (conditions, options, callback) {
        if (1 === arguments.length && 'function' == typeof conditions) {
          var msg = 'Model.findOneAndRemove(): First argument must not be a function.

      '
                    + '  ' + this.modelName + '.findOneAndRemove(conditions, callback)
      '
                    + '  ' + this.modelName + '.findOneAndRemove(conditions)
      '
                    + '  ' + this.modelName + '.findOneAndRemove()
      ';
          throw new TypeError(msg)
        }

        if ('function' == typeof options) {
          callback = options;
          options = undefined;
        }

        var fields;
        if (options) {
          fields = options.select;
          options.select = undefined;
        }

        var query = new Query(conditions, options);
        query.bind(this, 'findOneAndRemove');
        query.select(fields);

        if ('undefined' == typeof callback)
          return query;

        this._applyNamedScope(query);
        return query.findOneAndRemove(callback);
      }

  #### Parameters:

  - `conditions` <Object>
  - `[options]` <Object>
  - `[callback]` <Function>

  #### Returns:

  - <Query>

  #### See:

  - mongodb

  Finds a matching document, removes it, passing the found document (if any) to the callback.

  Executes immediately if `callback` is passed else a Query object is returned.

  #### Options:

  - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update

  #### Examples:

      A.findOneAndRemove(conditions, options, callback) // executes
      A.findOneAndRemove(conditions, options)  // return Query
      A.findOneAndRemove(conditions, callback) // executes
      A.findOneAndRemove(conditions) // returns Query
      A.findOneAndRemove()           // returns Query

  ### Model.findByIdAndRemove(`id`, `[options]`, `[callback]`)

  Issue a mongodb findAndModify remove command by a documents id.

  show code

      Model.findByIdAndRemove = function (id, options, callback) {
        if (1 === arguments.length && 'function' == typeof id) {
          var msg = 'Model.findByIdAndRemove(): First argument must not be a function.

      '
                    + '  ' + this.modelName + '.findByIdAndRemove(id, callback)
      '
                    + '  ' + this.modelName + '.findByIdAndRemove(id)
      '
                    + '  ' + this.modelName + '.findByIdAndRemove()
      ';
          throw new TypeError(msg)
        }

        return this.findOneAndRemove({ _id: id }, options, callback);
      }

  #### Parameters:

  - `id` <ObjectId, HexString> ObjectId or string that can be cast to one
  - `[options]` <Object>
  - `[callback]` <Function>

  #### Returns:

  - <Query>

  #### See:

  - Model.findOneAndRemove
  - mongodb

  Finds a matching document, removes it, passing the found document (if any) to the callback.

  Executes immediately if `callback` is passed, else a `Query` object is returned.

  #### Options:

  - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update

  #### Examples:

      A.findByIdAndRemove(id, options, callback) // executes
      A.findByIdAndRemove(id, options)  // return Query
      A.findByIdAndRemove(id, callback) // executes
      A.findByIdAndRemove(id) // returns Query
      A.findByIdAndRemove()           // returns Query

  ### Model.create(`doc`, `fn`)

  Shortcut for creating a new Document that is automatically saved to the db if valid.

  show code

      Model.create = function create (doc, fn) {
        if (1 === arguments.length) {
          return 'function' === typeof doc && doc(null);
        }

        var self = this
          , docs = [null]
          , promise
          , count
          , args

        if (Array.isArray(doc)) {
          args = doc;
        } else {
          args = utils.args(arguments, 0, arguments.length - 1);
          fn = arguments[arguments.length - 1];
        }

        if (0 === args.length) return fn(null);

        promise = new Promise(fn);
        count = args.length;

        args.forEach(function (arg, i) {
          var doc = new self(arg);
          docs[i+1] = doc;
          doc.save(function (err) {
            if (err) return promise.error(err);
            --count || fn.apply(null, docs);
          });
        });

        // TODO
        // utilize collection.insertAll for batch processing?
      };

  #### Parameters:

  - `doc` <Array, Object...>
  - `fn` <Function> callback

  #### Example:

      Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {
        if (err) // ...
      });

      var array = [{ type: 'jelly bean' }, { type: 'snickers' }];
      Candy.create(array, function (err, jellybean, snickers) {
        if (err) // ...
      });

  ### Model.update(`conditions`, `update`, `[options]`, `[callback]`)

  Updates documents in the database without returning them.

  show code

      Model.update = function update (conditions, doc, options, callback) {
        if (arguments.length < 4) {
          if ('function' === typeof options) {
            // Scenario: update(conditions, doc, callback)
            callback = options;
            options = null;
          } else if ('function' === typeof doc) {
            // Scenario: update(doc, callback);
            callback = doc;
            doc = conditions;
            conditions = {};
            options = null;
          }
        }

        var query = new Query(conditions, options).bind(this, 'update', doc);

        if ('undefined' == typeof callback)
          return query;

        this._applyNamedScope(query);
        return query.update(doc, callback);
      };

  #### Parameters:

  - `conditions` <Object>
  - `update` <Object>
  - `[options]` <Object>
  - `[callback]` <Function>

  #### Returns:

  - <Query>

  #### Examples:

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

  #### Valid options:

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

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

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

  - `err` is the error if any occurred
  - `numberAffected` is the count of updated documents Mongo reported
  - `rawResponse` is the full response from Mongo

  #### Note:

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

  #### Example:

      var query = { name: 'borne' };
      Model.update(query, { name: 'jason borne' }, options, callback)

      // is sent as
      Model.update(query, { $set: { name: 'jason borne' }}, options, callback)

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

  #### Note:

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

  - defaults
  - setters
  - validators
  - middleware

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

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

  ### Model.mapReduce(`o`, `callback`)

  Executes a mapReduce command.

  show code

      Model.mapReduce = function mapReduce (o, callback) {
        if ('function' != typeof callback) throw new Error('missing callback');

        var self = this;

        if (!Model.mapReduce.schema) {
          var opts = { noId: true, noVirtualId: true, strict: false }
          Model.mapReduce.schema = new Schema({}, opts);
        }

        if (!o.out) o.out = { inline: 1 };

        o.map = String(o.map);
        o.reduce = String(o.reduce);

        this.collection.mapReduce(null, null, o, function (err, ret, stats) {
          if (err) return callback(err);

          if (ret.findOne && ret.mapReduce) {
            // returned a collection, convert to Model
            var model = Model.compile(
                '_mapreduce_' + ret.collectionName
              , Model.mapReduce.schema
              , ret.collectionName
              , self.db
              , self.base);

            model._mapreduce = true;

            return callback(err, model, stats);
          }

          callback(err, ret, stats);
        });
      }

  #### Parameters:

  - `o` <Object> an object specifying map-reduce options
  - `callback` <Function>

  #### See:

  - http://www.mongodb.org/display/DOCS/MapReduce

  `o` is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.

  #### Example:

      var o = {};
      o.map = function () { emit(this.name, 1) }
      o.reduce = function (k, vals) { return vals.length }
      User.mapReduce(o, function (err, results) {
        console.log(results)
      })

  #### Other options:

  - `query` {Object} query filter object.
  - `limit` {Number} max number of documents
  - `keeptemp` {Boolean, default:false} keep temporary data
  - `finalize` {Function} finalize function
  - `scope` {Object} scope variables exposed to map/reduce/finalize during execution
  - `jsMode` {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
  - `verbose` {Boolean, default:false} provide statistics on job execution time.
  - `out*` {Object, default: {inline:1}} sets the output target for the map reduce job.

  #### * out options:

  - `{inline:1}` the results are returned in an array
  - `{replace: 'collectionName'}` add the results to collectionName: the results replace the collection
  - `{reduce: 'collectionName'}` add the results to collectionName: if dups are detected, uses the reducer / finalize functions
  - `{merge: 'collectionName'}` add the results to collectionName: if dups exist the new docs overwrite the old

  If `options.out` is set to `replace`, `merge`, or `reduce`, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the `lean` option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).

  #### Example:

      var o = {};
      o.map = function () { emit(this.name, 1) }
      o.reduce = function (k, vals) { return vals.length }
      o.out = { replace: 'createdCollectionNameForResults' }
      o.verbose = true;
      User.mapReduce(o, function (err, model, stats) {
        console.log('map reduce took %d ms', stats.processtime)
        model.find().where('value').gt(10).exec(function (err, docs) {
          console.log(docs);
        });
      })

  ### Model#base

  Base Mongoose instance the model uses.

  ### Model#collection

  Collection the model uses.

  ### Model#db

  Database instance the model uses.

  ### Model#schema

  Schema the model uses.

  ### Model#modelName

  The name of the model

  ### Model#collection

  Collection the model uses.

  ### Model#db

  Connection the model uses.

- namedscope.js

  ### NamedScope#decorate(`target`, `getters`)

  Decorate

  show code

      NamedScope.prototype.decorate = function (target, getters) {
        var name = this.name
          , block = this.block
          , query = this.query;
        if (block) {
          if (block.length === 0) {
            Object.defineProperty(target, name, {
              get: getters.block0(block)
            });
          } else {
            target[name] = getters.blockN(block);
          }
        } else {
          Object.defineProperty(target, name, {
            get: getters.basic(query)
          });
        }
      };

      NamedScope.prototype.compile = function (model) {
        var allScopes = this.scopesByName
          , scope;
        for (var k in allScopes) {
          scope = allScopes[k];
          scope.decorate(model, {
            block0: function (block) {
              return function () {
                var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
                block.call(cquery);
                return this;
              };
            },
            blockN: function (block) {
              return function () {
                var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
                block.apply(cquery, arguments);
                return this;
              };
            },
            basic: function (query) {
              return function () {
                var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
                cquery.find(query);
                return this;
              };
            }
          });
        }
      };

      module.exports = NamedScope;

  #### Parameters:

  - `target` <NamedScope>
  - `getters` <Object>

- promise.js

  ### Promise(`back`)

  Promise constructor.

  show code

      function Promise (back) {
        this.emitted = {};
        if ('function' == typeof back)
          this.addBack(back);
      };

  #### Parameters:

  - `back` <Function> a callback+errback that accepts `fn(err, ...){}` as signature

  #### Inherits:

  - NodeJS EventEmitter

  #### Events:

  - `err`: Emits when the promise resolves to an error.

  - `complete`: Emits when the promise resolves sucessfully.

  ### Promise#on(`event`, `callback`)

  Adds `listener` to the `event`.

  show code

      Promise.prototype.on = function (event, callback) {
        if (this.emitted[event])
          callback.apply(this, this.emitted[event]);
        else
          EventEmitter.prototype.on.call(this, event, callback);

        return this;
      };

  #### Parameters:

  - `event` <Event>
  - `callback` <Function>

  #### Returns:

  - <Promise> this

  If `event` is either `error` or `complete` and the event has already been emitted, the`listener` is called immediately and passed the results of the original emitted event.

  ### Promise#emit()

  Keeps track of emitted events to run them on `on`.

  show code

      Promise.prototype.emit = function (event) {
        // ensures a promise can't be complete() or error() twice
        if (event == 'err' || event == 'complete'){
          if (this.emitted.err || this.emitted.complete) {
            return this;
          }
          this.emitted[event] = util.args(arguments, 1);
        }

        return EventEmitter.prototype.emit.apply(this, arguments);
      };

  ### Promise#complete()

  Shortcut for emitting the `complete` event.

  show code

      Promise.prototype.complete = function () {
        var args = util.args(arguments);
        return this.emit.apply(this, ['complete'].concat(args));
      };

  ### Promise#error()

  Shortcut for emitting the `err` event.

  show code

      Promise.prototype.error = function (err) {
        if (!(err instanceof Error)) err = new Error(err);
        return this.emit('err', err);
      };

  #### Returns:

  - <Promise>

  ### Promise#addCallback()

  Shortcut for `.on('complete', fn)`.

  show code

      Promise.prototype.addCallback = function (fn) {
        return this.on('complete', fn);
      };

  #### Returns:

  - <Promise>

  ### Promise#addErrback()

  Shortcut for `.on('err', fn)`.

  show code

      Promise.prototype.addErrback = function (fn) {
        return this.on('err', fn);
      };

  #### Returns:

  - <Promise>

  ### Promise#addBack(`fn`)

  Adds a single function that's both a callback and errback.

  show code

      Promise.prototype.addBack = function (fn) {
        this.on('err', function(err){
          fn.call(this, err);
        });

        this.on('complete', function(){
          var args = util.args(arguments);
          fn.apply(this, [null].concat(args));
        });

        return this;
      };

  #### Parameters:

  - `fn` <Function>

  #### Returns:

  - <Promise>

  ### Promise#resolve(`err`, `val`)

  Sugar for handling cases where you may be resolving to either an error condition or a success condition.

  show code

      Promise.prototype.resolve = function (err, val) {
        if (err) return this.error(err);
        return this.complete(val);
      };

  #### Parameters:

  - `err` <Error> optional error or null
  - `val` <Object> value to complete the promise with

- query.js

  ### Query(`criteria`, `options`)

  Query constructor used for building queries.

  show code

      function Query (criteria, options) {
        this.setOptions(options, true);
        this._conditions = {};
        this._updateArg = {};
        if (criteria) this.find(criteria);
      }

  #### Parameters:

  - `criteria` <Object>
  - `options` <Object>

  #### Example:

      var query = Model.find();
      query.where('age').gte(21).exec(callback);

  ### Query#setOptions(`options`)

  Sets query options.

  show code

      Query.prototype.setOptions = function (options, overwrite) {
        // overwrite is internal use only
        if (overwrite) {
          options = this.options = options || {};
          this.safe = options.safe

          // normalize population options
          var pop = this.options.populate;
          this.options.populate = {};

          if (pop && Array.isArray(pop)) {
            for (var i = 0, l = pop.length; i < l; i++) {
              this.options.populate[pop[i]] = {};
            }
          }

          return this;
        }

        if (!(options && 'Object' == options.constructor.name))
          return this;

        if ('safe' in options)
          this.safe = options.safe;

        // set arbitrary options
        var methods = Object.keys(options)
          , i = methods.length
          , method

        while (i--) {
          method = methods[i];

          // use methods if exist (safer option manipulation)
          if ('function' == typeof this[method]) {
            var args = Array.isArray(options[method])
              ? options[method]
              : [options[method]];
            this[method].apply(this, args)
          } else {
            this.options[method] = options[method];
          }
        }
        return this;
      }

  #### Parameters:

  - `options` <Object>

  #### Options:

  - tailable *
  - sort *
  - limit *
  - skip *
  - maxscan *
  - batchSize *
  - comment *
  - snapshot *
  - hint *
  - slaveOk *
  - lean *
  - safe

  * denotes a query helper method is also available

  ### Query#bind(`model`, `op`, `updateArg`)

  Binds this query to a model.

  show code

      Query.prototype.bind = function bind (model, op, updateArg) {
        this.model = model;
        this.op = op;

        if (model._mapreduce) this.options.lean = true;

        if (op == 'update' || op == 'findOneAndUpdate') {
          merge(this._updateArg, updateArg || {});
        }

        return this;
      };

  #### Parameters:

  - `model` <Model> the model to which the query is bound
  - `op` <String> the operation to execute
  - `updateArg` <Object> used in update methods

  #### Returns:

  - <Query>

  ### Query#exec(`[operation]`, `[callback]`)

  Executes the query

  show code

      Query.prototype.exec = function exec (op, callback) {
        var promise = new Promise();

        switch (typeof op) {
          case 'function':
            callback = op;
            op = null;
            break;
          case 'string':
            this.op = op;
            break;
        }

        if (callback) promise.addBack(callback);

        if (!this.op) {
          promise.complete();
          return promise;
        }

        if ('update' == this.op) {
          this[this.op](this._updateArg, promise.resolve.bind(promise));
          return promise;
        }

        if ('distinct' == this.op) {
          this.distinct(this._distinctArg, promise.resolve.bind(promise));
          return promise;
        }

        this[this.op](promise.resolve.bind(promise));
        return promise;
      };

  #### Parameters:

  - `[operation]` <String, Function>
  - `[callback]` <Function>

  #### Returns:

  - <Promise>

  #### Examples

      query.exec();
      query.exec(callback);
      query.exec('update');
      query.exec('find', callback);

  ### Query#find(`[criteria]`, `[callback]`)

  Finds documents.

  show code

      Query.prototype.find = function (criteria, callback) {
        this.op = 'find';
        if ('function' === typeof criteria) {
          callback = criteria;
          criteria = {};
        } else if (criteria instanceof Query) {
          // TODO Merge options, too
          merge(this._conditions, criteria._conditions);
        } else if (criteria instanceof Document) {
          merge(this._conditions, criteria.toObject());
        } else if (criteria && 'Object' === criteria.constructor.name) {
          merge(this._conditions, criteria);
        }
        if (!callback) return this;
        return this.execFind(callback);
      };

  #### Parameters:

  - `[criteria]` <Object> mongodb selector
  - `[callback]` <Function>

  #### Returns:

  - <Query> this

  When no `callback` is passed, the query is not executed.

  #### Example

      query.find({ name: 'Los Pollos Hermanos' }).find(callback)

  ### Query#cast(`model`, `[obj]`)

  Casts this query to the schema of `model`

  show code

      Query.prototype.cast = function (model, obj) {
        obj || (obj= this._conditions);

        var schema = model.schema
          , paths = Object.keys(obj)
          , i = paths.length
          , any$conditionals
          , schematype
          , nested
          , path
          , type
          , val;

        while (i--) {
          path = paths[i];
          val = obj[path];

          if ('$or' === path || '$nor' === path) {
            var k = val.length
              , orComponentQuery;

            while (k--) {
              orComponentQuery = new Query(val[k]);
              orComponentQuery.cast(model);
              val[k] = orComponentQuery._conditions;
            }

          } else if (path === '$where') {
            type = typeof val;

            if ('string' !== type && 'function' !== type) {
              throw new Error("Must have a string or function for $where");
            }

            if ('function' === type) {
              obj[path] = val.toString();
            }

            continue;

          } else {

            if (!schema) {
              // no casting for Mixed types
              continue;
            }

            schematype = schema.path(path);

            if (!schematype) {
              // Handle potential embedded array queries
              var split = path.split('.')
                , j = split.length
                , pathFirstHalf
                , pathLastHalf
                , remainingConds
                , castingQuery;

              // Find the part of the var path that is a path of the Schema
              while (j--) {
                pathFirstHalf = split.slice(0, j).join('.');
                schematype = schema.path(pathFirstHalf);
                if (schematype) break;
              }

              // If a substring of the input path resolves to an actual real path...
              if (schematype) {
                // Apply the casting; similar code for $elemMatch in schema/array.js
                if (schematype.caster && schematype.caster.schema) {
                  remainingConds = {};
                  pathLastHalf = split.slice(j).join('.');
                  remainingConds[pathLastHalf] = val;
                  castingQuery = new Query(remainingConds);
                  castingQuery.cast(schematype.caster);
                  obj[path] = castingQuery._conditions[pathLastHalf];
                } else {
                  obj[path] = val;
                }
              }

            } else if (val === null || val === undefined) {
              continue;
            } else if ('Object' === val.constructor.name) {

              any$conditionals = Object.keys(val).some(function (k) {
                return k.charAt(0) === '$' && k !== '$id' && k !== '$ref';
              });

              if (!any$conditionals) {
                obj[path] = schematype.castForQuery(val);
              } else {

                var ks = Object.keys(val)
                  , k = ks.length
                  , $cond;

                while (k--) {
                  $cond = ks[k];
                  nested = val[$cond];

                  if ('$exists' === $cond) {
                    if ('boolean' !== typeof nested) {
                      throw new Error("$exists parameter must be Boolean");
                    }
                    continue;
                  }

                  if ('$type' === $cond) {
                    if ('number' !== typeof nested) {
                      throw new Error("$type parameter must be Number");
                    }
                    continue;
                  }

                  if ('$not' === $cond) {
                    this.cast(model, nested);
                  } else {
                    val[$cond] = schematype.castForQuery($cond, nested);
                  }
                }
              }
            } else {
              obj[path] = schematype.castForQuery(val);
            }
          }
        }

        return obj;
      };

  #### Parameters:

  - `model` <Model>
  - `[obj]` <Object>

  #### Returns:

  - <Object>

  #### Note

  If `obj` is present, it is cast instead of this query.

  ### Query#_optionsForExec(`model`)

  Returns default options.

  show code

      Query.prototype._optionsForExec = function (model) {
        var options = utils.clone(this.options, { retainKeyOrder: true });
        delete options.populate;
        if (! ('safe' in options)) options.safe = model.schema.options.safe;
        return options;
      };

  #### Parameters:

  - `model` <Model>

  ### Query#_applyPaths()

  Applies schematype selected options to this query.

  show code

      Query.prototype._applyPaths = function applyPaths () {
        // determine if query is selecting or excluding fields

        var fields = this._fields
          , exclude
          , keys
          , ki

        if (fields) {
          keys = Object.keys(fields);
          ki = keys.length;

          while (ki--) {
            if ('+' == keys[ki][0]) continue;
            exclude = 0 === fields[keys[ki]];
            break;
          }
        }

        // if selecting, apply default schematype select:true fields
        // if excluding, apply schematype select:false fields

        var selected = []
          , excluded = []
          , seen = [];

        analyzeSchema(this.model.schema);

        switch (exclude) {
          case true:
            excluded.length && this.select('-' + excluded.join(' -'));
            break;
          case false:
            selected.length && this.select(selected.join(' '));
            break;
          case undefined:
            // user didn't specify fields, implies returning all fields.
            // only need to apply excluded fields
            excluded.length && this.select('-' + excluded.join(' -'));
            break;
        }

        return seen = excluded = selected = keys = fields = null;

        function analyzeSchema (schema, prefix) {
          prefix || (prefix = '');

          // avoid recursion
          if (~seen.indexOf(schema)) return;
          seen.push(schema);

          schema.eachPath(function (path, type) {
            if (prefix) path = prefix + '.' + path;

            // array of subdocs?
            if (type.schema) {
              analyzeSchema(type.schema, path);
            }

            analyzePath(path, type);
          });
        }

        function analyzePath (path, type) {
          if ('boolean' != typeof type.selected) return;

          if (fields && ('+' + path) in fields) {
            // forced inclusion
            delete fields['+' + path];

            // if there are other fields being included, add this one
            // if no other included fields, leave this out (implied inclusion)
            if (false === exclude && keys.length > 1) {
              fields[path] = 1;
            }

            return
          };

          ;(type.selected ? selected : excluded).push(path);
        }
      }

  ### Query#$where(`js`)

  Specifies a `$where` condition

  #### Parameters:

  - `js` <String, Function> javascript string or function

  #### Returns:

  - <Query> this

  Use `$where` when you need to select documents using a JavaScript expression.

  #### Example

      query.$where('this.comments.length &gt; 10 || this.name.length &gt; 5')

      query.$where(function () {
        return this.comments.length &gt; 10 || this.name.length &gt; 5;
      })

  ### Query#where(`[path]`, `[val]`)

  Specifies a `path` for use with chaining.

  show code

      Query.prototype.where = function (path, val) {
        if (!arguments.length) return this;

        if ('string' != typeof path) {
          throw new TypeError('path must be a string');
        }

        this._currPath = path;

        if (2 === arguments.length) {
          this._conditions[path] = val;
        }

        return this;
      };

  #### Parameters:

  - `[path]` <String>
  - `[val]` <Object>

  #### 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);

      // Moreover, you can also chain a bunch of these together:

      User
      .where('age').gte(21).lte(65)
      .where('name', /^b/i)
      .where('friends').slice(10)
      .exec(callback)

  ### Query#equals(`val`)

  Specifies the complementary comparison value for paths specified with `where()`

  show code

      Query.prototype.equals = function equals (val) {
        var path = this._currPath;
        if (!path) throw new Error('equals() must be used after where()');
        this._conditions[path] = val;
        return this;
      }

  #### Parameters:

  - `val` <Object>

  #### Returns:

  - <Query> this

  #### Example

      User.where('age').equals(49);

      // is the same as

      User.where('age', 49);

  ### Query#or(`array`)

  Specifies arguments for an `$or` condition.

  show code

      Query.prototype.or = function or (array) {
        var or = this._conditions.$or || (this._conditions.$or = []);
        if (!Array.isArray(array)) array = [array];
        or.push.apply(or, array);
        return this;
      }

  #### Parameters:

  - `array` <Array> array of conditions

  #### Returns:

  - <Query> this

  #### Example

      query.or([{ color: 'red' }, { status: 'emergency' }])

  ### Query#nor(`array`)

  Specifies arguments for a `$nor` condition.

  show code

      Query.prototype.nor = function nor (array) {
        var nor = this._conditions.$nor || (this._conditions.$nor = []);
        if (!Array.isArray(array)) array = [array];
        nor.push.apply(nor, array);
        return this;
      }

  #### Parameters:

  - `array` <Array> array of conditions

  #### Returns:

  - <Query> this

  #### Example

      query.nor([{ color: 'green' }, { status: 'ok' }])

  ### Query#gt(`path`, `val`)

  Specifies a $gt query condition.

  #### Parameters:

  - `path` <String>
  - `val` <Number>

  When called with one argument, the most recent path passed to `where()` is used.

  #### Example

      Thing.find().where('age').gt(21)

      // or
      Thing.find().gt('age', 21)

  ### Query#gte(`path`, `val`)

  Specifies a $gte query condition.

  #### Parameters:

  - `path` <String>
  - `val` <Number>

  When called with one argument, the most recent path passed to `where()` is used.

  ### Query#lt(`path`, `val`)

  Specifies a $lt query condition.

  #### Parameters:

  - `path` <String>
  - `val` <Number>

  When called with one argument, the most recent path passed to `where()` is used.

  ### Query#lte(`path`, `val`)

  Specifies a $lte query condition.

  #### Parameters:

  - `path` <String>
  - `val` <Number>

  When called with one argument, the most recent path passed to `where()` is used.

  ### Query#ne(`path`, `val`)

  Specifies a $ne query condition.

  #### Parameters:

  - `path` <String>
  - `val` <Number>

  When called with one argument, the most recent path passed to `where()` is used.

  ### Query#in(`path`, `val`)

  Specifies an $in query condition.

  #### Parameters:

  - `path` <String>
  - `val` <Number>

  When called with one argument, the most recent path passed to `where()` is used.

  ### Query#nin(`path`, `val`)

  Specifies an $nin query condition.

  #### Parameters:

  - `path` <String>
  - `val` <Number>

  When called with one argument, the most recent path passed to `where()` is used.

  ### Query#all(`path`, `val`)

  Specifies an $all query condition.

  #### Parameters:

  - `path` <String>
  - `val` <Number>

  When called with one argument, the most recent path passed to `where()` is used.

  ### Query#size(`path`, `val`)

  Specifies an $size query condition.

  #### Parameters:

  - `path` <String>
  - `val` <Number>

  When called with one argument, the most recent path passed to `where()` is used.

  ### Query#regex(`path`, `val`)

  Specifies a $regex query condition.

  #### Parameters:

  - `path` <String>
  - `val` <Number>

  When called with one argument, the most recent path passed to `where()` is used.

  ### Query#maxDistance(`path`, `val`)

  Specifies a $maxDistance query condition.

  #### Parameters:

  - `path` <String>
  - `val` <Number>

  When called with one argument, the most recent path passed to `where()` is used.

  ### Query#near(`path`, `val`)

  Specifies a `$near` condition

  show code

      Query.prototype.near = function (path, val) {
        if (arguments.length === 1) {
          val = path;
          path = this._currPath
        } else if (arguments.length === 2 && !Array.isArray(val)) {
          val = utils.args(arguments);
          path = this._currPath;
        } else if (arguments.length === 3) {
          val = utils.args(arguments, 1);
        }
        var conds = this._conditions[path] || (this._conditions[path] = {});
        conds.$near = val;
        return this;
      }

  #### Parameters:

  - `path` <String>
  - `val` <Number>

  #### Returns:

  - <Query> this

  #### See:

  - http://www.mongodb.org/display/DOCS/Geospatial+Indexing

  ### Query#nearSphere(`path`, `val`)

  Specifies a `$nearSphere` condition.

  show code

      Query.prototype.nearSphere = function (path, val) {
        if (arguments.length === 1) {
          val = path;
          path = this._currPath
        } else if (arguments.length === 2 && !Array.isArray(val)) {
          val = utils.args(arguments);
          path = this._currPath;
        } else if (arguments.length === 3) {
          val = utils.args(arguments, 1);
        }
        var conds = this._conditions[path] || (this._conditions[path] = {});
        conds.$nearSphere = val;
        return this;
      }

  #### Parameters:

  - `path` <String>
  - `val` <Object>

  #### Returns:

  - <Query> this

  #### See:

  - http://www.mongodb.org/display/DOCS/Geospatial+Indexing

  ### Query#mod(`path`, `val`)

  Specifies a `$mod` condition

  show code

      Query.prototype.mod = function (path, val) {
        if (arguments.length === 1) {
          val = path;
          path = this._currPath
        } else if (arguments.length === 2 && !Array.isArray(val)) {
          val = utils.args(arguments);
          path = this._currPath;
        } else if (arguments.length === 3) {
          val = utils.args(arguments, 1);
        }
        var conds = this._conditions[path] || (this._conditions[path] = {});
        conds.$mod = val;
        return this;
      }

  #### Parameters:

  - `path` <String>
  - `val` <Number>

  #### Returns:

  - <Query> this

  ### Query#exists(`path`, `val`)

  Specifies an `$exists` condition

  show code

      Query.prototype.exists = function (path, val) {
        if (arguments.length === 0) {
          path = this._currPath
          val = true;
        } else if (arguments.length === 1) {
          if ('boolean' === typeof path) {
            val = path;
            path = this._currPath;
          } else {
            val = true;
          }
        }
        var conds = this._conditions[path] || (this._conditions[path] = {});
        conds['$exists'] = val;
        return this;
      };

  #### Parameters:

  - `path` <String>
  - `val` <Number>

  #### Returns:

  - <Query> this

  ### Query#elemMatch(`path`, `criteria`)

  Specifies an `$elemMatch` condition

  show code

      Query.prototype.elemMatch = function (path, criteria) {
        var block;
        if ('Object' === path.constructor.name) {
          criteria = path;
          path = this._currPath;
        } else if ('function' === typeof path) {
          block = path;
          path = this._currPath;
        } else if ('Object' === criteria.constructor.name) {
        } else if ('function' === typeof criteria) {
          block = criteria;
        } else {
          throw new Error("Argument error");
        }
        var conds = this._conditions[path] || (this._conditions[path] = {});
        if (block) {
          criteria = new Query();
          block(criteria);
          conds['$elemMatch'] = criteria._conditions;
        } else {
          conds['$elemMatch'] = criteria;
        }
        return this;
      };

      // Spatial queries

  #### Parameters:

  - `path` <String, Object, Function>
  - `criteria` <Object, Function>

  #### Returns:

  - <Query> this

  #### Example

      query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})

      query.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})

      query.elemMatch('comment', function (elem) {
        elem.where('author').equals('autobot');
        elem.where('votes').gte(5);
      })

      query.where('comment').elemMatch(function (elem) {
        elem.where('author').equals('autobot');
        elem.where('votes').gte(5);
      })

  ### Query#box(`path`, `val`)

  Specifies a $box condition

  show code

      Query.prototype.box = function (path, val) {
        if (arguments.length === 1) {
          val = path;
          path = this._currPath;
        }
        var conds = this._conditions[path] || (this._conditions[path] = {});
        conds['$within'] = { '$box': [val.ll, val.ur]  };
        return this;
      };

  #### Parameters:

  - `path` <String>
  - `val` <Object>

  #### Returns:

  - <Query> this

  #### See:

  - http://www.mongodb.org/display/DOCS/Geospatial+Indexing
  - Query#within

  #### Example

      var lowerLeft = [40.73083, -73.99756]
      var upperRight= [40.741404,  -73.988135]
      query.where('loc').within.box({ ll: lowerLeft , ur: upperRight })

  ### Query#center(`path`, `val`, `[opts]`)

  Specifies a $center condition

  show code

      Query.prototype.center = function (path, val, opts) {
        if (arguments.length === 1) {
          val = path;
          path = this._currPath;
        }
        var conds = this._conditions[path] || (this._conditions[path] = {});
        conds['$within'] = { '$center': [val.center, val.radius]  };

        // copy any options
        if (opts && 'Object' == opts.constructor.name) {
          utils.options(opts, conds.$within);
        }

        return this;
      };

  #### Parameters:

  - `path` <String>
  - `val` <Object>
  - `[opts]` <Object> options e.g. { $uniqueDocs: true }

  #### Returns:

  - <Query> this

  #### See:

  - http://www.mongodb.org/display/DOCS/Geospatial+Indexing

  #### Example

      var area = { center: [50, 50], radius: 10 }
      query.where('loc').within.center(area)

  ### Query#centerSphere(`path`, `val`)

  Specifies a $centerSphere condition

  show code

      Query.prototype.centerSphere = function (path, val) {
        if (arguments.length === 1) {
          val = path;
          path = this._currPath;
        }
        var conds = this._conditions[path] || (this._conditions[path] = {});
        conds['$within'] = { '$centerSphere': [val.center, val.radius]  };
        return this;
      };

  #### Parameters:

  - `path` <String>
  - `val` <Object>

  #### Returns:

  - <Query> this

  #### See:

  - http://www.mongodb.org/display/DOCS/Geospatial+Indexing

  #### Example

      var area = { center: [50, 50], radius: 10 }
      query.where('loc').within.centerSphere(area)

  ### Query#polygon(`path`, `val`)

  Specifies a $polygon condition

  show code

      Query.prototype.polygon = function (path, val) {
        if (arguments.length === 1) {
          val = path;
          path = this._currPath;
        }
        var conds = this._conditions[path] || (this._conditions[path] = {});
        conds['$within'] = { '$polygon': val };
        return this;
      };

  #### Parameters:

  - `path` <String>
  - `val` <Array, Object>

  #### Returns:

  - <Query> this

  #### See:

  - http://www.mongodb.org/display/DOCS/Geospatial+Indexing

  #### Example

      var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]
      query.where('loc').within.polygon(polyA)

      // or
      var polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }
      query.where('loc').within.polygon(polyB)

  ### Query#select(`arg`)

  Specifies which document fields to include or exclude

  show code

      Query.prototype.select = function select (arg) {
        if (!arg) return this;

        var fields = this._fields || (this._fields = {});

        if ('Object' === arg.constructor.name) {
          Object.keys(arg).forEach(function (field) {
            fields[field] = arg[field];
          });
        } else if (1 === arguments.length && 'string' == typeof arg) {
          arg.split(/\s+/).forEach(function (field) {
            if (!field) return;
            var include = '-' == field[0] ? 0 : 1;
            if (include === 0) field = field.substring(1);
            fields[field] = include;
          });
        } else {
          throw new TypeError('Invalid select() argument. Must be a string or object.');
        }

        return this;
      };

  #### Parameters:

  - `arg` <Object, String>

  #### Returns:

  - <Query> this

  #### See:

  - SchemaType

  When using string syntax, prefixing a path with `-` will flag that path as excluded. When a path does not have the `-` prefix, it is included. Lastly, if a path is prefixed with `+`, it forces inclusion of the path, which is useful for paths excluded at the schema level.

  #### Example

      // include a and b, exclude c
      query.select('a b -c');

      // or you may use object notation, useful when
      // you have keys already prefixed with a "-"
      query.select({a: 1, b: 1, c: 0});

      // force inclusion of field excluded at schema level
      query.select('+path')

  ### Query#slice(`path`, `val`)

  Specifies a $slice condition

  show code

      Query.prototype.slice = function (path, val) {
        if (arguments.length === 1) {
            val = path;
            path = this._currPath
        } else if (arguments.length === 2) {
          if ('number' === typeof path) {
            val = [path, val];
            path = this._currPath;
          }
        } else if (arguments.length === 3) {
          val = utils.args(arguments, 1);
        }
        var myFields = this._fields || (this._fields = {});
        myFields[path] = { '$slice': val };
        return this;
      };

  #### Parameters:

  - `path` <String>
  - `val` <Number> number of elements to slice

  #### Returns:

  - <Query> this

  #### See:

  - mongodb

  #### Example

      query.slice('comments', 5)
      query.slice('comments', -5)
      query.slice('comments', [10, 5])
      query.where('comments').slice(5)
      query.where('comments').slice([-10, 5])

  ### Query#sort(`arg`)

  Sets the sort order

  show code

      Query.prototype.sort = function (arg) {
        if (!arg) return this;

        var sort = this.options.sort || (this.options.sort = []);

        if ('Object' === arg.constructor.name) {
          Object.keys(arg).forEach(function (field) {
            push(sort, field, arg[field]);
          });
        } else if (1 === arguments.length && 'string' == typeof arg) {
          arg.split(/\s+/).forEach(function (field) {
            if (!field) return;
            var ascend = '-' == field[0] ? -1 : 1;
            if (ascend === -1) field = field.substring(1);
            push(sort, field, ascend);
          });
        } else {
          throw new TypeError('Invalid sort() argument. Must be a string or object.');
        }

        return this;
      };

  #### Parameters:

  - `arg` <Object, String>

  #### Returns:

  - <Query> this

  If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.

  If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with `-` which will be treated as descending.

  #### Example

      // these are equivalent
      query.sort({ field: 'asc', test: -1 });
      query.sort('field -test');

  ### Query#limit(`val`)

  Specifies the limit option.

  #### Parameters:

  - `val` <Number>

  #### See:

  - mongodb

  #### Example

      Kitten.find().limit(20)

  ### Query#skip(`val`)

  Specifies the skip option.

  #### Parameters:

  - `val` <Number>

  #### See:

  - mongodb

  #### Example

      Kitten.find().skip(100).limit(20)

  ### Query#maxscan(`val`)

  Specifies the maxscan option.

  #### Parameters:

  - `val` <Number>

  #### See:

  - mongodb

  #### Example

      Kitten.find().maxscan(100)

  ### Query#batchSize(`val`)

  Specifies the batchSize option.

  #### Parameters:

  - `val` <Number>

  #### See:

  - mongodb

  #### Example

      Kitten.find().batchSize(100)

  ### Query#comment(`val`)

  Specifies the `comment` option.

  #### Parameters:

  - `val` <Number>

  #### See:

  - mongodb

  #### Example

      Kitten.findOne(condition).comment('login query')

  ### Query#snapshot()

  Specifies this query as a `snapshot` query.

  show code

      Query.prototype.snapshot = function () {
        this.options.snapshot = true;
        return this;
      };

  #### Returns:

  - <Query> this

  #### See:

  - mongodb

  #### Example

      Kitten.find().snapshot()

  ### Query#hint(`val`)

  Sets query hints.

  show code

      Query.prototype.hint = function (val) {
        if (!val) return this;

        var hint = this.options.hint || (this.options.hint = {});

        if ('Object' === val.constructor.name) {
          // must keep object keys in order so don't use Object.keys()
          for (var k in val) {
            hint[k] = val[k];
          }
        } else {
          throw new TypeError('Invalid hint. ' + val);
        }

        return this;
      };

  #### Parameters:

  - `val` <Object> a hint object

  #### Returns:

  - <Query> this

  #### See:

  - mongodb

  #### Example

      Model.find().hint({ indexA: 1, indexB: -1})

  ### Query#slaveOk(`v`)

  Sets the slaveOk option.

  show code

      Query.prototype.slaveOk = function (v) {
        this.options.slaveOk = arguments.length ? !!v : true;
        return this;
      }

  #### Parameters:

  - `v` <Boolean> defaults to true

  #### Returns:

  - <Query> this

  #### See:

  - mongodb

  #### Example:

      new Query().slaveOk() // true
      new Query().slaveOk(true)
      new Query().slaveOk(false)

  ### Query#lean(`v`)

  Sets the lean option.

  show code

      Query.prototype.lean = function (v) {
        this.options.lean = arguments.length ? !!v : true;
        return this;
      }

  #### Parameters:

  - `v` <Boolean> defaults to true

  #### Returns:

  - <Query> this

  Documents returned from queries with the `lean` option enabled are plain javascript objects, not MongooseDocuments. They have no `save` method, getters/setters or any other Mongoose magic applied.

  This is a great option in high-performance read-only scenarios, especially when combined with the stream option.

  #### Example:

      new Query().lean() // true
      new Query().lean(true)
      new Query().lean(false)

      Model.find().lean().exec();

      var leanStream = Model.find().lean().stream();

  ### Query#tailable(`v`)

  Sets tailable option.

  show code

      Query.prototype.tailable = function (v) {
        this.options.tailable = arguments.length ? !!v : true;
        return this;
      };

  #### Parameters:

  - `v` <Boolean> defaults to true

  #### See:

  - mongodb

  #### Example

      Kitten.find().tailable() &lt;== true
      Kitten.find().tailable(true)
      Kitten.find().tailable(false)

  ### Query#execFind(`callback`)

  Executes the query as a find() operation.

  show code

      Query.prototype.execFind = function (callback) {
        var model = this.model
          , promise = new Promise(callback);

        try {
          this.cast(model);
        } catch (err) {
          promise.error(err);
          return this;
        }

        // apply default schematype path selections
        this._applyPaths();

        var self = this
          , castQuery = this._conditions
          , options = this._optionsForExec(model)

        var fields = utils.clone(options.fields = this._fields);

        model.collection.find(castQuery, options, function (err, cursor) {
          if (err) return promise.error(err);
          cursor.toArray(tick(cb));
        });

        function cb (err, docs) {
          if (err) return promise.error(err);

          if (true === options.lean)
            return promise.complete(docs);

          var arr = []
            , count = docs.length;

          if (!count) return promise.complete([]);

          for (var i = 0, l = docs.length; i < l; i++) {
            arr[i] = new model(undefined, fields, true);
            arr[i].init(docs[i], self, function (err) {
              if (err) return promise.error(err);
              --count || promise.complete(arr);
            });
          }
        }

        return this;
      };

  #### Parameters:

  - `callback` <Function>

  #### Returns:

  - <Query> this

  ### Query#findOne(`callback`)

  Executes the query as a findOne() operation.

  show code

      Query.prototype.findOne = function (callback) {
        this.op = 'findOne';

        if (!callback) return this;

        var model = this.model;
        var promise = new Promise(callback);

        try {
          this.cast(model);
        } catch (err) {
          promise.error(err);
          return this;
        }

        // apply default schematype path selections
        this._applyPaths();

        var self = this
          , castQuery = this._conditions
          , options = this._optionsForExec(model)

        var fields = utils.clone(options.fields = this._fields);

        model.collection.findOne(castQuery, options, tick(function (err, doc) {
          if (err) return promise.error(err);
          if (!doc) return promise.complete(null);

          if (true === options.lean) return promise.complete(doc);

          var casted = new model(undefined, fields, true);
          casted.init(doc, self, function (err) {
            if (err) return promise.error(err);
            promise.complete(casted);
          });
        }));

        return this;
      };

  #### Parameters:

  - `callback` <Function>

  #### Returns:

  - <Query> this

  #### Example

      Kitten.where('color', 'white').findOne(function (err, kitten) {
        if (err) return handleError(err);

        // kitten may be null if no document matched
        if (kitten) {
          ...
        }
      })

  ### Query#count(`callback`)

  Exectues the query as a count() operation.

  show code

      Query.prototype.count = function (callback) {
        this.op = 'count';
        var model = this.model;

        try {
          this.cast(model);
        } catch (err) {
          return callback(err);
        }

        var castQuery = this._conditions;
        model.collection.count(castQuery, tick(callback));

        return this;
      };

  #### Parameters:

  - `callback` <Function>

  #### Returns:

  - <Query> this

  #### See:

  - mongodb

  #### Example

      Kitten.where('color', 'black').count(function (err, count) {
        if (err) return handleError(err);
        console.log('there are %d black kittens', count);
      })

  ### Query#distinct(`field`, `callback`)

  Executes this query as a distict() operation.

  show code

      Query.prototype.distinct = function (field, callback) {
        this.op = 'distinct';
        var model = this.model;

        try {
          this.cast(model);
        } catch (err) {
          return callback(err);
        }

        var castQuery = this._conditions;
        model.collection.distinct(field, castQuery, tick(callback));

        return this;
      };

  #### Parameters:

  - `field` <String>
  - `callback` <Function>

  #### Returns:

  - <Query> this

  #### See:

  - mongodb

  ### Query#update(`doc`, `callback`)

  Executes this query as an update() operation.

  show code

      Query.prototype.update = function update (doc, callback) {
        this.op = 'update';
        this._updateArg = doc;

        var model = this.model
          , options = this._optionsForExec(model)
          , fn = 'function' == typeof callback
          , castedQuery
          , castedDoc

        castedQuery = castQuery(this);
        if (castedQuery instanceof Error) {
          if (fn) {
            process.nextTick(callback.bind(null, castedQuery));
            return this;
          }
          throw castedQuery;
        }

        castedDoc = castDoc(this);
        if (!castedDoc) {
          fn && process.nextTick(callback.bind(null, null, 0));
          return this;
        }

        if (castedDoc instanceof Error) {
          if (fn) {
            process.nextTick(callback.bind(null, castedDoc));
            return this;
          }
          throw castedDoc;
        }

        if (!fn) {
          delete options.safe;
        }

        model.collection.update(castedQuery, castedDoc, options, tick(callback));
        return this;
      };

  #### Parameters:

  - `doc` <Object> the update conditions
  - `callback` <Function>

  #### Returns:

  - <Query> this

  All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility.

  #### Example

      Model.update({..}, { title: 'remove words' }, ...)

  becomes

      Model.update({..}, { $set: { title: 'remove words' }}, ...)

  #### Note

  Passing an empty object `{}` as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.

  ### Query#_castUpdate(`obj`)

  Casts obj for an update command.

  show code

      Query.prototype._castUpdate = function _castUpdate (obj) {
        var ops = Object.keys(obj)
          , i = ops.length
          , ret = {}
          , hasKeys
          , val

        while (i--) {
          var op = ops[i];
          if ('$' !== op[0]) {
            // fix up $set sugar
            if (!ret.$set) {
              if (obj.$set) {
                ret.$set = obj.$set;
              } else {
                ret.$set = {};
              }
            }
            ret.$set[op] = obj[op];
            ops.splice(i, 1);
            if (!~ops.indexOf('$set')) ops.push('$set');
          } else if ('$set' === op) {
            if (!ret.$set) {
              ret[op] = obj[op];
            }
          } else {
            ret[op] = obj[op];
          }
        }

        // cast each value
        i = ops.length;

        while (i--) {
          op = ops[i];
          val = ret[op];
          if ('Object' === val.constructor.name) {
            hasKeys |= this._walkUpdatePath(val, op);
          } else {
            var msg = 'Invalid atomic update value for ' + op + '. '
                    + 'Expected an object, received ' + typeof val;
            throw new Error(msg);
          }
        }

        return hasKeys && ret;
      }

  #### Parameters:

  - `obj` <Object>

  #### Returns:

  - <Object> obj after casting its values

  ### Query#_walkUpdatePath(`obj`, `op`, `pref`)

  Walk each path of obj and cast its values
  according to its schema.

  show code

      Query.prototype._walkUpdatePath = function _walkUpdatePath (obj, op, pref) {
        var strict = this.model.schema.options.strict
          , prefix = pref ? pref + '.' : ''
          , keys = Object.keys(obj)
          , i = keys.length
          , hasKeys = false
          , schema
          , key
          , val

        while (i--) {
          key = keys[i];
          val = obj[key];

          if (val && 'Object' === val.constructor.name) {
            // watch for embedded doc schemas
            schema = this._getSchema(prefix + key);
            if (schema && schema.caster && op in castOps) {
              // embedded doc schema

              if (strict && !schema) {
                // path is not in our strict schema
                if ('throw' == strict) {
                  throw new Error('Field `' + key + '` is not in schema.');
                } else {
                  // ignore paths not specified in schema
                  delete obj[key];
                }
              } else {
                hasKeys = true;
                if ('$each' in val) {
                  obj[key] = {
                      $each: this._castUpdateVal(schema, val.$each, op)
                  }
                } else {
                  obj[key] = this._castUpdateVal(schema, val, op);
                }
              }
            } else {
              hasKeys |= this._walkUpdatePath(val, op, prefix + key);
            }
          } else {
            schema = '$each' === key
              ? this._getSchema(pref)
              : this._getSchema(prefix + key);

            var skip = strict &&
                       !schema &&
                       !/real|nested/.test(this.model.schema.pathType(prefix + key));

            if (skip) {
              if ('throw' == strict) {
                throw new Error('Field `' + prefix + key + '` is not in schema.');
              } else {
                delete obj[key];
              }
            } else {
              hasKeys = true;
              obj[key] = this._castUpdateVal(schema, val, op, key);
            }
          }
        }
        return hasKeys;
      }

  #### Parameters:

  - `obj` <Object> - part of a query
  - `op` <String> - the atomic operator ($pull, $set, etc)
  - `pref` <String> - path prefix (internal only)

  #### Returns:

  - <Bool> true if this path has keys to update

  ### Query#_castUpdateVal(`schema`, `val`, `op`, `[$conditional]`)

  Casts `val` according to `schema` and atomic `op`.

  show code

      Query.prototype._castUpdateVal = function _castUpdateVal (schema, val, op, $conditional) {
        if (!schema) {
          // non-existing schema path
          return op in numberOps
            ? Number(val)
            : val
        }

        if (schema.caster && op in castOps &&
          ('Object' === val.constructor.name || Array.isArray(val))) {
          // Cast values for ops that add data to MongoDB.
          // Ensures embedded documents get ObjectIds etc.
          var tmp = schema.cast(val);

          if (Array.isArray(val)) {
            val = tmp;
          } else {
            val = tmp[0];
          }
        }

        if (op in numberOps) return Number(val);
        if (/^\$/.test($conditional)) return schema.castForQuery($conditional, val);
        return schema.castForQuery(val)
      }

  #### Parameters:

  - `schema` <Schema>
  - `val` <Object>
  - `op` <String> - the atomic operator ($pull, $set, etc)
  - `[$conditional]` <String>

  ### Query#_getSchema(`path`)

  Finds the schema for `path`. This is different than
  calling `schema.path` as it also resolves paths with
  positional selectors (something.$.another.$.path).

  show code

      Query.prototype._getSchema = function _getSchema (path) {
        var schema = this.model.schema
          , pathschema = schema.path(path);

        if (pathschema)
          return pathschema;

        // look for arrays
        return (function search (parts, schema) {
          var p = parts.length + 1
            , foundschema
            , trypath

          while (p--) {
            trypath = parts.slice(0, p).join('.');
            foundschema = schema.path(trypath);
            if (foundschema) {
              if (foundschema.caster) {

                // array of Mixed?
                if (foundschema.caster instanceof Types.Mixed) {
                  return foundschema.caster;
                }

                // Now that we found the array, we need to check if there
                // are remaining document paths to look up for casting.
                // Also we need to handle array.$.path since schema.path
                // doesn't work for that.
                if (p !== parts.length) {
                  if ('$' === parts[p]) {
                    // comments.$.comments.$.title
                    return search(parts.slice(p+1), foundschema.schema);
                  } else {
                    // this is the last path of the selector
                    return search(parts.slice(p), foundschema.schema);
                  }
                }
              }
              return foundschema;
            }
          }
        })(path.split('.'), schema)
      }

  #### Parameters:

  - `path` <String>

  ### Query#remove(`callback`)

  Executes this query as a remove() operation.

  show code

      Query.prototype.remove = function (callback) {
        this.op = 'remove';

        var model = this.model
          , options = this._optionsForExec(model)
          , cb = 'function' == typeof callback

        try {
          this.cast(model);
        } catch (err) {
          if (cb) return callback(err);
          throw err;
        }

        if (!cb) {
          delete options.safe;
        }

        var castQuery = this._conditions;
        model.collection.remove(castQuery, options, tick(callback));
        return this;
      };

  #### Parameters:

  - `callback` <Function>

  #### Example

      Cassette.where('artist').equals('Anne Murray').remove(callback)

  ### Query#findOneAndUpdate(`[query]`, `[doc]`, `[options]`, `[callback]`)

  Issues a mongodb findAndModify update command.

  show code

      Query.prototype.findOneAndUpdate = function (query, doc, options, callback) {
        this.op = 'findOneAndUpdate';

        switch (arguments.length) {
          case 3:
            if ('function' == typeof options)
              callback = options, options = {};
            break;
          case 2:
            if ('function' == typeof doc) {
              callback = doc;
              doc = query;
              query = undefined;
            }
            options = undefined;
            break;
          case 1:
            if ('function' == typeof query) {
              callback = query;
              query = options = doc = undefined;
            } else {
              doc = query;
              query = options = undefined;
            }
        }

        // apply query
        if (query) {
          if ('Object' === query.constructor.name) {
            merge(this._conditions, query);
          } else if (query instanceof Query) {
            merge(this._conditions, query._conditions);
          } else if (query instanceof Document) {
            merge(this._conditions, query.toObject());
          }
        }

        // apply doc
        if (doc) {
          merge(this._updateArg, doc);
        }

        // apply options
        options && this.setOptions(options);

        if (!callback) return this;

        return this._findAndModify('update', callback);
      }

  #### Parameters:

  - `[query]` <Object>
  - `[doc]` <Object>
  - `[options]` <Object>
  - `[callback]` <Function>

  #### Returns:

  - <Query> this

  #### See:

  - mongodb

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

  #### Available options

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

  #### Examples

      query.findOneAndUpdate(conditions, update, options, callback) // executes
      query.findOneAndUpdate(conditions, update, options)  // returns Query
      query.findOneAndUpdate(conditions, update, callback) // executes
      query.findOneAndUpdate(conditions, update)           // returns Query
      query.findOneAndUpdate(callback)                     // executes
      query.findOneAndUpdate()                             // returns Query

  ### Query#findOneAndRemove(`[conditions]`, `[options]`, `[callback]`)

  Issues a mongodb findAndModify remove command.

  show code

      Query.prototype.findOneAndRemove = function (conditions, options, callback) {
        this.op = 'findOneAndRemove';

        if ('function' == typeof options) {
          callback = options;
          options = undefined;
        } else if ('function' == typeof conditions) {
          callback = conditions;
          conditions = undefined;
        }

        // apply conditions
        if (conditions) {
          if ('Object' === conditions.constructor.name) {
            merge(this._conditions, conditions);
          } else if (conditions instanceof Query) {
            merge(this._conditions, conditions._conditions);
          } else if (conditions instanceof Document) {
            merge(this._conditions, conditions.toObject());
          }
        }

        // apply options
        options && this.setOptions(options);

        if (!callback) return this;

        return this._findAndModify('remove', callback);
      }

  #### Parameters:

  - `[conditions]` <Object>
  - `[options]` <Object>
  - `[callback]` <Function>

  #### Returns:

  - <Query> this

  #### See:

  - mongodb

  Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if `callback` is passed else a Query object is returned.

  #### Available options

  - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update

  #### Examples

      A.where().findOneAndRemove(conditions, options, callback) // executes
      A.where().findOneAndRemove(conditions, options)  // return Query
      A.where().findOneAndRemove(conditions, callback) // executes
      A.where().findOneAndRemove(conditions) // returns Query
      A.where().findOneAndRemove(callback)   // executes
      A.where().findOneAndRemove()           // returns Query

  ### Query#_findAndModify(`type`, `callback`)

  _findAndModify

  show code

      Query.prototype._findAndModify = function (type, callback) {
        var model = this.model
          , promise = new Promise(callback)
          , self = this
          , castedQuery
          , castedDoc
          , fields
          , sort
          , opts

        castedQuery = castQuery(this);
        if (castedQuery instanceof Error) {
          process.nextTick(promise.error.bind(promise, castedQuery));
          return promise;
        }

        opts = this._optionsForExec(model);

        if ('remove' == type) {
          opts.remove = true;
        } else {
          if (!('new' in opts)) opts.new = true;
          if (!('upsert' in opts)) opts.upsert = false;

          castedDoc = castDoc(this);
          if (!castedDoc) {
            if (opts.upsert) {
              // still need to do the upsert to empty doc
              castedDoc = { $set: {} };
            } else {
              return this.findOne(callback);
            }
          } else if (castedDoc instanceof Error) {
            process.nextTick(promise.error.bind(promise, castedDoc));
            return promise;
          }
        }

        if (this._fields) {
          fields = utils.clone(opts.fields = this._fields);
        }

        // the driver needs a default
        sort = opts.sort || [];

        model
        .collection
        .findAndModify(castedQuery, sort, castedDoc, opts, tick(function (err, doc) {
          if (err) return promise.error(err);
          if (!doc) return promise.complete(null);

          if (true === opts.lean) {
            return promise.complete(doc);
          }

          var casted = new model(undefined, fields, true);
          casted.init(doc, self, function (err) {
            if (err) return promise.error(err);
            promise.complete(casted);
          });
        }));

        return promise;
      }

  #### Parameters:

  - `type` <String> - either "remove" or "update"
  - `callback` <Function>

  ### Query#populate(`path`, `[fields]`, `[model]`, `[conditions]`, `[options]`)

  Specifies paths which should be populated with other documents.

  show code

      Query.prototype.populate = function (path, fields, model, conditions, options) {
        if ('string' !== typeof model) {
          options = conditions;
          conditions = model;
          model = undefined;
        }
        // The order of fields/conditions args is opposite Model.find but
        // necessary to keep backward compatibility (fields could be
        // an array, string, or object literal).
        this.options.populate[path] =
          new PopulateOptions(fields, conditions, options, model);

        return this;
      };

  #### Parameters:

  - `path` <String>
  - `[fields]` <Object, String>
  - `[model]` <Model>
  - `[conditions]` <Object>
  - `[options]` <Object>

  #### Returns:

  - <Query> this

  #### See:

  - population

  Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.

  #### Example:

      Kitten.findOne().populate('owner').exec(function (err, kitten) {
        console.log(kitten.owner.name) // Max
      })

  ### Query#stream()

  Returns a stream interface

  show code

      Query.prototype.stream = function stream () {
        return new QueryStream(this);
      }

      // helpers

  #### Returns:

  - <QueryStream>

  #### See:

  - QueryStream

  #### Example

      // follows the nodejs stream api
      Thing.find({ name: /^hello/ }).stream().pipe(res)

      // manual streaming
      var stream = Thing.find({ name: /^hello/ }).stream();

      stream.on('data', function (doc) {
        // do something with the mongoose document
      }).on('error', function (err) {
        // handle the error
      }).on('close', function () {
        // the stream is closed
      });

  ### Query#within

  Syntax sugar for expressive queries.

  #### Example

      query.within.box()
      query.within.center()

  #### Returns:

  - <Query> this

- querystream.js

  ### QueryStream(`query`)

  Provides a ReadStream interface for Queries.

  show code

      function QueryStream (query) {
        Stream.call(this);

        this.query = query;
        this.readable = true;
        this.paused = false;
        this._cursor = null;
        this._destroyed = null;
        this._fields = null;
        this._ticks = 0;
        this._inline = T_INIT;

        // give time to hook up events
        var self = this;
        process.nextTick(function () {
          self._init();
        });
      }

  #### Parameters:

  - `query` <Query>

  #### Inherits:

  - NodeJS Stream

  #### Events:

  - `data`: emits a single Mongoose document

  - `error`: emits when an error occurs during streaming. This will emit before the `close` event.

  - `close`: emits when the stream reaches the end of the cursor or an error occurs, or the stream is manually `destroy`ed. After this event, no more events are emitted.

      var stream = Model.find().stream();

      stream.on('data', function (doc) {
        // do something with the mongoose document
      }).on('error', function (err) {
        // handle the error
      }).on('close', function () {
        // the stream is closed
      });

  The stream interface allows us to simply "plug-in" to other Node streams such as http responses and write streams so everything "just works" out of the box.

      Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);

  ### QueryStream#_init()

  Initializes the query.

  show code

      QueryStream.prototype._init = function () {
        if (this._destroyed) return;

        var query = this.query
          , model = query.model
          , options = query._optionsForExec(model)
          , self = this

        try {
          query.cast(model);
        } catch (err) {
          return self.destroy(err);
        }

        self._fields = utils.clone(options.fields = query._fields);

        model.collection.find(query._conditions, options, function (err, cursor) {
          if (err) return self.destroy(err);
          self._cursor = cursor;
          self._next();
        });
      }

  ### QueryStream#_next()

  Trampoline for pulling the next doc from cursor.

  show code

      QueryStream.prototype._next = function () {
        // avoid stack overflows with large result sets.
        // trampoline instead of recursion.
        var fn;
        while (fn = this.__next()) fn.call(this);
      }

  #### See:

  - QueryStream#__next

  ### QueryStream#__next()

  Pulls the next doc from the cursor.

  show code

      QueryStream.prototype.__next = function () {
        if (this.paused || this._destroyed) return;

        var self = this;
        self._inline = T_INIT;

        self._cursor.nextObject(function (err, doc) {
          self._onNextObject(err, doc);
        });

        // if onNextObject() was already called in this tick
        // return ourselves to the trampoline.
        if (T_CONT === this._inline) {
          return this.__next;
        } else {
          // onNextObject() hasn't fired yet. tell onNextObject
          // that its ok to call _next b/c we are not within
          // the trampoline anymore.
          this._inline = T_IDLE;
        }
      }

  #### See:

  - QueryStream#_next

  ### QueryStream#_onNextObject(`err`, `doc`)

  Transforms raw `doc`s returned from the cursor into a model instance.

  show code

      QueryStream.prototype._onNextObject = function (err, doc) {
        if (err) return this.destroy(err);

        // when doc is null we hit the end of the cursor
        if (!doc) {
          return this.destroy();
        }

        if (this.query.options && this.query.options.lean === true)  {
          this.emit('data', doc);
          this._next();
          return;
        }

        var instance = new this.query.model(undefined, this._fields);

        // skip _id for pre-init hooks
        delete instance._doc._id;

        var self = this;
        instance.init(doc, this.query, function (err) {
          if (err) return self.destroy(err);
          self.emit('data', instance);

          // trampoline management
          if (T_IDLE === self._inline) {
            // no longer in trampoline. restart it.
            self._next();
          } else
            // in a trampoline. tell __next that its
            // ok to continue jumping.
            self._inline = T_CONT;
        });
      }

  #### Parameters:

  - `err` <Error, null>
  - `doc` <Object>

  ### QueryStream#pause()

  Pauses this stream.

  show code

      QueryStream.prototype.pause = function () {
        this.paused = true;
      }

  ### QueryStream#resume()

  Resumes this stream.

  show code

      QueryStream.prototype.resume = function () {
        this.paused = false;
        this._next();
      }

  ### QueryStream#destroy(`[err]`)

  Destroys the stream, closing the underlying cursor. No more events will be emitted.

  show code

      QueryStream.prototype.destroy = function (err) {
        if (this._destroyed) return;
        this._destroyed = true;
        this.readable = false;

        if (this._cursor) {
          this._cursor.close();
        }

        if (err) {
          this.emit('error', err);
        }

        this.emit('close');
      }

  #### Parameters:

  - `[err]` <Error>

  ### QueryStream#pipe()

  Pipes this query stream into another stream. This method is inherited from NodeJS Streams.

  #### See:

  - NodeJS

  #### Example:

      query.stream().pipe(writeStream [, options])

  This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.

      var format = new ArrayFormatter;
      Events.find().stream().pipe(format).pipe(res);

  As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this gist for a hacked example.

  ### QueryStream#paused

  Flag stating whether or not this stream is paused.

  ### QueryStream#readable

  Flag stating whether or not this stream is readable.

- schema/array.js

  ### SchemaArray(`key`, `cast`, `options`)

  Array SchemaType constructor

  show code

      function SchemaArray (key, cast, options) {
        if (cast) {
          var castOptions = {};

          if ('Object' === cast.constructor.name) {
            if (cast.type) {
              // support { type: Woot }
              castOptions = cast;
              cast = cast.type;
              delete castOptions.type;
            } else {
              cast = Mixed;
            }
          }

          var caster = cast.name in Types ? Types[cast.name] : cast;
          this.casterConstructor = caster;
          this.caster = new caster(null, castOptions);
        }

        SchemaType.call(this, key, options);

        var self = this
          , defaultArr
          , fn;

        if (this.defaultValue) {
          defaultArr = this.defaultValue;
          fn = 'function' == typeof defaultArr;
        }

        this.default(function(){
          var arr = fn ? defaultArr() : defaultArr || [];
          return new MongooseArray(arr, self.path, this);
        });
      };

  #### Parameters:

  - `key` <String>
  - `cast` <SchemaType>
  - `options` <Object>

  #### Inherits:

  - SchemaType

  ### SchemaArray#checkRequired(`value`)

  Check required

  show code

      SchemaArray.prototype.checkRequired = function (value) {
        return !!(value && value.length);
      };

  #### Parameters:

  - `value` <Array>

  ### SchemaArray#applyGetters(`value`, `scope`)

  Overrides the getters application for the population special-case

  show code

      SchemaArray.prototype.applyGetters = function (value, scope) {
        if (this.caster.options && this.caster.options.ref) {
          // means the object id was populated
          return value;
        }

        return SchemaType.prototype.applyGetters.call(this, value, scope);
      };

  #### Parameters:

  - `value` <Object>
  - `scope` <Object>

  ### SchemaArray#cast(`value`, `doc`, `init`)

  Casts contents

  show code

      SchemaArray.prototype.cast = function (value, doc, init) {
        if (Array.isArray(value)) {
          if (!(value instanceof MongooseArray)) {
            value = new MongooseArray(value, this.path, doc);
          }

          if (this.caster) {
            try {
              for (var i = 0, l = value.length; i < l; i++) {
                value[i] = this.caster.cast(value[i], doc, init);
              }
            } catch (e) {
              // rethrow
              throw new CastError(e.type, value);
            }
          }

          return value;
        } else {
          return this.cast([value], doc, init);
        }
      };

  #### Parameters:

  - `value` <Object>
  - `doc` <Document> document that triggers the casting
  - `init` <Boolean> whether this is an initialization cast

  ### SchemaArray#castForQuery(`$conditional`, `[value]`)

  Casts contents for queries.

  show code

      SchemaArray.prototype.castForQuery = function ($conditional, value) {
        var handler
          , val;
        if (arguments.length === 2) {
          handler = this.$conditionalHandlers[$conditional];
          if (!handler)
            throw new Error("Can't use " + $conditional + " with Array.");
          val = handler.call(this, value);
        } else {
          val = $conditional;
          var proto = this.casterConstructor.prototype;
          var method = proto.castForQuery || proto.cast;
          if (Array.isArray(val)) {
            val = val.map(function (v) {
              if (method) v = method.call(proto, v);
              return isMongooseObject(v)
                ? v.toObject()
                : v;
            });
          } else if (method) {
            val = method.call(proto, val);
          }
        }
        return val && isMongooseObject(val)
          ? val.toObject()
          : val;
      };

  #### Parameters:

  - `$conditional` <String>
  - `[value]` <any>

- schema/boolean.js

  ### SchemaBoolean(`path`, `options`)

  Boolean SchemaType constructor.

  show code

      function SchemaBoolean (path, options) {
        SchemaType.call(this, path, options);
      };

  #### Parameters:

  - `path` <String>
  - `options` <Object>

  #### Inherits:

  - SchemaType

  ### SchemaBoolean#checkRequired()

  Required validator

  show code

      SchemaBoolean.prototype.checkRequired = function (value) {
        return value === true || value === false;
      };

  ### SchemaBoolean#cast(`value`)

  Casts to boolean

  show code

      SchemaBoolean.prototype.cast = function (value) {
        if (value === null) return value;
        if (value === '0') return false;
        return !!value;
      };

  #### Parameters:

  - `value` <Object>

  ### SchemaBoolean#castForQuery(`$conditional`, `val`)

  Casts contents for queries.

  show code

      SchemaBoolean.prototype.castForQuery = function ($conditional, val) {
        var handler;
        if (2 === arguments.length) {
          handler = SchemaBoolean.$conditionalHandlers[$conditional];

          if (!handler)
            throw new Error("Can't use " + $conditional + " with Boolean.");

          return handler.call(this, val);
        }

        return this.cast($conditional);
      };

  #### Parameters:

  - `$conditional` <String>
  - `val` <any>

- schema/buffer.js

  ### SchemaBuffer(`key`, `cast`)

  Buffer SchemaType constructor

  show code

      function SchemaBuffer (key, options) {
        SchemaType.call(this, key, options, 'Buffer');
      };

  #### Parameters:

  - `key` <String>
  - `cast` <SchemaType>

  #### Inherits:

  - SchemaType

  ### SchemaBuffer#checkRequired()

  Check required

  show code

      SchemaBuffer.prototype.checkRequired = function (value) {
        return !!(value && value.length);
      };

  ### SchemaBuffer#cast(`value`, `doc`, `init`)

  Casts contents

  show code

      SchemaBuffer.prototype.cast = function (value, doc, init) {
        if (SchemaType._isRef(this, value, init)) return value;

        if (Buffer.isBuffer(value)) {
          if (!(value instanceof MongooseBuffer)) {
            value = new MongooseBuffer(value, [this.path, doc]);
          }

          return value;
        } else if (value instanceof Binary) {
          return new MongooseBuffer(value.value(true), [this.path, doc]);
        }

        if ('string' === typeof value || Array.isArray(value)) {
          return new MongooseBuffer(value, [this.path, doc]);
        }

        throw new CastError('buffer', value);
      };

  #### Parameters:

  - `value` <Object>
  - `doc` <Document> document that triggers the casting
  - `init` <Boolean>

  ### SchemaBuffer#castForQuery(`$conditional`, `[value]`)

  Casts contents for queries.

  show code

      SchemaBuffer.prototype.castForQuery = function ($conditional, val) {
        var handler;
        if (arguments.length === 2) {
          handler = this.$conditionalHandlers[$conditional];
          if (!handler)
            throw new Error("Can't use " + $conditional + " with Buffer.");
          return handler.call(this, val);
        } else {
          val = $conditional;
          return this.cast(val).toObject();
        }
      };

  #### Parameters:

  - `$conditional` <String>
  - `[value]` <any>

- schema/date.js

  ### SchemaDate(`key`, `options`)

  Date SchemaType constructor.

  show code

      function SchemaDate (key, options) {
        SchemaType.call(this, key, options);
      };

  #### Parameters:

  - `key` <String>
  - `options` <Object>

  #### Inherits:

  - SchemaType

  ### SchemaDate#checkRequired()

  Required validator for date

  show code

      SchemaDate.prototype.checkRequired = function (value) {
        return value instanceof Date;
      };

  ### SchemaDate#cast(`value`)

  Casts to date

  show code

      SchemaDate.prototype.cast = function (value) {
        if (value === null || value === '')
          return null;

        if (value instanceof Date)
          return value;

        var date;

        // support for timestamps
        if (value instanceof Number || 'number' == typeof value
            || String(value) == Number(value))
          date = new Date(Number(value));

        // support for date strings
        else if (value.toString)
          date = new Date(value.toString());

        if (date.toString() != 'Invalid Date')
          return date;

        throw new CastError('date', value);
      };

  #### Parameters:

  - `value` <Object> to cast

  ### SchemaDate#castForQuery(`$conditional`, `[value]`)

  Casts contents for queries.

  show code

      SchemaDate.prototype.castForQuery = function ($conditional, val) {
        var handler;

        if (2 !== arguments.length) {
          return this.cast($conditional);
        }

        handler = this.$conditionalHandlers[$conditional];

        if (!handler) {
          throw new Error("Can't use " + $conditional + " with Date.");
        }

        return handler.call(this, val);
      };

  #### Parameters:

  - `$conditional` <String>
  - `[value]` <any>

- schema/documentarray.js

  ### DocumentArray(`key`, `schema`, `options`)

  SubdocsArray SchemaType constructor

  show code

      function DocumentArray (key, schema, options) {
        // compile an embedded document for this schema
        // TODO Move this into parent model compilation for performance improvement?
        function EmbeddedDocument () {
          Subdocument.apply(this, arguments);
        };

        EmbeddedDocument.prototype.__proto__ = Subdocument.prototype;
        EmbeddedDocument.prototype._setSchema(schema);
        EmbeddedDocument.schema = schema;

        // apply methods
        for (var i in schema.methods) {
          EmbeddedDocument.prototype[i] = schema.methods[i];
        }

        // apply statics
        for (var i in schema.statics)
          EmbeddedDocument[i] = schema.statics[i];

        EmbeddedDocument.options = options;
        this.schema = schema;

        ArrayType.call(this, key, EmbeddedDocument, options);

        this.schema = schema;
        var path = this.path;
        var fn = this.defaultValue;

        this.default(function(){
          var arr = fn.call(this);
          if (!Array.isArray(arr)) arr = [arr];
          return new MongooseDocumentArray(arr, path, this);
        });
      };

  #### Parameters:

  - `key` <String>
  - `schema` <Schema>
  - `options` <Object>

  #### Inherits:

  - SchemaArray

  ### DocumentArray#doValidate()

  Performs local validations first, then validations on each embedded doc

  show code

      DocumentArray.prototype.doValidate = function (array, fn, scope) {
        var self = this;
        SchemaType.prototype.doValidate.call(this, array, function(err){
          if (err) return fn(err);

          var count = array && array.length
            , error = false;

          if (!count) return fn();

          array.forEach(function(doc, index){
            doc.validate(function(err){
              if (err && !error){
                // rewrite they key
                err.key = self.key + '.' + index + '.' + err.key;
                fn(err);
                error = true;
              } else {
                --count || fn();
              }
            });
          });
        }, scope);
      };

  ### DocumentArray#cast(`value`, `document`)

  Casts contents

  show code

      DocumentArray.prototype.cast = function (value, doc, init, prev) {
        var subdoc
          , i

        if (Array.isArray(value)) {
          if (!(value instanceof MongooseDocumentArray)) {
            value = new MongooseDocumentArray(value, this.path, doc);
          }

          i = value.length;

          while (i--) {
            if (!(value[i] instanceof Subdocument)) {
              if (init) {
                subdoc = new this.casterConstructor(null, value, true);
                value[i] = subdoc.init(value[i]);
              } else {
                if (prev && (subdoc = prev.id(value[i]._id))) {
                  // handle resetting doc with existing id but differing data
                  // doc.array = [{ doc: 'val' }]
                  subdoc.set(value[i]);
                } else {
                  subdoc = new this.casterConstructor(value[i], value);
                }

                // if set() is hooked it will have no return value
                // see gh-746
                value[i] = subdoc;
              }
            }
          }

          return value;
        } else {
          return this.cast([value], doc, init, prev);
        }

        throw new CastError('documentarray', value);
      };

  #### Parameters:

  - `value` <Object>
  - `document` <Document> that triggers the casting

- schema/mixed.js

  ### Mixed(`path`, `options`)

  Mixed SchemaType constructor.

  show code

      function Mixed (path, options) {
        // make sure empty array defaults are handled
        if (options &&
            options.default &&
            Array.isArray(options.default) &&
            0 === options.default.length) {
          options.default = Array;
        }

        SchemaType.call(this, path, options);
      };

  #### Parameters:

  - `path` <String>
  - `options` <Object>

  #### Inherits:

  - SchemaType

  ### Mixed#checkRequired()

  Required validator

  show code

      Mixed.prototype.checkRequired = function (val) {
        return true;
      };

  ### Mixed#cast(`value`)

  Casts `val` for Mixed.

  show code

      Mixed.prototype.cast = function (val) {
        return val;
      };

  #### Parameters:

  - `value` <Object> to cast

  this is a no-op

  ### Mixed#castForQuery(`$cond`, `[val]`)

  Casts contents for queries.

  show code

      Mixed.prototype.castForQuery = function ($cond, val) {
        if (arguments.length === 2) return val;
        return $cond;
      };

  #### Parameters:

  - `$cond` <String>
  - `[val]` <any>

- schema/number.js

  ### SchemaNumber(`key`, `options`)

  Number SchemaType constructor.

  show code

      function SchemaNumber (key, options) {
        SchemaType.call(this, key, options, 'Number');
      };

  #### Parameters:

  - `key` <String>
  - `options` <Object>

  #### Inherits:

  - SchemaType

  ### SchemaNumber#checkRequired()

  Required validator for number

  show code

      SchemaNumber.prototype.checkRequired = function checkRequired (value) {
        if (SchemaType._isRef(this, value, true)) {
          return null != value;
        } else {
          return typeof value == 'number' || value instanceof Number;
        }
      };

  ### SchemaNumber#min(`value`, `message`)

  Sets a maximum number validator.

  show code

      SchemaNumber.prototype.min = function (value, message) {
        if (this.minValidator)
          this.validators = this.validators.filter(function(v){
            return v[1] != 'min';
          });
        if (value != null)
          this.validators.push([function(v){
            return v === null || v >= value;
          }, 'min']);
        return this;
      };

  #### Parameters:

  - `value` <Number> minimum number
  - `message` <String>

  #### Example:

      var s = new Schema({ n: { type: Number, min: 10 })
      var M = db.model('M', s)
      var m = new M({ n: 9 })
      m.save(function (err) {
        console.error(err) // validator error
        m.n = 10;
        m.save() // success
      })

  ### SchemaNumber#max(`maximum`, `message`)

  Sets a maximum number validator.

  show code

      SchemaNumber.prototype.max = function (value, message) {
        if (this.maxValidator)
          this.validators = this.validators.filter(function(v){
            return v[1] != 'max';
          });
        if (value != null)
          this.validators.push([this.maxValidator = function(v){
            return v === null || v <= value;
          }, 'max']);
        return this;
      };

  #### Parameters:

  - `maximum` <Number> number
  - `message` <String>

  #### Example:

      var s = new Schema({ n: { type: Number, max: 10 })
      var M = db.model('M', s)
      var m = new M({ n: 11 })
      m.save(function (err) {
        console.error(err) // validator error
        m.n = 10;
        m.save() // success
      })

  ### SchemaNumber#cast(`value`, `doc`, `init`)

  Casts to number

  show code

      SchemaNumber.prototype.cast = function (value, doc, init) {
        if (SchemaType._isRef(this, value, init)) return value;

        if (!isNaN(value)){
          if (null === value) return value;
          if ('' === value) return null;
          if ('string' == typeof value) value = Number(value);
          if (value instanceof Number) return value
          if ('number' == typeof value) return value;
          if (value.toString && !Array.isArray(value) &&
              value.toString() == Number(value)) {
            return new Number(value)
          }
        }

        throw new CastError('number', value);
      };

  #### Parameters:

  - `value` <Object> value to cast
  - `doc` <Document> document that triggers the casting
  - `init` <Boolean>

  ### SchemaNumber#castForQuery(`$conditional`, `[value]`)

  Casts contents for queries.

  show code

      SchemaNumber.prototype.castForQuery = function ($conditional, val) {
        var handler;
        if (arguments.length === 2) {
          handler = this.$conditionalHandlers[$conditional];
          if (!handler)
            throw new Error("Can't use " + $conditional + " with Number.");
          return handler.call(this, val);
        } else {
          val = this.cast($conditional);
          return val == null ? val : val
        }
      };

  #### Parameters:

  - `$conditional` <String>
  - `[value]` <any>

- schema/objectid.js

  ### ObjectId(`key`, `options`)

  ObjectId SchemaType constructor.

  show code

      function ObjectId (key, options) {
        SchemaType.call(this, key, options, 'ObjectID');
      };

  #### Parameters:

  - `key` <String>
  - `options` <Object>

  #### Inherits:

  - SchemaType

  ### ObjectId#checkRequired()

  Check required

  show code

      ObjectId.prototype.checkRequired = function checkRequired (value) {
        if (SchemaType._isRef(this, value, true)) {
          return null != value;
        } else {
          return value instanceof oid;
        }
      };

  ### ObjectId#cast(`value`, `scope`, `init`)

  Casts to ObjectId

  show code

      ObjectId.prototype.cast = function (value, scope, init) {
        if (SchemaType._isRef(this, value, init)) return value;

        if (value === null) return value;

        if (value instanceof oid)
          return value;

        if (value._id && value._id instanceof oid)
          return value._id;

        if (value.toString)
          return oid.fromString(value.toString());

        throw new CastError('object id', value);
      };

  #### Parameters:

  - `value` <Object>
  - `scope` <Object>
  - `init` <Boolean> whether this is an initialization cast

  ### ObjectId#castForQuery(`$conditional`, `[val]`)

  Casts contents for queries.

  show code

      ObjectId.prototype.castForQuery = function ($conditional, val) {
        var handler;
        if (arguments.length === 2) {
          handler = this.$conditionalHandlers[$conditional];
          if (!handler)
            throw new Error("Can't use " + $conditional + " with ObjectId.");
          return handler.call(this, val);
        } else {
          return this.cast($conditional);
        }
      };

  #### Parameters:

  - `$conditional` <String>
  - `[val]` <any>

  ### ObjectId#auto(`turnOn`)

  Adds an auto-generated ObjectId default if turnOn is true.

  show code

      ObjectId.prototype.auto = function (turnOn) {
        if (turnOn) {
          this.default(defaultId);
          this.set(resetId)
        }
      };

  #### Parameters:

  - `turnOn` <Boolean> auto generated ObjectId defaults

- schema/string.js

  ### SchemaString(`key`, `options`)

  String SchemaType constructor.

  show code

      function SchemaString (key, options) {
        this.enumValues = [];
        this.regExp = null;
        SchemaType.call(this, key, options, 'String');
      };

  #### Parameters:

  - `key` <String>
  - `options` <Object>

  #### Inherits:

  - SchemaType

  ### SchemaString#enum(`[args...]`)

  Adds enumeration values and a coinciding validator.

  show code

      SchemaString.prototype.enum = function () {
        var len = arguments.length;
        if (!len || undefined === arguments[0] || false === arguments[0]) {
          if (this.enumValidator){
            this.enumValidator = false;
            this.validators = this.validators.filter(function(v){
              return v[1] != 'enum';
            });
          }
          return;
        }

        for (var i = 0; i < len; i++) {
          if (undefined !== arguments[i]) {
            this.enumValues.push(this.cast(arguments[i]));
          }
        }

        if (!this.enumValidator) {
          var values = this.enumValues;
          this.enumValidator = function(v){
            return undefined === v || ~values.indexOf(v);
          };
          this.validators.push([this.enumValidator, 'enum']);
        }
      };

  #### Parameters:

  - `[args...]` <String> enumeration values

  #### Example:

      var states = 'opening open closing closed'.split(' ')
      var s = new Schema({ state: { type: String, enum: states })
      var M = db.model('M', s)
      var m = new M({ state: 'invalid' })
      m.save(function (err) {
        console.error(err) // validator error
        m.state = 'open'
        m.save() // success
      })

  ### SchemaString#lowercase()

  Adds a lowercase setter.

  show code

      SchemaString.prototype.lowercase = function () {
        return this.set(function (v) {
          return v.toLowerCase();
        });
      };

  #### Example:

      var s = new Schema({ email: { type: String, lowercase: true }})
      var M = db.model('M', s);
      var m = new M({ email: 'SomeEmail@example.COM' });
      console.log(m.email) // someemail@example.com

  ### SchemaString#uppercase()

  Adds an uppercase setter.

  show code

      SchemaString.prototype.uppercase = function () {
        return this.set(function (v) {
          return v.toUpperCase();
        });
      };

  #### Example:

      var s = new Schema({ caps: { type: String, uppercase: true }})
      var M = db.model('M', s);
      var m = new M({ caps: 'an example' });
      console.log(m.caps) // AN EXAMPLE

  ### SchemaString#trim()

  Adds a trim setter.

  show code

      SchemaString.prototype.trim = function () {
        return this.set(function (v) {
          return v.trim();
        });
      };

  The string value will be trimmed when set.

  #### Example:

      var s = new Schema({ name: { type: String, trim: true }})
      var M = db.model('M', s)
      var string = ' some name '
      console.log(string.length) // 11
      var m = new M({ name: string })
      console.log(m.name.length) // 9

  ### SchemaString#match(`regExp`)

  Sets a regexp validator.

  show code

      SchemaString.prototype.match = function match (regExp) {
        this.validators.push([function(v){
          return null != v && '' !== v
            ? regExp.test(v)
            : true
        }, 'regexp']);
      };

  #### Parameters:

  - `regExp` <RegExp> regular expression to test against

  Any value that does not pass `regExp`.test(val) will fail validation.

  #### Example:

      var s = new Schema({ name: { type: String, match: /^a/ }})
      var M = db.model('M', s)
      var m = new M({ name: 'invalid' })
      m.validate(function (err) {
        console.error(err) // validation error
        m.name = 'apples'
        m.validate(function (err) {
          assert.ok(err) // success
        })
      })

  ### SchemaString#checkRequired(`value`)

  Check required

  show code

      SchemaString.prototype.checkRequired = function checkRequired (value) {
        if (SchemaType._isRef(this, value, true)) {
          return null != value;
        } else {
          return (value instanceof String || typeof value == 'string') && value.length;
        }
      };

  #### Parameters:

  - `value` <String, null, undefined>

  ### SchemaString#cast()

  Casts to String

  show code

      SchemaString.prototype.cast = function (value, scope, init) {
        if (SchemaType._isRef(this, value, init)) return value;
        if (value === null) return value;
        if ('undefined' !== typeof value && value.toString) return value.toString();
        throw new CastError('string', value);
      };

  ### SchemaString#castForQuery(`$conditional`, `[val]`)

  Casts contents for queries.

  show code

      SchemaString.prototype.castForQuery = function ($conditional, val) {
        var handler;
        if (arguments.length === 2) {
          handler = this.$conditionalHandlers[$conditional];
          if (!handler)
            throw new Error("Can't use " + $conditional + " with String.");
          return handler.call(this, val);
        } else {
          val = $conditional;
          if (val instanceof RegExp) return val;
          return this.cast(val);
        }
      };

  #### Parameters:

  - `$conditional` <String>
  - `[val]` <any>

- schema.js

  ### Schema(`definition`)

  Schema constructor.

  show code

      function Schema (obj, options) {
        if (!(this instanceof Schema))
          return new Schema(obj, options);

        this.paths = {};
        this.subpaths = {};
        this.virtuals = {};
        this.nested = {};
        this.inherits = {};
        this.callQueue = [];
        this._indexes = [];
        this.methods = {};
        this.statics = {};
        this.tree = {};
        this._requiredpaths = undefined;

        // set options
        this.options = utils.options({
            safe: true
          , strict: true
          , capped: false // { size, max, autoIndexId }
          , versionKey: '__v'
          , minimize: true
          , autoIndex: true
          , shardKey: null
        }, options);

        // build paths
        if (obj) {
          this.add(obj);
        }

        if (!this.paths['_id'] && !this.options.noId) {
          this.add({ _id: {type: Schema.ObjectId, auto: true} });
        }

        if (!this.paths['id'] && !this.options.noVirtualId) {
          this.virtual('id').get(function () {
            if (this.__id) {
              return this.__id;
            }

            return this.__id = null == this._id
              ? null
              : this._id.toString();
          });
        }

        delete this.options.noVirtualId;

        // versioning not directly added to schema b/c we only want
        // it in the top level document, not embedded ones.
      };

  #### Parameters:

  - `definition` <Object>

  #### Inherits:

  - NodeJS EventEmitter

  #### Events:

  - `init`: Emitted after the schema is compiled into a `Model`.

  #### Example:

      var child = new Schema({ name: String });
      var schema = new Schema({ name: String, age: Number, children: [child] });
      var Tree = mongoose.model('Tree', schema);

  #### Note:

  When nesting schemas, (`children` in the example above), always declare the child schema first before passing it into is parent.

  ### Schema#add(`obj`, `prefix`)

  Adds key path / schema type pairs to this schema.

  show code

      Schema.prototype.add = function add (obj, prefix) {
        prefix = prefix || '';
        for (var i in obj) {
          if (null == obj[i]) {
            throw new TypeError('Invalid value for schema path `'+ prefix + i +'`');
          }

          if (obj[i].constructor.name == 'Object' && (!obj[i].type || obj[i].type.type)) {
            if (Object.keys(obj[i]).length) {
              // nested object { last: { name: String }}
              this.nested[prefix + i] = true;
              this.add(obj[i], prefix + i + '.');
            }
            else
              this.path(prefix + i, obj[i]); // mixed type
          } else
            this.path(prefix + i, obj[i]);
        }
      };

  #### Parameters:

  - `obj` <Object>
  - `prefix` <String>

  #### Example:

      var ToySchema = new Schema;
      ToySchema.add({ name: 'string', color: 'string', price: 'number' });

  ### Schema#path(`path`, `constructor`)

  Gets/sets schema paths.

  show code

      Schema.prototype.path = function (path, obj) {
        if (obj == undefined) {
          if (this.paths[path]) return this.paths[path];
          if (this.subpaths[path]) return this.subpaths[path];

          // subpaths?
          return /\.\d+\.?/.test(path)
            ? getPositionalPath(this, path)
            : undefined;
        }

        // some path names conflict with document methods
        if (reserved[path]) {
          throw new Error("`" + path + "` may not be used as a schema pathname");
        }

        // update the tree
        var subpaths = path.split(/\./)
          , last = subpaths.pop()
          , branch = this.tree;

        subpaths.forEach(function(path) {
          if (!branch[path]) branch[path] = {};
          branch = branch[path];
        });

        branch[last] = utils.clone(obj);

        this.paths[path] = Schema.interpretAsType(path, obj);
        return this;
      };

  #### Parameters:

  - `path` <String>
  - `constructor` <Object>

  Sets a path (if arity 2)
  Gets a path (if arity 1)

  #### Example

      schema.path('name') // returns a SchemaType
      schema.path('name', Number) // changes the schemaType of `name` to Number

  ### Schema#eachPath(`fn`)

  Iterates the schemas paths similar to Array#forEach.

  show code

      Schema.prototype.eachPath = function (fn) {
        var keys = Object.keys(this.paths)
          , len = keys.length;

        for (var i = 0; i < len; ++i) {
          fn(keys[i], this.paths[keys[i]]);
        }

        return this;
      };

  #### Parameters:

  - `fn` <Function> callback function

  #### Returns:

  - <Schema> this

  The callback is passed the pathname and schemaType as arguments on each iteration.

  ### Schema#requiredPaths()

  Returns an Array of path strings that are required by this schema.

  show code

      Schema.prototype.requiredPaths = function requiredPaths () {
        if (this._requiredpaths) return this._requiredpaths;

        var paths = Object.keys(this.paths)
          , i = paths.length
          , ret = [];

        while (i--) {
          var path = paths[i];
          if (this.paths[path].isRequired) ret.push(path);
        }

        return this._requiredpaths = ret;
      }

  #### Returns:

  - <Array>

  ### Schema#pathType(`path`)

  Returns the pathType of `path` for this schema.

  show code

      Schema.prototype.pathType = function (path) {
        if (path in this.paths) return 'real';
        if (path in this.virtuals) return 'virtual';
        if (path in this.nested) return 'nested';
        if (path in this.subpaths) return 'real';

        if (/\.\d+\.?/.test(path) && getPositionalPath(this, path)) {
          return 'real';
        } else {
          return 'adhocOrUndefined'
        }
      };

  #### Parameters:

  - `path` <String>

  #### Returns:

  - <String>

  Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.

  ### Schema#queue(`name`, `args`)

  Adds a method call to the queue.

  show code

      Schema.prototype.queue = function(name, args){
        this.callQueue.push([name, args]);
        return this;
      };

  #### Parameters:

  - `name` <String> name of the document method to call later
  - `args` <Array> arguments to pass to the method

  ### Schema#pre(`method`, `callback`)

  Defines a pre hook for the document.

  show code

      Schema.prototype.pre = function(){
        return this.queue('pre', arguments);
      };

  #### Parameters:

  - `method` <String>
  - `callback` <Function>

  #### See:

  - hooks.js

  #### Example

      var toySchema = new Schema(..);

      toySchema.pre('save', function (next) {
        if (!this.created) this.created = new Date;
        next();
      })

      toySchema.pre('validate', function (next) {
        if (this.name != 'Woody') this.name = 'Woody';
        next();
      })

  ### Schema#post(`method`, `fn`)

  Defines a post for the document

  show code

      Schema.prototype.post = function(method, fn){
        return this.queue('on', arguments);
      };

  #### Parameters:

  - `method` <String> name of the method to hook
  - `fn` <Function> callback

  #### See:

  - hooks.js

  Post hooks fire `on` the event emitted from document instances of Models compiled from this schema.

      var schema = new Schema(..);
      schema.post('save', function () {
        console.log('this fired after a document was saved');
      });

      var Model = mongoose.model('Model', schema);

      var m = new Model(..);
      m.save(function (err) {
        console.log('this fires after the `post` hook');
      });

  ### Schema#plugin(`plugin`, `opts`)

  Registers a plugin for this schema.

  show code

      Schema.prototype.plugin = function (fn, opts) {
        fn(this, opts);
        return this;
      };

  #### Parameters:

  - `plugin` <Function> callback
  - `opts` <Object>

  #### See:

  - plugins

  ### Schema#method(`method`, `[fn]`)

  Adds an instance method to documents constructed from Models compiled from this schema.

  show code

      Schema.prototype.method = function (name, fn) {
        if ('string' != typeof name)
          for (var i in name)
            this.methods[i] = name[i];
        else
          this.methods[name] = fn;
        return this;
      };

  #### Parameters:

  - `method` <String, Object> name
  - `[fn]` <Function>

  #### Example

      var schema = kittySchema = new Schema(..);

      schema.methods.meow = function () {
        console.log('meeeeeoooooooooooow');
      })

      var Kitty = mongoose.model('Kitty', schema);

      var fizz = new Kitty;
      fizz.meow(); // meeeeeooooooooooooow

  If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.

      schema.method({
          purr: function () {}
        , scratch: function () {}
      });

      // later
      fizz.purr();
      fizz.scratch();

  ### Schema#static(`name`, `fn`)

  Adds static "class" methods to Models compiled from this schema.

  show code

      Schema.prototype.static = function(name, fn) {
        if ('string' != typeof name)
          for (var i in name)
            this.statics[i] = name[i];
        else
          this.statics[name] = fn;
        return this;
      };

  #### Parameters:

  - `name` <String>
  - `fn` <Function>

  #### Example

      var schema = new Schema(..);
      schema.static('findByName', function (name, callback) {
        return this.find({ name: name }, callback);
      });

      var Drink = mongoose.model('Drink', schema);
      Drink.findByName('sanpellegrino', function (err, drinks) {
        //
      });

  If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.

  ### Schema#index(`fields`, `[options]`)

  Defines an index (most likely compound) for this schema.

  show code

      Schema.prototype.index = function (fields, options) {
        options || (options = {});

        if (options.expires)
          utils.expires(options);

        this._indexes.push([fields, options]);
        return this;
      };

  #### Parameters:

  - `fields` <Object>
  - `[options]` <Object>

  #### Example

      schema.index({ first: 1, last: -1 })

  ### Schema#set(`key`, `[value]`)

  Sets/gets a schema option.

  show code

      Schema.prototype.set = function (key, value) {
        if (arguments.length == 1)
          return this.options[key];
        this.options[key] = value;
        return this;
      };

  #### Parameters:

  - `key` <String> option name
  - `[value]` <Object> if not passed, the current option value is returned

  ### Schema#indexes()

  Compiles indexes from fields and schema-level indexes

  show code

      Schema.prototype.indexes = function () {
        var indexes = []
          , seenSchemas = [];

        collectIndexes(this);

        return indexes;

        function collectIndexes (schema, prefix) {
          if (~seenSchemas.indexOf(schema)) return;
          seenSchemas.push(schema);

          var index;
          var paths = schema.paths;
          prefix = prefix || '';

          for (var i in paths) {
            if (paths[i]) {
              if (paths[i] instanceof Types.DocumentArray) {
                collectIndexes(paths[i].schema, i + '.');
              } else {
                index = paths[i]._index;

                if (index !== false && index !== null){
                  var field = {};
                  field[prefix + i] = '2d' === index ? index : 1;
                  var options = 'Object' === index.constructor.name ? index : {};
                  if (!('background' in options)) options.background = true;
                  indexes.push([field, options]);
                }
              }
            }
          }

          if (prefix) {
            fixSubIndexPaths(schema, prefix);
          } else {
            schema._indexes.forEach(function (index) {
              if (!('background' in index[1])) index[1].background = true;
            });
            indexes = indexes.concat(schema._indexes);
          }
        }

  ### Schema#virtual(`name`, `options`)

  Creates a virtual type with the given name.

  show code

      Schema.prototype.virtual = function (name, options) {
        var virtuals = this.virtuals;
        var parts = name.split('.');
        return virtuals[name] = parts.reduce(function (mem, part, i) {
          mem[part] || (mem[part] = (i === parts.length-1)
                                  ? new VirtualType(options)
                                  : {});
          return mem[part];
        }, this.tree);
      };

  #### Parameters:

  - `name` <String>
  - `options` <Object>

  #### Returns:

  - <VirtualType>

  ### Schema#virtualpath(`name`)

  Returns the virtual type with the given `name`.

  show code

      Schema.prototype.virtualpath = function (name) {
        return this.virtuals[name];
      };

  #### Parameters:

  - `name` <String>

  #### Returns:

  - <VirtualType>

  ### Schema#namedScope()

  These still haven't been fixed. Once they're working we'll make them public again.

  show code

      Schema.prototype.namedScope = function (name, fn) {
        var namedScopes = this.namedScopes || (this.namedScopes = new NamedScope)
          , newScope = Object.create(namedScopes)
          , allScopes = namedScopes.scopesByName || (namedScopes.scopesByName = {});
        allScopes[name] = newScope;
        newScope.name = name;
        newScope.block = fn;
        newScope.query = new Query();
        newScope.decorate(namedScopes, {
          block0: function (block) {
            return function () {
              block.call(this.query);
              return this;
            };
          },
          blockN: function (block) {
            return function () {
              block.apply(this.query, arguments);
              return this;
            };
          },
          basic: function (query) {
            return function () {
              this.query.find(query);
              return this;
            };
          }
        });
        return newScope;
      };

  ### Schema.reserved

  Reserved document keys.

  show code

      Schema.reserved = Object.create(null);
      var reserved = Schema.reserved;
      reserved.on =
      reserved.db =
      reserved.init =
      reserved.isNew =
      reserved.errors =
      reserved.schema =
      reserved.options =
      reserved.modelName =
      reserved.collection = 1;

  Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.

      on, db, init, isNew, errors, schema, options, modelName, collection

  ### Schema.interpretAsType(`path`, `obj`)

  Converts type arguments into Mongoose Types.

  show code

      Schema.interpretAsType = function (path, obj) {
        if (obj.constructor.name != 'Object')
          obj = { type: obj };

        // Get the type making sure to allow keys named "type"
        // and default to mixed if not specified.
        // { type: { type: String, default: 'freshcut' } }
        var type = obj.type && !obj.type.type
          ? obj.type
          : {};

        if ('Object' == type.constructor.name || 'mixed' == type) {
          return new Types.Mixed(path, obj);
        }

        if (Array.isArray(type) || Array == type || 'array' == type) {
          // if it was specified through { type } look for `cast`
          var cast = (Array == type || 'array' == type)
            ? obj.cast
            : type[0];

          if (cast instanceof Schema) {
            return new Types.DocumentArray(path, cast, obj);
          }

          if ('string' == typeof cast) {
            cast = Types[cast.charAt(0).toUpperCase() + cast.substring(1)];
          } else if (cast && (!cast.type || cast.type.type)
                          && 'Object' == cast.constructor.name
                          && Object.keys(cast).length) {
            return new Types.DocumentArray(path, new Schema(cast), obj);
          }

          return new Types.Array(path, cast || Types.Mixed, obj);
        }

        var name = 'string' == typeof type
          ? type
          : type.name;

        if (name) {
          name = name.charAt(0).toUpperCase() + name.substring(1);
        }

        if (undefined == Types[name]) {
          throw new TypeError('Undefined type at `' + path +
              '`
        Did you try nesting Schemas? ' +
              'You can only nest using refs or arrays.');
        }

        return new Types[name](path, obj);
      };

  #### Parameters:

  - `path` <String>
  - `obj` <Object> constructor

  ### Schema.Types

  The various Mongoose Schema Types.

  show code

      Schema.Types = require('./schema/index');

  #### Example:

      var mongoose = require('mongoose');
      var ObjectId = mongoose.Schema.Types.ObjectId;

  #### Types:

  - String
  - Number
  - Boolean | Bool
  - Array
  - Buffer
  - Date
  - ObjectId | Oid
  - Mixed

  Using this exposed access to the `Mixed` SchemaType, we can use them in our schema.

      var ObjectId = mongoose.Schema.Types.Mixed;
      new mongoose.Schema({ _user: ObjectId })

  ### Schema#tree

  Schema as a tree

  #### Example:

      {
          '_id'     : ObjectId
        , 'nested'  : {
              'key' : String
          }
      }

  ### Schema#paths

  Schema as flat paths

  #### Example:

      {
          '_id'        : SchemaType,
        , 'nested.key' : SchemaType,
      }

- schemadefault.js

  ### exports#system.profile

  Default model for querying the system.profiles collection.

- schematype.js

  ### SchemaType(`path`, `[options]`, `[instance]`)

  SchemaType constructor

  show code

      function SchemaType (path, options, instance) {
        this.path = path;
        this.instance = instance;
        this.validators = [];
        this.setters = [];
        this.getters = [];
        this.options = options;
        this._index = null;
        this.selected;

        for (var i in options) if (this[i] && 'function' == typeof this[i]) {
          // { unique: true, index: true }
          if ('index' == i && this._index) continue;

          var opts = Array.isArray(options[i])
            ? options[i]
            : [options[i]];

          this[i].apply(this, opts);
        }
      };

  #### Parameters:

  - `path` <String>
  - `[options]` <Object>
  - `[instance]` <String>

  ### SchemaType#default(`val`)

  Sets a default value for this schematype.

  show code

      SchemaType.prototype.default = function (val) {
        if (1 === arguments.length) {
          this.defaultValue = typeof val === 'function'
            ? val
            : this.cast(val);
          return this;
        } else if (arguments.length > 1) {
          this.defaultValue = utils.args(arguments);
        }
        return this.defaultValue;
      };

  #### Parameters:

  - `val` <any> default value

  #### Returns:

  - <SchemaType, defaultValue>

  #### Example:

      var s = new Schema({ n: { type: Number, default: 10 })
      var M = db.model('M', s)
      var m = new M;
      console.log(m.n) // 10

  ### SchemaType#index(`options`)

  Declares the index options for this schematype.

  show code

      SchemaType.prototype.index = function (options) {
        this._index = options;
        utils.expires(this._index);
        return this;
      };

  #### Parameters:

  - `options` <Object, Boolean>

  #### Returns:

  - <SchemaType> this

  #### Example:

      var s = new Schema({ name: { type: String, index: true })
      var s = new Schema({ name: { type: String, index: { unique: true, expires: '1d' }})
      Schema.path('my.path').index(true);
      Schema.path('my.path').index({ expires: 60 });
      Schema.path('my.path').index({ unique: true, sparse: true });

  #### NOTE:

  Indexes are created in the background by default. Specify `background: false` to override.

  Direction doesn't matter for single key indexes

  ### SchemaType#unique(`bool`)

  Declares an unique index.

  show code

      SchemaType.prototype.unique = function (bool) {
        if (!this._index || 'Object' !== this._index.constructor.name) {
          this._index = {};
        }

        this._index.unique = bool;
        return this;
      };

  #### Parameters:

  - `bool` <Boolean>

  #### Returns:

  - <SchemaType> this

  #### Examples:

      var s = new Schema({ name: { type: String, unique: true })
      Schema.path('name').index({ unique: true });

  ### SchemaType#sparse(`bool`)

  Declares a sparse index.

  show code

      SchemaType.prototype.sparse = function (bool) {
        if (!this._index || 'Object' !== this._index.constructor.name) {
          this._index = {};
        }

        this._index.sparse = bool;
        return this;
      };

  #### Parameters:

  - `bool` <Boolean>

  #### Returns:

  - <SchemaType> this

  #### Examples:

      var s = new Schema({ name: { type: String, sparse: true })
      Schema.path('name').index({ sparse: true });

  ### SchemaType#expires(`when`)

  Declares a TTL index (rounded to the nearest second) for Date types only.

  show code

      SchemaType.prototype.expires = function (when) {
        if (!this._index || 'Object' !== this._index.constructor.name) {
          this._index = {};
        }

        this._index.expires = when;
        utils.expires(this._index);
        return this;
      };

  #### Parameters:

  - `when` <Number, String>

  #### Returns:

  - <SchemaType> this

  This sets the `expiresAfterSeconds` index option available in MongoDB >= 2.1.2.
  This index type is only compatible with Date types.

  #### Example:

      // expire in 24 hours
      new Schema({..}, { expires: 60*60*24 });

  `expires` utilizes the `ms` module from guille allowing us to use a friendlier syntax:

  #### Example:

      // expire in 24 hours
      new Schema({..}, { expires: '24h' });

      // expire in 1.5 hours
      new Schema({..}, { expires: '1.5h' });

      // expire in 7 days
      var schema = new Schema({..});
      schema.expires('7d');

  ### SchemaType#set(`fn`)

  Adds a setter to this schematype.

  show code

      SchemaType.prototype.set = function (fn) {
        if ('function' != typeof fn)
          throw new Error('A setter must be a function.');
        this.setters.push(fn);
        return this;
      };

  #### Parameters:

  - `fn` <Function>

  #### Returns:

  - <SchemaType> this

  #### Example:

      function capitalize (val) {
        if ('string' != typeof val) val = '';
        return val.charAt(0).toUpperCase() + val.substring(1);
      }

      var s = new Schema({ name: { type: String, set: capitalize })
      // or
      Schema.path('name').set(capitalize);

  ### SchemaType#get(`fn`)

  Adds a getter to this schematype.

  show code

      SchemaType.prototype.get = function (fn) {
        if ('function' != typeof fn)
          throw new Error('A getter must be a function.');
        this.getters.push(fn);
        return this;
      };

  #### Parameters:

  - `fn` <Function>

  #### Returns:

  - <SchemaType> this

  #### Example:

      function dob (val) {
        if (!val) return val;
        return (val.getMonth() + 1) + "/" + val.getDate() + "/" + val.getFullYear();
      }

      var s = new Schema({ born: { type: Date, get: dob })
      // or
      Schema.path('name').get(dob);

  ### SchemaType#validate(`obj`, `[error]`)

  Adds validator(s) for this document path.

  show code

      SchemaType.prototype.validate = function (obj, error) {
        if ('function' == typeof obj || obj && 'RegExp' === obj.constructor.name) {
          this.validators.push([obj, error]);
          return this;
        }

        var i = arguments.length
          , arg

        while (i--) {
          arg = arguments[i];
          if (!(arg && 'Object' == arg.constructor.name)) {
            var msg = 'Invalid validator. Received (' + typeof arg + ') '
              + arg
              + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';

            throw new Error(msg);
          }
          this.validate(arg.validator, arg.msg);
        }

        return this;
      };

  #### Parameters:

  - `obj` <RegExp, Function, Object> validator
  - `[error]` <String> optional error message

  Validators must return `Boolean`. Returning false is interpreted as validation failure.

  #### Examples:

      function validator () { ... }

      var single = [validator, 'failed']
      new Schema({ name: { type: String, validate: single }});

      var many = [
          { validator: validator, msg: 'uh oh' }
        , { validator: fn, msg: 'failed' }
      ]
      new Schema({ name: { type: String, validate: many }});

      // or utilizing SchemaType methods directly:

      var schema = new Schema({ name: 'string' });
      schema.path('name').validate(validator, 'validation failed');

  #### Asynchronous validation:

  Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The first arg passed is the value to validate, the second is an callback function that must be passed either `true` or `false` when validation is complete. Asynchronous validators open the door for retreiving other documents from the database first to validate against.

      schema.path('name').validate(function (value, respond) {
        doStuff(value, function () {
          ...
          respond(false); // validation failed
        })
       }, 'my error type');

  Validation occurs `pre('save')` or whenever you manually execute document#validate.

  If validation fails during `pre('save')` and no callback was passed to receive the error, an `error` event will be emitted on your Models associated db connection, passing the validation error object along.

      var conn = mongoose.createConnection(..);
      conn.on('error', handleError);

      var Product = conn.model('Product', yourSchema);
      var dvd = new Product(..);
      dvd.save(); // emits error on the `conn` above

  If you desire handling these errors at the Model level, attach an `error` listener to your Model and the event will instead be emitted there.

      // registering an error listener on the Model lets us handle errors more locally
      Product.on('error', handleError);

  ### SchemaType#required(`required`)

  Adds a required validator to this schematype.

  show code

      SchemaType.prototype.required = function (required) {
        var self = this;

        function __checkRequired (v) {
          // in here, `this` refers to the validating document.
          // no validation when this path wasn't selected in the query.
          if ('isSelected' in this &&
              !this.isSelected(self.path) &&
              !this.isModified(self.path)) return true;
          return self.checkRequired(v);
        }

        if (false === required) {
          this.isRequired = false;
          this.validators = this.validators.filter(function (v) {
            return v[0].name !== '__checkRequired';
          });
        } else {
          this.isRequired = true;
          this.validators.push([__checkRequired, 'required']);
        }

        return this;
      };

  #### Parameters:

  - `required` <Boolean> enable/disable the validator

  #### Returns:

  - <SchemaType> this

  #### Example:

      var s = new Schema({ born: { type: Date, required: true })
      // or
      Schema.path('name').required(true);

  ### SchemaType#getDefault(`scope`, `init`)

  Gets the default value

  show code

      SchemaType.prototype.getDefault = function (scope, init) {
        var ret = 'function' === typeof this.defaultValue
          ? this.defaultValue.call(scope)
          : this.defaultValue;

        if (null !== ret && undefined !== ret) {
          return this.cast(ret, scope, init);
        } else {
          return ret;
        }
      };

  #### Parameters:

  - `scope` <Object> the scope which callback are executed
  - `init` <Boolean>

  ### SchemaType#applySetters(`value`, `scope`, `init`)

  Applies setters

  show code

      SchemaType.prototype.applySetters = function (value, scope, init) {
        if (SchemaType._isRef(this, value, init)) return value;

        var v = value
          , setters = this.setters
          , len = setters.length

        if (!len) {
          if (null === v || undefined === v) return v;
          return init
            ? v // if we just initialized we dont recast
            : this.cast(v, scope, init)
        }

        while (len--) {
          v = setters[len].call(scope, v, this);
        }

        if (null === v || undefined === v) return v;

        // do not cast until all setters are applied #665
        v = this.cast(v, scope);

        return v;
      };

  #### Parameters:

  - `value` <Object>
  - `scope` <Object>
  - `init` <Boolean>

  ### SchemaType#applyGetters(`value`, `scope`)

  Applies getters to a value

  show code

      SchemaType.prototype.applyGetters = function (value, scope) {
        if (SchemaType._isRef(this, value, true)) return value;

        var v = value
          , getters = this.getters
          , len = getters.length;

        if (!len) {
          return v;
        }

        while (len--) {
          v = getters[len].call(scope, v, this);
        }

        return v;
      };

  #### Parameters:

  - `value` <Object>
  - `scope` <Object>

  ### SchemaType#select(`val`)

  Sets default `select()` behavior for this path.

  show code

      SchemaType.prototype.select = function select (val) {
        this.selected = !! val;
      }

  #### Parameters:

  - `val` <Boolean>

  Set to `true` if this path should always be included in the results, `false` if it should be excluded by default. This setting can be overridden at the query level.

  #### Example:

      T = db.model('T', new Schema({ x: { type: String, select: true }}));
      T.find(..); // field x will always be selected ..
      // .. unless overridden;
      T.find().select('-x').exec(callback);

  ### SchemaType#doValidate(`value`, `callback`, `scope`)

  Performs a validation of `value` using the validators declared for this SchemaType.

  show code

      SchemaType.prototype.doValidate = function (value, fn, scope) {
        var err = false
          , path = this.path
          , count = this.validators.length;

        if (!count) return fn(null);

        function validate (val, msg) {
          if (err) return;
          if (val === undefined || val) {
            --count || fn(null);
          } else {
            fn(err = new ValidatorError(path, msg));
          }
        }

        this.validators.forEach(function (v) {
          var validator = v[0]
            , message   = v[1];

          if (validator instanceof RegExp) {
            validate(validator.test(value), message);
          } else if ('function' === typeof validator) {
            if (2 === validator.length) {
              validator.call(scope, value, function (val) {
                validate(val, message);
              });
            } else {
              validate(validator.call(scope, value), message);
            }
          }
        });
      };

  #### Parameters:

  - `value` <any>
  - `callback` <Function>
  - `scope` <Object>

  ### SchemaType._isRef(`self`, `value`, `init`)

  Determines if value is a valid Reference.

  show code

      SchemaType._isRef = function (self, value, init) {
        if (init && self.options && self.options.ref) {
          if (null == value) return true;
          if (value._id && value._id.constructor.name === self.instance) return true;
        }

        return false;
      }

  #### Parameters:

  - `self` <SchemaType>
  - `value` <Object>
  - `init` <Boolean>

  #### Returns:

  - <Boolean>

- types/array.js

  ### MongooseArray(`values`, `path`, `doc`)

  Mongoose Array constructor.

  show code

      function MongooseArray (values, path, doc) {
        var arr = [];
        arr.push.apply(arr, values);
        arr.__proto__ = MongooseArray.prototype;

        arr._atomics = {};
        arr.validators = [];
        arr._path = path;

        if (doc) {
          arr._parent = doc;
          arr._schema = doc.schema.path(path);
        }

        return arr;
      };

  #### Parameters:

  - `values` <Array>
  - `path` <String>
  - `doc` <Document> parent document

  #### Inherits:

  - Array

  #### See:

  - http://bit.ly/f6CnZU

  #### NOTE:

  Values always have to be passed to the constructor to initialize, otherwise `MongooseArray#push` will mark the array as modified.

  ### MongooseArray#_cast(`value`)

  Casts a member based on this arrays schema.

  show code

      MongooseArray.prototype._cast = function (value) {
        var cast = this._schema.caster.cast
          , doc = this._parent;

        return cast.call(null, value, doc);
      };

  #### Parameters:

  - `value` <any>

  #### Returns:

  - <value> the casted value

  ### MongooseArray#_markModified(`embeddedDoc`, `embeddedPath`)

  Marks this array as modified.

  show code

      MongooseArray.prototype._markModified = function (embeddedDoc, embeddedPath) {
        var parent = this._parent
          , dirtyPath;

        if (parent) {
          if (arguments.length) {
            // If an embedded doc bubbled up the change
            dirtyPath = [this._path, this.indexOf(embeddedDoc), embeddedPath].join('.');
          } else {
            dirtyPath = this._path;
          }
          parent.markModified(dirtyPath);
        }

        return this;
      };

  #### Parameters:

  - `embeddedDoc` <EmbeddedDocument> the embedded doc that invoked this method on the Array
  - `embeddedPath` <String> the path which changed in the embeddedDoc

  If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)

  ### MongooseArray#_registerAtomic(`op`, `val`)

  Register an atomic operation with the parent.

  show code

      MongooseArray.prototype._registerAtomic = function (op, val) {
        if ('$set' == op) {
          // $set takes precedence over all other ops.
          // mark entire array modified.
          this._atomics = { $set: val };
          this._markModified();
          return this;
        }

        var atomics = this._atomics;

        // reset pop/shift after save
        if ('$pop' == op && !('$pop' in atomics)) {
          var self = this;
          this._parent.once('save', function () {
            self._popped = self._shifted = null;
          });
        }

        if (this._atomics.$set) {
          return this;
        }

        // check for impossible $atomic combos (Mongo denies more than one
        // $atomic op on a single path
        if (Object.keys(atomics).length && !(op in atomics)) {
          // a different op was previously registered.
          // save the entire thing.
          this._atomics = { $set: this };
          this._markModified();
          return this;
        }

        if (op === '$pullAll' || op === '$pushAll' || op === '$addToSet') {
          atomics[op] || (atomics[op] = []);
          atomics[op] = atomics[op].concat(val);
        } else if (op === '$pullDocs') {
          var pullOp = atomics['$pull'] || (atomics['$pull'] = {})
            , selector = pullOp['_id'] || (pullOp['_id'] = {'$in' : [] });
          selector['$in'] = selector['$in'].concat(val);
        } else {
          atomics[op] = val;
        }

        this._markModified();
        return this;
      };

  #### Parameters:

  - `op` <Array> operation
  - `val` <any>

  ### MongooseArray#hasAtomics()

  Returns the number of pending atomic operations to send to the db for this array.

  show code

      MongooseArray.prototype.hasAtomics = function hasAtomics () {
        if (!(this._atomics && 'Object' === this._atomics.constructor.name)) {
          return 0;
        }

        return Object.keys(this._atomics).length;
      }

  #### Returns:

  - <Number>

  ### MongooseArray#push(`[args...]`)

  Wraps `Array#push` with proper change tracking.

  show code

      MongooseArray.prototype.push = function () {
        var values = [].map.call(arguments, this._cast, this)
          , ret = [].push.apply(this, values);

        // $pushAll might be fibbed (could be $push). But it makes it easier to
        // handle what could have been $push, $pushAll combos
        this._registerAtomic('$pushAll', values);
        return ret;
      };

  #### Parameters:

  - `[args...]` <Object>

  ### MongooseArray#nonAtomicPush(`[args...]`)

  Pushes items to the array non-atomically.

  show code

      MongooseArray.prototype.nonAtomicPush = function () {
        var values = [].map.call(arguments, this._cast, this)
          , ret = [].push.apply(this, values);
        this._registerAtomic('$set', this);
        return ret;
      };

  #### Parameters:

  - `[args...]` <any>

  #### NOTE:

  marks the entire array as modified, which if saved, will store it as a `$set` operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

  ### MongooseArray#$pop()

  Pops the array atomically at most one time per document `save()`.

  #### See:

  - mongodb

  #### NOTE:

  Calling this mulitple times on an array before saving sends the same command as calling it once.
  This update is implemented using the MongoDB $pop method which enforces this restriction.

      doc.array = [1,2,3];

       var popped = doc.array.$pop();
       console.log(popped); // 3
       console.log(doc.array); // [1,2]

       // no affect
       popped = doc.array.$pop();
       console.log(doc.array); // [1,2]

       doc.save(function (err) {
         if (err) return handleError(err);

         // we saved, now $pop works again
         popped = doc.array.$pop();
         console.log(popped); // 2
         console.log(doc.array); // [1]
       })

  ### MongooseArray#pop()

  Wraps `Array#pop` with proper change tracking.

  show code

      MongooseArray.prototype.pop = function () {
        var ret = [].pop.call(this);
        this._registerAtomic('$set', this);
        return ret;
      };

  #### See:

  - MongooseArray#$pop

  #### Note:

  marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it.

  ### MongooseArray#$shift()

  Atomically shifts the array at most one time per document `save()`.

  #### See:

  - mongodb

  #### NOTE:

  Calling this mulitple times on an array before saving sends the same command as calling it once.
  This update is implemented using the MongoDB $pop method which enforces this restriction.

      doc.array = [1,2,3];

       var shifted = doc.array.$shift();
       console.log(shifted); // 1
       console.log(doc.array); // [2,3]

       // no affect
       shifted = doc.array.$shift();
       console.log(doc.array); // [2,3]

       doc.save(function (err) {
         if (err) return handleError(err);

         // we saved, now $shift works again
         shifted = doc.array.$shift();
         console.log(shifted ); // 2
         console.log(doc.array); // [3]
       })

  ### MongooseArray#shift()

  Wraps `Array#shift` with proper change tracking.

  show code

      MongooseArray.prototype.shift = function () {
        var ret = [].shift.call(this);
        this._registerAtomic('$set', this);
        return ret;
      };

  #### Example:

      doc.array = [2,3];
      var res = doc.array.shift();
      console.log(res) // 2
      console.log(doc.array) // [3]

  #### Note:

  marks the entire array as modified, which if saved, will store it as a `$set` operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

  ### MongooseArray#remove(`[args...]`)

  Removes items from an array atomically

  show code

      MongooseArray.prototype.remove = function () {
        var args = [].map.call(arguments, this._cast, this);
        if (args.length == 1)
          this.pull(args[0]);
        else
          this.pull.apply(this, args);
        return args;
      };

  #### Parameters:

  - `[args...]` <Object> values to remove

  #### See:

  - mongodb

  #### Examples:

      doc.array.remove(ObjectId)
      doc.array.remove('tag 1', 'tag 2')

  ### MongooseArray#pull(`[args...]`)

  Pulls items from the array atomically.

  show code

      MongooseArray.prototype.pull = function () {
        var values = [].map.call(arguments, this._cast, this)
          , cur = this._parent.get(this._path)
          , i = cur.length
          , mem;

        while (i--) {
          mem = cur[i];
          if (mem instanceof EmbeddedDocument) {
            if (values.some(function (v) { return v.equals(mem); } )) {
              [].splice.call(cur, i, 1);
            }
          } else if (~cur.indexOf.call(values, mem)) {
            [].splice.call(cur, i, 1);
          }
        }

        if (values[0] instanceof EmbeddedDocument) {
          this._registerAtomic('$pullDocs', values.map( function (v) { return v._id; } ));
        } else {
          this._registerAtomic('$pullAll', values);
        }

        return this;
      };

  #### Parameters:

  - `[args...]` <any>

  #### See:

  - mongodb

  ### MongooseArray#splice()

  Wraps `Array#splice` with proper change tracking.

  show code

      MongooseArray.prototype.splice = function () {
        if (arguments.length) {
          var ret = [].splice.apply(this, arguments);
          this._registerAtomic('$set', this);
        }
        return ret;
      };

  #### Note:

  marks the entire array as modified, which if saved, will store it as a `$set` operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

  ### MongooseArray#unshift()

  Wraps `Array#unshift` with proper change tracking.

  show code

      MongooseArray.prototype.unshift = function () {
        var values = [].map.call(arguments, this._cast, this);
        [].unshift.apply(this, values);
        this._registerAtomic('$set', this);
        return this.length;
      };

  #### Note:

  marks the entire array as modified, which if saved, will store it as a `$set` operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

  ### MongooseArray#sort()

  Wraps `Array#sort` with proper change tracking.

  show code

      MongooseArray.prototype.sort = function () {
        var ret = [].sort.apply(this, arguments);
        this._registerAtomic('$set', this);
        return ret;
      }

  #### NOTE:

  marks the entire array as modified, which if saved, will store it as a `$set` operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it.

  ### MongooseArray#addToSet(`[args...]`)

  Adds values to the array if not already present.

  show code

      MongooseArray.prototype.addToSet = function addToSet () {
        var values = [].map.call(arguments, this._cast, this)
          , added = []
          , type = values[0] instanceof EmbeddedDocument ? 'doc' :
                   values[0] instanceof Date ? 'date' :
                   '';

        values.forEach(function (v) {
          var found;
          switch (type) {
            case 'doc':
              found = this.some(function(doc){ return doc.equals(v) });
              break;
            case 'date':
              var val = +v;
              found = this.some(function(d){ return +d === val });
              break;
            default:
              found = ~this.indexOf(v);
          }

          if (!found) {
            [].push.call(this, v);
            this._registerAtomic('$addToSet', v);
            [].push.call(added, v);
          }
        }, this);

        return added;
      };

  #### Parameters:

  - `[args...]` <any>

  #### Returns:

  - <Array> the values that were added

  #### Example:

      console.log(doc.array) // [2,3,4]
      var added = doc.array.addToSet(4,5);
      console.log(doc.array) // [2,3,4,5]
      console.log(added)     // [5]

  ### MongooseArray#toObject(`options`)

  Returns a native js Array.

  show code

      MongooseArray.prototype.toObject = function (options) {
        if (options && options.depopulate && this[0] instanceof Document) {
          return this.map(function (doc) {
            return doc._id;
          });
        }

        // return this.slice()?
        return this.map(function (doc) {
          return doc;
        });
      };

  #### Parameters:

  - `options` <Object>

  #### Returns:

  - <Array>

  ### MongooseArray#inspect()

  Helper for console.log

  show code

      MongooseArray.prototype.inspect = function () {
        return '[' + this.map(function (doc) {
          return ' ' + doc;
        }) + ' ]';
      };

  ### MongooseArray#indexOf(`obj`)

  Return the index of `obj` or `-1` if not found.

  show code

      MongooseArray.prototype.indexOf = function indexOf (obj) {
        if (obj instanceof ObjectId) obj = obj.toString();
        for (var i = 0, len = this.length; i < len; ++i) {
          if (obj == this[i])
            return i;
        }
        return -1;
      };

  #### Parameters:

  - `obj` <Object> the item to look for

  #### Returns:

  - <Number>

  ### MongooseArray#_parent

  Parent owner document

  ### MongooseArray#_atomics

  Stores a queue of atomic operations to perform

- types/buffer.js

  ### MongooseBuffer(`value`, `encode`, `offset`)

  Mongoose Buffer constructor.

  show code

      function MongooseBuffer (value, encode, offset) {
        var length = arguments.length;
        var val;

        if (0 === length || null === arguments[0] || undefined === arguments[0]) {
          val = 0;
        } else {
          val = value;
        }

        var encoding;
        var path;
        var doc;

        if (Array.isArray(encode)) {
          // internal casting
          path = encode[0];
          doc = encode[1];
        } else {
          encoding = encode;
        }

        var buf = new Buffer(val, encoding, offset);
        buf.__proto__ = MongooseBuffer.prototype;

        // make sure these internal props don't show up in Object.keys()
        Object.defineProperties(buf, {
            validators: { value: [] }
          , _path: { value: path }
          , _parent: { value: doc }
        });

        if (doc && "string" === typeof path) {
          Object.defineProperty(buf, '_schema', {
              value: doc.schema.path(path)
          });
        }

        return buf;
      };

  #### Parameters:

  - `value` <Buffer>
  - `encode` <String>
  - `offset` <Number>

  #### Inherits:

  - Buffer

  #### See:

  - http://bit.ly/f6CnZU

  Values always have to be passed to the constructor to initialize.

  ### MongooseBuffer#_markModified()

  Marks this buffer as modified.

  show code

      MongooseBuffer.prototype._markModified = function () {
        var parent = this._parent;

        if (parent) {
          parent.markModified(this._path);
        }
        return this;
      };

  ### MongooseBuffer#write()

  Writes the buffer.

  show code

      MongooseBuffer.prototype.write = function () {
        var written = Buffer.prototype.write.apply(this, arguments);

        if (written > 0) {
          this._markModified();
        }

        return written;
      };

  ### MongooseBuffer#copy(`target`)

  Copies the buffer.

  show code

      MongooseBuffer.prototype.copy = function (target) {
        var ret = Buffer.prototype.copy.apply(this, arguments);

        if (target instanceof MongooseBuffer) {
          target._markModified();
        }

        return ret;
      };

  #### Parameters:

  - `target` <Buffer>

  #### Returns:

  - <MongooseBuffer>

  #### Note:

  `Buffer#copy` does not mark `target` as modified so you must copy from a `MongooseBuffer` for it to work as expected. This is a work around since `copy` modifies the target, not this.

  ### MongooseBuffer#toObject(`[subtype]`)

  Converts this buffer to its Binary type representation.

  show code

      MongooseBuffer.prototype.toObject = function (subtype) {
        subtype = typeof subtype !== 'undefined' ? subtype : 0x00
        return new Binary(this, subtype);
      };

  #### Parameters:

  - `[subtype]` <Hex>

  #### Returns:

  - <Binary>

  #### See:

  - http://bsonspec.org/#/specification

  #### SubTypes:

  - 0x00: Binary/Generic
  - 0x01: Function
  - 0x02: Binary (Deprecated, 0x00 is new default)
  - 0x03: UUID
  - 0x04: MD5
  - 0x80: User Defined

  ### MongooseBuffer#_parent

  Parent owner document

- types/documentarray.js

  ### MongooseDocumentArray(`values`, `path`, `doc`)

  DocumentArray constructor

  show code

      function MongooseDocumentArray (values, path, doc) {
        var arr = [];

        // Values always have to be passed to the constructor to initialize, since
        // otherwise MongooseArray#push will mark the array as modified to the parent.
        arr.push.apply(arr, values);
        arr.__proto__ = MongooseDocumentArray.prototype;

        arr._atomics = {};
        arr.validators = [];
        arr._path = path;

        if (doc) {
          arr._parent = doc;
          arr._schema = doc.schema.path(path);
          doc.on('save', arr.notify('save'));
          doc.on('isNew', arr.notify('isNew'));
        }

        return arr;
      };

  #### Parameters:

  - `values` <Array>
  - `path` <String> the path to this array
  - `doc` <Document> parent document

  #### Returns:

  - <MongooseDocumentArray>

  #### Inherits:

  - MongooseArray

  #### See:

  - http://bit.ly/f6CnZU

  ### MongooseDocumentArray#_cast()

  Overrides MongooseArray#cast

  show code

      MongooseDocumentArray.prototype._cast = function (value) {
        var doc = new this._schema.casterConstructor(value, this);
        return doc;
      };

  ### MongooseDocumentArray#id(`id`)

  Searches array items for the first document with a matching id.

  show code

      MongooseDocumentArray.prototype.id = function (id) {
        var casted
          , _id;

        try {
          casted = ObjectId.toString(ObjectIdSchema.prototype.cast.call({}, id));
        } catch (e) {
          casted = null;
        }

        for (var i = 0, l = this.length; i < l; i++) {
          _id = this[i].get('_id');
          if (!(_id instanceof ObjectId)) {
            if (String(id) == _id)
              return this[i];
          } else {
            if (casted == _id)
              return this[i];
          }
        }

        return null;
      };

  #### Parameters:

  - `id` <ObjectId, String, Number, Buffer>

  #### Returns:

  - <EmbeddedDocument, null> the subdocuent or null if not found.

  #### Example:

      var embeddedDoc = m.array.id(some_id);

  ### MongooseDocumentArray#toObject()

  Returns a native js Array of plain js objects

  show code

      MongooseDocumentArray.prototype.toObject = function () {
        return this.map(function (doc) {
          return doc && doc.toObject() || null;
        });
      };

  #### Returns:

  - <Array>

  #### NOTE:

  Each sub-document is converted to a plain object by calling its `#toObject` method.

  ### MongooseDocumentArray#inspect()

  Helper for console.log

  show code

      MongooseDocumentArray.prototype.inspect = function () {
        return '[' + this.map(function (doc) {
          if (doc) {
            return doc.inspect
              ? doc.inspect()
              : util.inspect(doc)
          }
          return 'null'
        }).join('
      ') + ']';
      };

  ### MongooseDocumentArray#create(`obj`)

  Creates a subdocument casted to this schema.

  show code

      MongooseDocumentArray.prototype.create = function (obj) {
        return new this._schema.casterConstructor(obj);
      }

  #### Parameters:

  - `obj` <Object> the value to cast to this arrays SubDocument schema

  This is the same subdocument constructor used for casting.

  ### MongooseDocumentArray#notify(`event`)

  Creates a fn that notifies all child docs of `event`.

  show code

      MongooseDocumentArray.prototype.notify = function notify (event) {
        var self = this;
        return function notify (val) {
          var i = self.length;
          while (i--) {
            self[i].emit(event, val);
          }
        }
      }

  #### Parameters:

  - `event` <String>

  #### Returns:

  - <Function>

- types/embedded.js

  ### EmbeddedDocument(`obj`, `parentArr`, `skipId`)

  EmbeddedDocument constructor.

  show code

      function EmbeddedDocument (obj, parentArr, skipId) {
        if (parentArr) {
          this.__parentArray = parentArr;
          this.__parent = parentArr._parent;
        } else {
          this.__parentArray = undefined;
          this.__parent = undefined;
        }

        Document.call(this, obj, undefined, skipId);

        var self = this;
        this.on('isNew', function (val) {
          self.isNew = val;
        });
      };

  #### Parameters:

  - `obj` <Object> js object returned from the db
  - `parentArr` <MongooseDocumentArray> the parent array of this document
  - `skipId` <Boolean>

  #### Inherits:

  - Document

  ### EmbeddedDocument#markModified(`path`)

  Marks the embedded doc modified.

  show code

      EmbeddedDocument.prototype.markModified = function (path) {
        if (!this.__parentArray) return;

        this._activePaths.modify(path);

        if (this.isNew) {
          // Mark the WHOLE parent array as modified
          // if this is a new document (i.e., we are initializing
          // a document),
          this.__parentArray._markModified();
        } else
          this.__parentArray._markModified(this, path);
      };

  #### Parameters:

  - `path` <String> the path which changed

  #### Example:

      var doc = blogpost.comments.id(hexstring);
      doc.mixed.type = 'changed';
      doc.markModified('mixed.type');

  ### EmbeddedDocument#save(`[fn]`)

  Used as a stub for hooks.js

  show code

      EmbeddedDocument.prototype.save = function(fn) {
        if (fn)
          fn(null);
        return this;
      };

  #### Parameters:

  - `[fn]` <Function>

  #### Returns:

  - <EmbeddedDocument> this

  #### NOTE:

  This is a no-op. Does not actually save the doc to the db.

  ### EmbeddedDocument#remove(`[fn]`)

  Removes the subdocument from its parent array.

  show code

      EmbeddedDocument.prototype.remove = function (fn) {
        if (!this.__parentArray) return this;

        var _id;
        if (!this.willRemove) {
          _id = this._doc._id;
          if (!_id) {
            throw new Error('For your own good, Mongoose does not know ' +
                            'how to remove an EmbeddedDocument that has no _id');
          }
          this.__parentArray.pull({ _id: _id });
          this.willRemove = true;
        }

        if (fn)
          fn(null);

        return this;
      };

  #### Parameters:

  - `[fn]` <Function>

  ### EmbeddedDocument#update()

  Override #update method of parent documents.

  show code

      EmbeddedDocument.prototype.update = function () {
        throw new Error('The #update method is not available on EmbeddedDocuments');
      }

  ### EmbeddedDocument#inspect()

  Helper for console.log

  show code

      EmbeddedDocument.prototype.inspect = function () {
        return inspect(this.toObject());
      };

  ### EmbeddedDocument#invalidate(`path`, `err`)

  Marks a path as invalid, causing validation to fail.

  show code

      EmbeddedDocument.prototype.invalidate = function (path, err, first) {
        if (!this.__parent) return false;
        var index = this.__parentArray.indexOf(this);
        var parentPath = this.__parentArray._path;
        var fullPath = [parentPath, index, path].join('.');
        this.__parent.invalidate(fullPath, err);
        if (first)
          this._validationError = ownerDocument(this)._validationError;
        return true;
      }

  #### Parameters:

  - `path` <String> the field to invalidate
  - `err` <String, Error> error which states the reason `path` was invalid

  #### Returns:

  - <Boolean>

  ### EmbeddedDocument#ownerDocument()

  Returns the top level document of this sub-document.

  show code

      EmbeddedDocument.prototype.ownerDocument = function () {
        return ownerDocument(this);
      }

  #### Returns:

  - <Document>

  ### EmbeddedDocument#parent()

  Returns this sub-documents parent document.

  show code

      EmbeddedDocument.prototype.parent = function () {
        return this.__parent;
      }

  ### EmbeddedDocument#parentArray()

  Returns this sub-documents parent array.

  show code

      EmbeddedDocument.prototype.parentArray = function () {
        return this.__parentArray;
      }

- types/objectid.js

  ### ObjectId()

  ObjectId type constructor

  #### Example

      var id = new mongoose.Types.ObjectId;

  ### ObjectId.fromString(`str`)

  Creates an ObjectId from `str`

  show code

      ObjectId.fromString;

  #### Parameters:

  - `str` <ObjectId, HexString>

  #### Returns:

  - <ObjectId>

  ### ObjectId.toString(`oid`)

  Converts `oid` to a string.

  show code

      ObjectId.toString;

  #### Parameters:

  - `oid` <ObjectId> ObjectId instance

  #### Returns:

  - <String>

- utils.js

  ### exports.toCollectionName(`name`)

  Produces a collection name from model `name`.

  show code

      exports.toCollectionName = function (name) {
        if ('system.profile' === name) return name;
        if ('system.indexes' === name) return name;
        return pluralize(name.toLowerCase());
      };

  #### Parameters:

  - `name` <String> a model name

  #### Returns:

  - <String> a collection name

  ### exports.pluralization

  Pluralization rules.

  show code

      exports.pluralization = [
        [/(m)an$/gi, '$1en'],
        [/(pe)rson$/gi, '$1ople'],
        [/(child)$/gi, '$1ren'],
        [/^(ox)$/gi, '$1en'],
        [/(ax|test)is$/gi, '$1es'],
        [/(octop|vir)us$/gi, '$1i'],
        [/(alias|status)$/gi, '$1es'],
        [/(bu)s$/gi, '$1ses'],
        [/(buffal|tomat|potat)o$/gi, '$1oes'],
        [/([ti])um$/gi, '$1a'],
        [/sis$/gi, 'ses'],
        [/(?:([^f])fe|([lr])f)$/gi, '$1$2ves'],
        [/(hive)$/gi, '$1s'],
        [/([^aeiouy]|qu)y$/gi, '$1ies'],
        [/(x|ch|ss|sh)$/gi, '$1es'],
        [/(matr|vert|ind)ix|ex$/gi, '$1ices'],
        [/([m|l])ouse$/gi, '$1ice'],
        [/(quiz)$/gi, '$1zes'],
        [/s$/gi, 's'],
        [/$/gi, 's']
      ];
      var rules = exports.pluralization;

  These rules are applied while processing the argument to `toCollectionName`.

  ### exports.uncountables

  Uncountable words.

  show code

      exports.uncountables = [
        'advice',
        'energy',
        'excretion',
        'digestion',
        'cooperation',
        'health',
        'justice',
        'labour',
        'machinery',
        'equipment',
        'information',
        'pollution',
        'sewage',
        'paper',
        'money',
        'species',
        'series',
        'rain',
        'rice',
        'fish',
        'sheep',
        'moose',
        'deer',
        'news'
      ];
      var uncountables = exports.uncountables;

  These words are applied while processing the argument to `toCollectionName`.

  ### exports.deepEqual(`a`, `b`)

  Determines if `a` and `b` are deep equal.

  show code

      exports.deepEqual = function deepEqual (a, b) {
        if (a === b) return true;

        if (a instanceof Date && b instanceof Date)
          return a.getTime() === b.getTime();

        if (a instanceof ObjectId && b instanceof ObjectId) {
          return a.toString() === b.toString();
        }

        if (typeof a !== 'object' && typeof b !== 'object')
          return a == b;

        if (a === null || b === null || a === undefined || b === undefined)
          return false

        if (a.prototype !== b.prototype) return false;

        // Handle MongooseNumbers
        if (a instanceof Number && b instanceof Number) {
          return a.valueOf() === b.valueOf();
        }

        if (Buffer.isBuffer(a)) {
          if (!Buffer.isBuffer(b)) return false;
          if (a.length !== b.length) return false;
          for (var i = 0, len = a.length; i < len; ++i) {
            if (a[i] !== b[i]) return false;
          }
          return true;
        }

        if (isMongooseObject(a)) a = a.toObject();
        if (isMongooseObject(b)) b = b.toObject();

        try {
          var ka = Object.keys(a),
              kb = Object.keys(b),
              key, i;
        } catch (e) {//happens when one is a string literal and the other isn't
          return false;
        }

        // having the same number of owned properties (keys incorporates
        // hasOwnProperty)
        if (ka.length != kb.length)
          return false;

        //the same set of keys (although not necessarily the same order),
        ka.sort();
        kb.sort();

        //~~~cheap key test
        for (i = ka.length - 1; i >= 0; i--) {
          if (ka[i] != kb[i])
            return false;
        }

        //equivalent values for every corresponding key, and
        //~~~possibly expensive deep test
        for (i = ka.length - 1; i >= 0; i--) {
          key = ka[i];
          if (!deepEqual(a[key], b[key])) return false;
        }

        return true;
      };

  #### Parameters:

  - `a` <any> a value to compare to `b`
  - `b` <any> a value to compare to `a`

  #### Returns:

  - <Boolean>

  Modified from node/lib/assert.js

  ### exports.clone(`obj`, `options`)

  Object clone with Mongoose natives support.

  show code

      exports.clone = function clone (obj, options) {
        if (obj === undefined || obj === null)
          return obj;

        if (Array.isArray(obj))
          return cloneArray(obj, options);

        if (isMongooseObject(obj)) {
          if (options && options.json && 'function' === typeof obj.toJSON) {
            return obj.toJSON(options);
          } else {
            return obj.toObject(options);
          }
        }

        if ('Object' === obj.constructor.name)
          return cloneObject(obj, options);

        if ('Date' === obj.constructor.name || 'Function' === obj.constructor.name)
          return new obj.constructor(+obj);

        if ('RegExp' === obj.constructor.name)
          return new RegExp(obj.source);

        if (obj instanceof ObjectId) {
          return new ObjectId(obj.id);
        }

        if (obj.valueOf)
          return obj.valueOf();
      };
      var clone = exports.clone;

  #### Parameters:

  - `obj` <Object> the object to clone
  - `options` <Object>

  #### Returns:

  - <Object> the cloned object

  Creates a minimal data Object.
  It does not clone empty Arrays, empty Objects, and undefined values.
  This makes the data payload sent to MongoDB as minimal as possible.

  ### exports.options(`defaults`, `options`)

  Copies and merges options with defaults.

  show code

      exports.options = function (defaults, options) {
        var keys = Object.keys(defaults)
          , i = keys.length
          , k ;

        options = options || {};

        while (i--) {
          k = keys[i];
          if (!(k in options)) {
            options[k] = defaults[k];
          }
        }

        return options;
      };

  #### Parameters:

  - `defaults` <Object>
  - `options` <Object>

  #### Returns:

  - <Object> the merged object

  ### exports.random()

  Generates a random string

  show code

      exports.random = function () {
        return Math.random().toString().substr(3);
      };

  ### exports.merge(`to`, `from`)

  Merges `from` into `to` without overwriting existing properties.

  show code

      exports.merge = function merge (to, from) {
        var keys = Object.keys(from)
          , i = keys.length
          , key

        while (i--) {
          key = keys[i];
          if ('undefined' === typeof to[key]) {
            to[key] = from[key];
          } else {
            merge(to[key], from[key]);
          }
        }
      };

  #### Parameters:

  - `to` <Object>
  - `from` <Object>

  ### exports.args()

  A faster Array.prototype.slice.call(arguments) alternative

  show code

      exports.args = function (args, slice, sliceEnd) {
        var ret = [];
        var start = slice || 0;
        var end = 3 === arguments.length
          ? sliceEnd
          : args.length;

        for (var i = start; i < end; ++i) {
          ret[i - start] = args[i];
        }

        return ret;
      }

  ### exports.tick(`callback`)

  process.nextTick helper.

  show code

      exports.tick = function tick (callback) {
        if ('function' !== typeof callback) return;
        return function () {
          try {
            callback.apply(this, arguments);
          } catch (err) {
            // only nextTick on err to get out of
            // the event loop and avoid state corruption.
            process.nextTick(function () {
              throw err;
            });
          }
        }
      }

  #### Parameters:

  - `callback` <Function>

  Wraps `callback` in a try/catch + nextTick.

  node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.

  ### exports.isMongooseObject(`v`)

  Returns if `v` is a mongoose object that has a `toObject()` method we can use.

  show code

      exports.isMongooseObject = function (v) {
        Document || (Document = require('./document'));
        MongooseArray || (MongooseArray = require('./types').Array);
        MongooseBuffer || (MongooseBuffer = require('./types').Buffer);

        return v instanceof Document ||
               v instanceof MongooseArray ||
               v instanceof MongooseBuffer
      }
      var isMongooseObject = exports.isMongooseObject;

  #### Parameters:

  - `v` <any>

  This is for compatibility with libs like Date.js which do foolish things to Natives.

  ### exports.expires(`object`)

  Converts `expires` options of index objects to `expiresAfterSeconds` options for MongoDB.

  show code

      exports.expires = function expires (object) {
        if (!(object && 'Object' == object.constructor.name)) return;
        if (!('expires' in object)) return;

        var when;
        if ('string' != typeof object.expires) {
          when = object.expires;
        } else {
          when = Math.round(ms(object.expires) / 1000);
        }
        object.expiresAfterSeconds = when;
        delete object.expires;
      }

  #### Parameters:

  - `object` <Object>

- virtualtype.js

  ### VirtualType()

  VirtualType constructor

  show code

      function VirtualType (options) {
        this.getters = [];
        this.setters = [];
        this.options = options || {};
      }

  This is what mongoose uses to define virtual attributes via `Schema.prototype.virtual`.

  #### Example:

      var fullname = schema.virtual('fullname');
      fullname instanceof mongoose.VirtualType // true

  ### VirtualType#get(`fn`)

  Defines a getter.

  show code

      VirtualType.prototype.get = function (fn) {
        this.getters.push(fn);
        return this;
      };

  #### Parameters:

  - `fn` <Function>

  #### Returns:

  - <VirtualType> this

  #### Example:

      var virtual = schema.virtual('fullname');
      virtual.get(function () {
        return this.name.first + ' ' + this.name.last;
      });

  ### VirtualType#set(`fn`)

  Defines a setter.

  show code

      VirtualType.prototype.set = function (fn) {
        this.setters.push(fn);
        return this;
      };

  #### Parameters:

  - `fn` <Function>

  #### Returns:

  - <VirtualType> this

  #### Example:

      var virtual = schema.virtual('fullname');
      virtual.set(function (v) {
        var parts = v.split(' ');
        this.name.first = parts[0];
        this.name.last = parts[1];
      });

  ### VirtualType#applyGetters(`value`, `scope`)

  Applies getters to `value` using optional `scope`.

  show code

      VirtualType.prototype.applyGetters = function (value, scope) {
        var v = value;
        for (var l = this.getters.length - 1; l >= 0; l--){
          v = this.getters[l].call(scope, v);
        }
        return v;
      };

  #### Parameters:

  - `value` <Object>
  - `scope` <Object>

  #### Returns:

  - <any> the value after applying all getters

  ### VirtualType#applySetters(`value`, `scope`)

  Applies setters to `value` using optional `scope`.

  show code

      VirtualType.prototype.applySetters = function (value, scope) {
        var v = value;
        for (var l = this.setters.length - 1; l >= 0; l--){
          this.setters[l].call(scope, v);
        }
        return v;
      };

  #### Parameters:

  - `value` <Object>
  - `scope` <Object>

  #### Returns:

  - <any> the value after applying all setters