arnaucube
arnaucube/thoughtsPublic Self-hosted repository
thoughts/node_modules/mongoose/lib/schema.js
node_modules/mongoose/lib/schema.jsRaw
  1/*!
  2 * Module dependencies.
  3 */
  4
  5var EventEmitter = require('events').EventEmitter
  6  , VirtualType = require('./virtualtype')
  7  , utils = require('./utils')
  8  , NamedScope
  9  , Query
 10  , Types
 11
 12/**
 13 * Schema constructor.
 14 *
 15 * ####Example:
 16 *
 17 *     var child = new Schema({ name: String });
 18 *     var schema = new Schema({ name: String, age: Number, children: [child] });
 19 *     var Tree = mongoose.model('Tree', schema);
 20 *
 21 *     // setting schema options
 22 *     new Schema({ name: String }, { _id: false, autoIndex: false })
 23 *
 24 * ####Options:
 25 *
 26 * - [autoIndex](/docs/guide.html#autoIndex): bool - defaults to true
 27 * - [bufferCommands](/docs/guide.html#bufferCommands): bool - defaults to true
 28 * - [capped](/docs/guide.html#capped): bool - defaults to false
 29 * - [collection](/docs/guide.html#collection): string - no default
 30 * - [id](/docs/guide.html#id): bool - defaults to true
 31 * - [_id](/docs/guide.html#_id): bool - defaults to true
 32 * - `minimize`: bool - controls [document#toObject](#document_Document-toObject) behavior when called manually - defaults to true
 33 * - [read](/docs/guide.html#read): string
 34 * - [safe](/docs/guide.html#safe): bool - defaults to true.
 35 * - [shardKey](/docs/guide.html#shardKey): bool - defaults to `null`
 36 * - [strict](/docs/guide.html#strict): bool - defaults to true
 37 * - [toJSON](/docs/guide.html#toJSON) - object - no default
 38 * - [toObject](/docs/guide.html#toObject) - object - no default
 39 * - [versionKey](/docs/guide.html#versionKey): bool - defaults to "__v"
 40 *
 41 * ####Note:
 42 *
 43 * _When nesting schemas, (`children` in the example above), always declare the child schema first before passing it into is parent._
 44 *
 45 * @param {Object} definition
 46 * @inherits NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter
 47 * @event `init`: Emitted after the schema is compiled into a `Model`.
 48 * @api public
 49 */
 50
 51function Schema (obj, options) {
 52  if (!(this instanceof Schema))
 53    return new Schema(obj, options);
 54
 55  this.paths = {};
 56  this.subpaths = {};
 57  this.virtuals = {};
 58  this.nested = {};
 59  this.inherits = {};
 60  this.callQueue = [];
 61  this._indexes = [];
 62  this.methods = {};
 63  this.statics = {};
 64  this.tree = {};
 65  this._requiredpaths = undefined;
 66
 67  this.options = this.defaultOptions(options);
 68
 69  // build paths
 70  if (obj) {
 71    this.add(obj);
 72  }
 73
 74  // ensure the documents get an auto _id unless disabled
 75  var auto_id = !this.paths['_id'] && (!this.options.noId && this.options._id);
 76  if (auto_id) {
 77    this.add({ _id: {type: Schema.ObjectId, auto: true} });
 78  }
 79
 80  // ensure the documents receive an id getter unless disabled
 81  var autoid = !this.paths['id'] && (!this.options.noVirtualId && this.options.id);
 82  if (autoid) {
 83    this.virtual('id').get(idGetter);
 84  }
 85}
 86
 87/*!
 88 * Returns this documents _id cast to a string.
 89 */
 90
 91function idGetter () {
 92  if (this.$__._id) {
 93    return this.$__._id;
 94  }
 95
 96  return this.$__._id = null == this._id
 97    ? null
 98    : String(this._id);
 99}
