diff --git a/lib/model.js b/lib/model.js index c2786efc4af..e33e8d54452 100644 --- a/lib/model.js +++ b/lib/model.js @@ -968,18 +968,16 @@ Model.init = function init(callback) { const Promise = PromiseProvider.get(); const autoIndex = this.schema.options.autoIndex; this.$init = new Promise((resolve, reject) => { - process.nextTick(() => { - if (autoIndex || (autoIndex == null && this.db.config.autoIndex)) { - this.ensureIndexes({ _automatic: true }, function(error) { - if (error) { - return reject(error); - } - resolve(this); - }); - } else { + if (autoIndex || (autoIndex == null && this.db.config.autoIndex)) { + this.ensureIndexes({ _automatic: true }, function(error) { + if (error) { + return reject(error); + } resolve(this); - } - }); + }); + } else { + resolve(this); + } }); if (callback) { @@ -1195,6 +1193,7 @@ Model.createIndexes = function createIndexes(options, callback) { function _ensureIndexes(model, options, callback) { const indexes = model.schema.indexes(); + options = options || {}; const done = function(err) { @@ -1205,6 +1204,15 @@ function _ensureIndexes(model, options, callback) { callback && callback(err); }; + for (const index of indexes) { + if (index[0]._id != null) { + const err = new Error('Cannot specify a custom index on `_id`, ' + + 'MongoDB does not allow overwriting the default `_id` index. See ' + + 'http://bit.ly/mongodb-id-index'); + return done(err); + } + } + if (!indexes.length) { utils.immediate(function() { done(); diff --git a/lib/schema.js b/lib/schema.js index 8365db3381d..5143b0904fe 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -4,16 +4,17 @@ * Module dependencies. */ -var readPref = require('./drivers').ReadPreference; -var EventEmitter = require('events').EventEmitter; -var VirtualType = require('./virtualtype'); -var utils = require('./utils'); -var MongooseTypes; -var Kareem = require('kareem'); -var SchemaType = require('./schematype'); -var get = require('lodash.get'); -var getIndexes = require('./helpers/schema/getIndexes'); -var mpath = require('mpath'); +const EventEmitter = require('events').EventEmitter; +const Kareem = require('kareem'); +const SchemaType = require('./schematype'); +const VirtualType = require('./virtualtype'); +const get = require('lodash.get'); +const getIndexes = require('./helpers/schema/getIndexes'); +const mpath = require('mpath'); +const readPref = require('./drivers').ReadPreference; +const utils = require('./utils'); + +let MongooseTypes; /** * Schema constructor. @@ -509,38 +510,36 @@ Schema.prototype.path = function(path, obj) { branch[last] = utils.clone(obj); this.paths[path] = Schema.interpretAsType(path, obj, this.options); + const schemaType = this.paths[path]; - if (this.paths[path].$isSchemaMap) { + if (schemaType.$isSchemaMap) { // Maps can have arbitrary keys, so `$*` is internal shorthand for "any key" // The '$' is to imply this path should never be stored in MongoDB so we // can easily build a regexp out of this path, and '*' to imply "any key." const mapPath = path + '.$*'; this.paths[path + '.$*'] = Schema.interpretAsType(mapPath, obj.of || { type: {} }, this.options); - this.paths[path].$__schemaType = this.paths[path + '.$*']; + schemaType.$__schemaType = this.paths[path + '.$*']; } - if (this.paths[path].$isSingleNested) { - for (let key in this.paths[path].schema.paths) { - this.singleNestedPaths[path + '.' + key] = - this.paths[path].schema.paths[key]; + if (schemaType.$isSingleNested) { + for (let key in schemaType.schema.paths) { + this.singleNestedPaths[path + '.' + key] = schemaType.schema.paths[key]; } - for (let key in this.paths[path].schema.singleNestedPaths) { + for (let key in schemaType.schema.singleNestedPaths) { this.singleNestedPaths[path + '.' + key] = - this.paths[path].schema.singleNestedPaths[key]; + schemaType.schema.singleNestedPaths[key]; } this.childSchemas.push({ - schema: this.paths[path].schema, - model: this.paths[path].caster + schema: schemaType.schema, + model: schemaType.caster }); - } else if (this.paths[path].$isMongooseDocumentArray) { + } else if (schemaType.$isMongooseDocumentArray) { this.childSchemas.push({ - schema: this.paths[path].schema, - model: this.paths[path].casterConstructor + schema: schemaType.schema, + model: schemaType.casterConstructor }); - } else if (this.paths[path].path === '_id' && this.paths[path].options && this.paths[path].options.unique) { - throw new Error('Cannot put unique index on _id'); } return this; diff --git a/test/model.indexes.test.js b/test/model.indexes.test.js index b5952ad5f9c..2989247474d 100644 --- a/test/model.indexes.test.js +++ b/test/model.indexes.test.js @@ -139,7 +139,7 @@ describe('model', function() { it('of multiple embedded documents with same schema', function(done) { var BlogPosts = new Schema({ - _id: {type: ObjectId, index: true}, + _id: {type: ObjectId, unique: true}, title: {type: String, index: true}, desc: String }); diff --git a/test/schema.test.js b/test/schema.test.js index 8029d1b5e97..af3f1d4b4b4 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -835,17 +835,6 @@ describe('schema', function() { done(); }); - it('errors if unique index on _id', function(done) { - try { - var schema = new Schema({ _id: { type: mongoose.Schema.Types.ObjectId, unique: true } }); - - schema.path('_id').index({ unique: true }); - done(new Error('Should not have reached this point!')); - } catch (error) { - assert.equal(error.message, 'Cannot put unique index on _id'); - done(); - } - }); it('with single nested doc (gh-6113)', function(done) { var pointSchema = new Schema({