Skip to content

Commit

Permalink
Merge pull request #15155 from Automattic/vkarpov15/autocreate-syncin…
Browse files Browse the repository at this point in the history
…dexes

fix(model): skip createCollection() in syncIndexes() if autoCreate: false
  • Loading branch information
vkarpov15 authored Jan 4, 2025
2 parents 57237a9 + 4d4bd00 commit 911ba54
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 9 deletions.
20 changes: 11 additions & 9 deletions lib/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down
1 change: 1 addition & 0 deletions lib/schema/documentArray.js
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,7 @@ SchemaDocumentArray.prototype.clone = function() {
}
schematype.Constructor.discriminators = Object.assign({},
this.Constructor.discriminators);
schematype._appliedDiscriminators = this._appliedDiscriminators;
return schematype;
};

Expand Down
1 change: 1 addition & 0 deletions lib/schema/subdocument.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
52 changes: 52 additions & 0 deletions test/model.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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 },
Expand Down

0 comments on commit 911ba54

Please sign in to comment.