diff --git a/lib/model.js b/lib/model.js index edfe7c5e61..e400536eb9 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1302,19 +1302,21 @@ Model.syncIndexes = async function syncIndexes(options) { throw new MongooseError('Model.syncIndexes() no longer accepts a callback'); } - const model = this; + const autoCreate = options?.autoCreate ?? this.schema.options?.autoCreate ?? this.db.config.autoCreate ?? true; - try { - await model.createCollection(); - } catch (err) { - if (err != null && (err.name !== 'MongoServerError' || err.code !== 48)) { - throw err; + if (autoCreate) { + try { + await this.createCollection(); + } catch (err) { + if (err != null && (err.name !== 'MongoServerError' || err.code !== 48)) { + throw err; + } } } - const diffIndexesResult = await model.diffIndexes(); - const dropped = await model.cleanIndexes({ ...options, toDrop: diffIndexesResult.toDrop }); - await model.createIndexes({ ...options, toCreate: diffIndexesResult.toCreate }); + const diffIndexesResult = await this.diffIndexes(); + const dropped = await this.cleanIndexes({ ...options, toDrop: diffIndexesResult.toDrop }); + await this.createIndexes({ ...options, toCreate: diffIndexesResult.toCreate }); return dropped; }; diff --git a/lib/schema/documentArray.js b/lib/schema/documentArray.js index 9a7a5d3181..413dc4a8fb 100644 --- a/lib/schema/documentArray.js +++ b/lib/schema/documentArray.js @@ -522,6 +522,7 @@ SchemaDocumentArray.prototype.clone = function() { } schematype.Constructor.discriminators = Object.assign({}, this.Constructor.discriminators); + schematype._appliedDiscriminators = this._appliedDiscriminators; return schematype; }; diff --git a/lib/schema/subdocument.js b/lib/schema/subdocument.js index 5116ed0cfa..9a77d82c87 100644 --- a/lib/schema/subdocument.js +++ b/lib/schema/subdocument.js @@ -393,5 +393,6 @@ SchemaSubdocument.prototype.clone = function() { schematype.requiredValidator = this.requiredValidator; } schematype.caster.discriminators = Object.assign({}, this.caster.discriminators); + schematype._appliedDiscriminators = this._appliedDiscriminators; return schematype; }; diff --git a/test/model.test.js b/test/model.test.js index 098624e2e9..e7bd52447a 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -4885,6 +4885,28 @@ describe('Model', function() { assert.deepStrictEqual(indexes.map(index => index.name), ['_id_', 'name_1']); }); + it('avoids creating collection if autoCreate: false', async() => { + const collectionName = generateRandomCollectionName(); + const userSchema = new Schema( + { name: { type: String, index: true } }, + { autoIndex: false, autoCreate: false, collation: { locale: 'en_US', strength: 2 } } + ); + const User = db.model('User', userSchema, collectionName); + + // Act + await User.syncIndexes(); + + // Assert + const indexes = await User.listIndexes(); + assert.deepStrictEqual(indexes.map(index => index.name), ['_id_', 'name_1']); + + const collections = await User.db.listCollections(); + const collection = collections.find(c => c.name === collectionName); + assert.ok(collection); + // Collation was not applied because autoCreate was false, so Mongoose did not send `createCollection()` + assert.ok(!collection.options.collation); + }); + it('drops indexes that are not present in schema', async() => { // Arrange const collectionName = generateRandomCollectionName(); @@ -8004,6 +8026,36 @@ describe('Model', function() { assert.equal(doc.items[0].prop, 42); }); + it('does not throw with multiple self-referencing discriminator schemas applied to schema (gh-15120)', async function() { + const baseSchema = new Schema({ + type: { type: Number, required: true } + }, { discriminatorKey: 'type' }); + + const selfRefSchema = new Schema({ + self: { type: [baseSchema] } + }); + + const anotherSelfRefSchema = new Schema({ + self2: { type: [baseSchema] } + }); + + baseSchema.discriminator(5, selfRefSchema); + baseSchema.discriminator(6, anotherSelfRefSchema); + const Test = db.model('Test', baseSchema); + + const doc = await Test.create({ + type: 5, + self: { + type: 6, + self2: null + } + }); + assert.strictEqual(doc.type, 5); + assert.equal(doc.self.length, 1); + assert.strictEqual(doc.self[0].type, 6); + assert.strictEqual(doc.self[0].self2, null); + }); + it('inserts versionKey even if schema has `toObject.versionKey` set to false (gh-14344)', async function() { const schema = new mongoose.Schema( { name: String },