You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

910 lines
21 KiB

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