100
101/*!
102 * Inherit from EventEmitter.
103 */
104
105Schema.prototype.__proto__ = EventEmitter.prototype;
106
107/**
108 * Schema as flat paths
109 *
110 * ####Example:
111 *     {
112 *         '_id'        : SchemaType,
113 *       , 'nested.key' : SchemaType,
114 *     }
115 *
116 * @api private
117 * @property paths
118 */
119
120Schema.prototype.paths;
121
122/**
123 * Schema as a tree
124 *
125 * ####Example:
126 *     {
127 *         '_id'     : ObjectId
128 *       , 'nested'  : {
129 *             'key' : String
130 *         }
131 *     }
132 *
133 * @api private
134 * @property tree
135 */
136
137Schema.prototype.tree;
138
139/**
140 * Returns default options for this schema, merged with `options`.
141 *
142 * @param {Object} options
143 * @return {Object}
144 * @api private
145 */
146
147Schema.prototype.defaultOptions = function (options) {
148  if (options && false === options.safe) {
149    options.safe = { w: 0 };
150  }
151
152  options = utils.options({
153      strict: true
154    , bufferCommands: true
155    , capped: false // { size, max, autoIndexId }
156    , versionKey: '__v'
157    , minimize: true
158    , autoIndex: true
159    , shardKey: null
160    , read: null
161    // the following are only applied at construction time
162    , noId: false // deprecated, use { _id: false }
163    , _id: true
164    , noVirtualId: false // deprecated, use { id: false }
165    , id: true
166  }, options);
167
168  if (options.read)
169    options.read = utils.readPref(options.read);
170
171  return options;
172}
173
174/**
175 * Adds key path / schema type pairs to this schema.
176 *
177 * ####Example:
178 *
179 *     var ToySchema = new Schema;
180 *     ToySchema.add({ name: 'string', color: 'string', price: 'number' });
181 *
182 * @param {Object} obj
183 * @param {String} prefix
184 * @api public
185 */
186
187Schema.prototype.add = function add (obj, prefix) {
188  prefix = prefix || '';
189  var keys = Object.keys(obj);
190
191  for (var i = 0; i < keys.length; ++i) {
192    var key = keys[i];
193
194    if (null == obj[key]) {
195      throw new TypeError('Invalid value for schema path `'+ prefix + key +'`');
196    }
197
198    if (utils.isObject(obj[key]) && (!obj[key].constructor || 'Object' == obj[key].constructor.name) && (!obj[key].type || obj[key].type.type)) {
199      if (Object.keys(obj[key]).length) {
200        // nested object { last: { name: String }}
201        this.nested[prefix + key] = true;
202        this.add(obj[key], prefix + key + '.');
203      } else {
204        this.path(prefix + key, obj[key]); // mixed type
205      }
206    } else {
207      this.path(prefix + key, obj[key]);
208    }
209  }
210};
211
212/**
213 * Reserved document keys.
214 *
215 * 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.
216 *
217 *      on, emit, _events, db, init, isNew, errors, schema, options, modelName, collection, _pres, _posts, toObject
218 *
219 * _NOTE:_ Use of these terms as method names is permitted, but play at your own risk, as they may be existing mongoose document methods you are stomping on.
220 *
221 *      var schema = new Schema(..);
222 *      schema.methods.init = function () {} // potentially breaking
223 */
224
225Schema.reserved = Object.create(null);
226var reserved = Schema.reserved;
227reserved.on =
228reserved.db =
229reserved.init =
230reserved.isNew =
231reserved.errors =
232reserved.schema =
233reserved.options =
234reserved.modelName =
235reserved.collection =
236reserved.toObject =
237reserved.emit =    // EventEmitter
238reserved._events = // EventEmitter
239reserved._pres = reserved._posts = 1 // hooks.js
240
241/**
242 * Gets/sets schema paths.
243 *
244 * Sets a path (if arity 2)
245 * Gets a path (if arity 1)
246 *
247 * ####Example
248 *
249 *     schema.path('name') // returns a SchemaType
250 *     schema.path('name', Number) // changes the schemaType of `name` to Number
251 *
252 * @param {String} path
253 * @param {Object} constructor
254 * @api public
255 */
256
257Schema.prototype.path = function (path, obj) {
258  if (obj == undefined) {
259    if (this.paths[path]) return this.paths[path];
260    if (this.subpaths[path]) return this.subpaths[path];
261
262    // subpaths?
263    return /\.\d+\.?.*$/.test(path)
264      ? getPositionalPath(this, path)
265      : undefined;
266  }
267
268  // some path names conflict with document methods
269  if (reserved[path]) {
270    throw new Error("`" + path + "` may not be used as a schema pathname");
271  }
272
273  // update the tree
274  var subpaths = path.split(/\./)
275    , last = subpaths.pop()
276    , branch = this.tree;
277
278  subpaths.forEach(function(sub, i) {
279    if (!branch[sub]) branch[sub] = {};
280    if ('object' != typeof branch[sub]) {
281      var msg = 'Cannot set nested path `' + path + '`. '
282              + 'Parent path `'
283              + subpaths.slice(0, i).concat([sub]).join('.')
284              + '` already set to type ' + branch[sub].name
285              + '.';
286      throw new Error(msg);
287    }
288    branch = branch[sub];
289  });
290
291  branch[last] = utils.clone(obj);
292
293  this.paths[path] = Schema.interpretAsType(path, obj);
294  return this;
295};
296
297/**
298 * Converts type arguments into Mongoose Types.
299 *
300 * @param {String} path
301 * @param {Object} obj constructor
302 * @api private
303 */
304
305Schema.interpretAsType = function (path, obj) {
306  if (obj.constructor && obj.constructor.name != 'Object')
307    obj = { type: obj };
308
309  // Get the type making sure to allow keys named "type"
310  // and default to mixed if not specified.
311  // { type: { type: String, default: 'freshcut' } }
312  var type = obj.type && !obj.type.type
313    ? obj.type
314    : {};
315
316  if ('Object' == type.constructor.name || 'mixed' == type) {
317    return new Types.Mixed(path, obj);
318  }
319
320  if (Array.isArray(type) || Array == type || 'array' == type) {
321    // if it was specified through { type } look for `cast`
322    var cast = (Array == type || 'array' == type)
323      ? obj.cast
324      : type[0];
325
326    if (cast instanceof Schema) {
327      return new Types.DocumentArray(path, cast, obj);
328    }
329
330    if ('string' == typeof cast) {
331      cast = Types[cast.charAt(0).toUpperCase() + cast.substring(1)];
332    } else if (cast && (!cast.type || cast.type.type)
333                    && 'Object' == cast.constructor.name
334                    && Object.keys(cast).length) {
335      return new Types.DocumentArray(path, new Schema(cast), obj);
336    }
337
338    return new Types.Array(path, cast || Types.Mixed, obj);
339  }
340
341  var name = 'string' == typeof type
342    ? type
343    : type.name;
344
345  if (name) {
346    name = name.charAt(0).toUpperCase() + name.substring(1);
347  }
348
349  if (undefined == Types[name]) {
350    throw new TypeError('Undefined type at `' + path +
351        '`\n  Did you try nesting Schemas? ' +
352        'You can only nest using refs or arrays.');
353  }
354
355  return new Types[name](path, obj);
356};
357
358/**
359 * Iterates the schemas paths similar to Array#forEach.
360 *
361 * The callback is passed the pathname and schemaType as arguments on each iteration.
362 *
363 * @param {Function} fn callback function
364 * @return {Schema} this
365 * @api public
366 */
367
368Schema.prototype.eachPath = function (fn) {
369  var keys = Object.keys(this.paths)
370    , len = keys.length;
371
372  for (var i = 0; i < len; ++i) {
373    fn(keys[i], this.paths[keys[i]]);
374  }
375
376  return this;
377};
378
379/**
380 * Returns an Array of path strings that are required by this schema.
381 *
382 * @api public
383 * @return {Array}
384 */
385
386Schema.prototype.requiredPaths = function requiredPaths () {
387  if (this._requiredpaths) return this._requiredpaths;
388
389  var paths = Object.keys(this.paths)
390    , i = paths.length
391    , ret = [];
392
393  while (i--) {
394    var path = paths[i];
395    if (this.paths[path].isRequired) ret.push(path);
396  }
397
398  return this._requiredpaths = ret;
399}
400
401/**
402 * Returns the pathType of `path` for this schema.
403 *
404 * Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.
405 *
406 * @param {String} path
407 * @return {String}
408 * @api public
409 */
410
411Schema.prototype.pathType = function (path) {
412  if (path in this.paths) return 'real';
413  if (path in this.virtuals) return 'virtual';
414  if (path in this.nested) return 'nested';
415  if (path in this.subpaths) return 'real';
416
417  if (/\.\d+\.|\.\d+$/.test(path) && getPositionalPath(this, path)) {
418    return 'real';
419  } else {
420    return 'adhocOrUndefined'
421  }
422};
423
424/*!
425 * ignore
426 */
427
428function getPositionalPath (self, path) {
429  var subpaths = path.split(/\.(\d+)\.|\.(\d+)$/).filter(Boolean);
430  if (subpaths.length < 2) {
431    return self.paths[subpaths[0]];
432  }
433
434  var val = self.path(subpaths[0]);
435  if (!val) return val;
436
437  var last = subpaths.length - 1
438    , subpath
439    , i = 1;
440
441  for (; i < subpaths.length; ++i) {
442    subpath = subpaths[i];
443
444    if (i === last && val && !val.schema && !/\D/.test(subpath)) {
445      if (val instanceof Types.Array) {
446        // StringSchema, NumberSchema, etc
447        val = val.caster;
448      } else {
449        val = undefined;
450      }
451      break;
452    }
453
454    // ignore if its just a position segment: path.0.subpath
455    if (!/\D/.test(subpath)) continue;
456
457    if (!(val && val.schema)) {
458      val = undefined;
459      break;
460    }
461
462    val = val.schema.path(subpath);
463  }
464
465  return self.subpaths[path] = val;
466}
467
468/**
469 * Adds a method call to the queue.
470 *
471 * @param {String} name name of the document method to call later
472 * @param {Array} args arguments to pass to the method
473 * @api private
474 */
475
476Schema.prototype.queue = function(name, args){
477  this.callQueue.push([name, args]);
478  return this;
479};
480
481/**
482 * Defines a pre hook for the document.
483 *
484 * ####Example
485 *
486 *     var toySchema = new Schema(..);
487 *
488 *     toySchema.pre('save', function (next) {
489 *       if (!this.created) this.created = new Date;
490 *       next();
491 *     })
492 *
493 *     toySchema.pre('validate', function (next) {
494 *       if (this.name != 'Woody') this.name = 'Woody';
495 *       next();
496 *     })
497 *
498 * @param {String} method
499 * @param {Function} callback
500 * @see hooks.js https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3
501 * @api public
502 */
503
504Schema.prototype.pre = function(){
505  return this.queue('pre', arguments);
506};
507
508/**
509 * Defines a post for the document
510 *
511 * Post hooks fire `on` the event emitted from document instances of Models compiled from this schema.
512 *
513 *     var schema = new Schema(..);
514 *     schema.post('save', function (doc) {
515 *       console.log('this fired after a document was saved');
516 *     });
517 *
518 *     var Model = mongoose.model('Model', schema);
519 *
520 *     var m = new Model(..);
521 *     m.save(function (err) {
522 *       console.log('this fires after the `post` hook');
523 *     });
524 *
525 * @param {String} method name of the method to hook
526 * @param {Function} fn callback
527 * @see hooks.js https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3
528 * @api public
529 */
530
531Schema.prototype.post = function(method, fn){
532  return this.queue('on', arguments);
533};
534
535/**
536 * Registers a plugin for this schema.
537 *
538 * @param {Function} plugin callback
539 * @param {Object} opts
540 * @see plugins
541 * @api public
542 */
543
544Schema.prototype.plugin = function (fn, opts) {
545  fn(this, opts);
546  return this;
547};
548
549/**
550 * Adds an instance method to documents constructed from Models compiled from this schema.
551 *
552 * ####Example
553 *
554 *     var schema = kittySchema = new Schema(..);
555 *
556 *     schema.method('meow', function () {
557 *       console.log('meeeeeoooooooooooow');
558 *     })
559 *
560 *     var Kitty = mongoose.model('Kitty', schema);
561 *
562 *     var fizz = new Kitty;
563 *     fizz.meow(); // meeeeeooooooooooooow
564 *
565 * If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.
566 *
567 *     schema.method({
568 *         purr: function () {}
569 *       , scratch: function () {}
570 *     });
571 *
572 *     // later
573 *     fizz.purr();
574 *     fizz.scratch();
575 *
576 * @param {String|Object} method name
577 * @param {Function} [fn]
578 * @api public
579 */
580
581Schema.prototype.method = function (name, fn) {
582  if ('string' != typeof name)
583    for (var i in name)
584      this.methods[i] = name[i];
585  else
586    this.methods[name] = fn;
587  return this;
588};
589
590/**
591 * Adds static "class" methods to Models compiled from this schema.
592 *
593 * ####Example
594 *
595 *     var schema = new Schema(..);
596 *     schema.static('findByName', function (name, callback) {
597 *       return this.find({ name: name }, callback);
598 *     });
599 *
600 *     var Drink = mongoose.model('Drink', schema);
601 *     Drink.findByName('sanpellegrino', function (err, drinks) {
602 *       //
603 *     });
604 *
605 * If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.
606 *
607 * @param {String} name
608 * @param {Function} fn
609 * @api public
610 */
611
612Schema.prototype.static = function(name, fn) {
613  if ('string' != typeof name)
614    for (var i in name)
615      this.statics[i] = name[i];
616  else
617    this.statics[name] = fn;
618  return this;
619};
620
621/**
622 * Defines an index (most likely compound) for this schema.
623 *
624 * ####Example
625 *
626 *     schema.index({ first: 1, last: -1 })
627 *
628 * @param {Object} fields
629 * @param {Object} [options]
630 * @api public
631 */
632
633Schema.prototype.index = function (fields, options) {
634  options || (options = {});
635
636  if (options.expires)
637    utils.expires(options);
638
639  this._indexes.push([fields, options]);
640  return this;
641};
642
643/**
644 * Sets/gets a schema option.
645 *
646 * @param {String} key option name
647 * @param {Object} [value] if not passed, the current option value is returned
648 * @api public
649 */
650
651Schema.prototype.set = function (key, value, _tags) {
652  if (1 === arguments.length) {
653    return this.options[key];
654  }
655
656  switch (key) {
657    case 'read':
658      this.options[key] = utils.readPref(value, _tags)
659      break;
660    case 'safe':
661      this.options[key] = false === value
662        ? { w: 0 }
663        : value
664      break;
665    default:
666      this.options[key] = value;
667  }
668
669  return this;
670}
671
672/**
673 * Gets a schema option.
674 *
675 * @param {String} key option name
676 * @api public
677 */
678
679Schema.prototype.get = function (key) {
680  return this.options[key];
681}
682
683/**
684 * The allowed index types
685 *
686 * @static indexTypes
687 * @receiver Schema
688 * @api public
689 */
690
691var indexTypes = '2d 2dsphere hashed text'.split(' ');
692
693Object.defineProperty(Schema, 'indexTypes', {
694    get: function () { return indexTypes }
695  , set: function () { throw new Error('Cannot overwrite Schema.indexTypes') }
696})
697
698/**
699 * Compiles indexes from fields and schema-level indexes
700 *
701 * @api public
702 */
703
704Schema.prototype.indexes = function () {
705  'use strict';
706
707  var indexes = []
708    , seenSchemas = []
709  collectIndexes(this);
710  return indexes;
711
712  function collectIndexes (schema, prefix) {
713    if (~seenSchemas.indexOf(schema)) return;
714    seenSchemas.push(schema);
715
716    prefix = prefix || '';
717
718    var key, path, index, field, isObject, options, type;
719    var keys = Object.keys(schema.paths);
720
721    for (var i = 0; i < keys.length; ++i) {
722      key = keys[i];
723      path = schema.paths[key];
724
725      if (path instanceof Types.DocumentArray) {
726        collectIndexes(path.schema, key + '.');
727      } else {
728        index = path._index;
729
730        if (false !== index && null != index) {
731          field = {};
732          isObject = utils.isObject(index);
733          options = isObject ? index : {};
734          type = 'string' == typeof index ? index :
735            isObject ? index.type :
736            false;
737
738          if (type && ~Schema.indexTypes.indexOf(type)) {
739            field[prefix + key] = type;
740          } else {
741            field[prefix + key] = 1;
742          }
743
744          delete options.type;
745          if (!('background' in options)) {
746            options.background = true;
747          }
748
749          indexes.push([field, options]);
750        }
751      }
752    }
753
754    if (prefix) {
755      fixSubIndexPaths(schema, prefix);
756    } else {
757      schema._indexes.forEach(function (index) {
758        if (!('background' in index[1])) index[1].background = true;
759      });
760      indexes = indexes.concat(schema._indexes);
761    }
762  }
763
764  /*!
765   * Checks for indexes added to subdocs using Schema.index().
766   * These indexes need their paths prefixed properly.
767   *
768   * schema._indexes = [ [indexObj, options], [indexObj, options] ..]
769   */
770
771  function fixSubIndexPaths (schema, prefix) {
772    var subindexes = schema._indexes
773      , len = subindexes.length
774      , indexObj
775      , newindex
776      , klen
777      , keys
778      , key
779      , i = 0
780      , j
781
782    for (i = 0; i < len; ++i) {
783      indexObj = subindexes[i][0];
784      keys = Object.keys(indexObj);
785      klen = keys.length;
786      newindex = {};
787
788      // use forward iteration, order matters
789      for (j = 0; j < klen; ++j) {
790        key = keys[j];
791        newindex[prefix + key] = indexObj[key];
792      }
793
794      indexes.push([newindex, subindexes[i][1]]);
795    }
796  }
797}
798
799/**
800 * Creates a virtual type with the given name.
801 *
802 * @param {String} name
803 * @param {Object} [options]
804 * @return {VirtualType}
805 */
806
807Schema.prototype.virtual = function (name, options) {
808  var virtuals = this.virtuals;
809  var parts = name.split('.');
810  return virtuals[name] = parts.reduce(function (mem, part, i) {
811    mem[part] || (mem[part] = (i === parts.length-1)
812                            ? new VirtualType(options, name)
813                            : {});
814    return mem[part];
815  }, this.tree);
816};
817
818/**
819 * Returns the virtual type with the given `name`.
820 *
821 * @param {String} name
822 * @return {VirtualType}
823 */
824
825Schema.prototype.virtualpath = function (name) {
826  return this.virtuals[name];
827};
828
829/**
830 * These still haven't been fixed. Once they're working we'll make them public again.
831 * @api private
832 */
833
834Schema.prototype.namedScope = function (name, fn) {
835  var namedScopes = this.namedScopes || (this.namedScopes = new NamedScope)
836    , newScope = Object.create(namedScopes)
837    , allScopes = namedScopes.scopesByName || (namedScopes.scopesByName = {});
838  allScopes[name] = newScope;
839  newScope.name = name;
840  newScope.block = fn;
841  newScope.query = new Query();
842  newScope.decorate(namedScopes, {
843    block0: function (block) {
844      return function () {
845        block.call(this.query);
846        return this;
847      };
848    },
849    blockN: function (block) {
850      return function () {
851        block.apply(this.query, arguments);
852        return this;
853      };
854    },
855    basic: function (query) {
856      return function () {
857        this.query.find(query);
858        return this;
859      };
860    }
861  });
862  return newScope;
863};
864
865/*!
866 * Module exports.
867 */
868
869module.exports = exports = Schema;
870
871// require down here because of reference issues
872
873/**
874 * The various built-in Mongoose Schema Types.
875 *
876 * ####Example:
877 *
878 *     var mongoose = require('mongoose');
879 *     var ObjectId = mongoose.Schema.Types.ObjectId;
880 *
881 * ####Types:
882 *
883 * - [String](#schema-string-js)
884 * - [Number](#schema-number-js)
885 * - [Boolean](#schema-boolean-js) | Bool
886 * - [Array](#schema-array-js)
887 * - [Buffer](#schema-buffer-js)
888 * - [Date](#schema-date-js)
889 * - [ObjectId](#schema-objectid-js) | Oid
890 * - [Mixed](#schema-mixed-js)
891 *
892 * Using this exposed access to the `Mixed` SchemaType, we can use them in our schema.
893 *
894 *     var Mixed = mongoose.Schema.Types.Mixed;
895 *     new mongoose.Schema({ _user: Mixed })
896 *
897 * @api public
898 */
899
900Schema.Types = require('./schema/index');
901
902/*!
903 * ignore
904 */
905
906Types = Schema.Types;
907NamedScope = require('./namedscope')
908Query = require('./query');
909var ObjectId = exports.ObjectId = Types.ObjectId;
910