Skip to content

Commit 45b20f0

Browse files
committed
feat(model): make syncIndexes() not call createIndex() on indexes that already exist
1 parent 39886fb commit 45b20f0

File tree

2 files changed

+33
-13
lines changed

2 files changed

+33
-13
lines changed

lib/model.js

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1256,7 +1256,7 @@ Model.syncIndexes = async function syncIndexes(options) {
12561256
}
12571257
}
12581258

1259-
const diffIndexesResult = await model.diffIndexes();
1259+
const diffIndexesResult = await model.diffIndexes({ indexOptionsToCreate: true });
12601260
const dropped = await model.cleanIndexes({ ...options, toDrop: diffIndexesResult.toDrop });
12611261
await model.createIndexes({ ...options, toCreate: diffIndexesResult.toCreate });
12621262

@@ -1361,13 +1361,14 @@ Model.listSearchIndexes = async function listSearchIndexes(options) {
13611361
*
13621362
* const { toDrop, toCreate } = await Model.diffIndexes();
13631363
* toDrop; // Array of strings containing names of indexes that `syncIndexes()` will drop
1364-
* toCreate; // Array of strings containing names of indexes that `syncIndexes()` will create
1364+
* toCreate; // Array of index specs containing the keys of indexes that `syncIndexes()` will create
13651365
*
13661366
* @param {Object} [options]
1367+
* @param {Boolean} [options.indexOptionsToCreate=false] If true, `toCreate` will include both the index spec and the index options, not just the index spec
13671368
* @return {Promise<Object>} contains the indexes that would be dropped in MongoDB and indexes that would be created in MongoDB as `{ toDrop: string[], toCreate: string[] }`.
13681369
*/
13691370

1370-
Model.diffIndexes = async function diffIndexes() {
1371+
Model.diffIndexes = async function diffIndexes(options) {
13711372
if (typeof arguments[0] === 'function' || typeof arguments[1] === 'function') {
13721373
throw new MongooseError('Model.syncIndexes() no longer accepts a callback');
13731374
}
@@ -1389,13 +1390,14 @@ Model.diffIndexes = async function diffIndexes() {
13891390
const schemaIndexes = getRelatedSchemaIndexes(model, schema.indexes());
13901391

13911392
const toDrop = getIndexesToDrop(schema, schemaIndexes, dbIndexes);
1392-
const toCreate = getIndexesToCreate(schema, schemaIndexes, dbIndexes, toDrop);
1393+
const toCreate = getIndexesToCreate(schema, schemaIndexes, dbIndexes, toDrop, options);
13931394

13941395
return { toDrop, toCreate };
13951396
};
13961397

1397-
function getIndexesToCreate(schema, schemaIndexes, dbIndexes, toDrop) {
1398+
function getIndexesToCreate(schema, schemaIndexes, dbIndexes, toDrop, options) {
13981399
const toCreate = [];
1400+
const indexOptionsToCreate = options?.indexOptionsToCreate ?? false;
13991401

14001402
for (const [schemaIndexKeysObject, schemaIndexOptions] of schemaIndexes) {
14011403
let found = false;
@@ -1416,7 +1418,11 @@ function getIndexesToCreate(schema, schemaIndexes, dbIndexes, toDrop) {
14161418
}
14171419

14181420
if (!found) {
1419-
toCreate.push(schemaIndexKeysObject);
1421+
if (indexOptionsToCreate) {
1422+
toCreate.push([schemaIndexKeysObject, schemaIndexOptions]);
1423+
} else {
1424+
toCreate.push(schemaIndexKeysObject);
1425+
}
14201426
}
14211427
}
14221428

@@ -1597,7 +1603,7 @@ Model.createIndexes = async function createIndexes(options) {
15971603
*/
15981604

15991605
function _ensureIndexes(model, options, callback) {
1600-
const indexes = model.schema.indexes();
1606+
const indexes = Array.isArray(options?.toCreate) ? options.toCreate : model.schema.indexes();
16011607
let indexError;
16021608

16031609
options = options || {};
@@ -1681,12 +1687,6 @@ function _ensureIndexes(model, options, callback) {
16811687
indexOptions.background = options.background;
16821688
}
16831689

1684-
if ('toCreate' in options) {
1685-
if (options.toCreate.length === 0) {
1686-
return done();
1687-
}
1688-
}
1689-
16901690
// Just in case `createIndex()` throws a sync error
16911691
let promise = null;
16921692
try {

test/model.test.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5056,6 +5056,26 @@ describe('Model', function() {
50565056
assert.strictEqual(indexes[1].background, false);
50575057
});
50585058

5059+
it('syncIndexes() does not call createIndex for indexes that already exist', async function() {
5060+
const opts = { autoIndex: false };
5061+
const schema = new Schema({ name: String }, opts);
5062+
schema.index({ name: 1 }, { background: true });
5063+
5064+
const M = db.model('Test', schema);
5065+
await M.syncIndexes();
5066+
5067+
const indexes = await M.listIndexes();
5068+
assert.deepEqual(indexes[1].key, { name: 1 });
5069+
5070+
sinon.stub(M.collection, 'createIndex').callsFake(() => Promise.resolve());
5071+
try {
5072+
await M.syncIndexes();
5073+
assert.equal(M.collection.createIndex.getCalls().length, 0);
5074+
} finally {
5075+
sinon.restore();
5076+
}
5077+
});
5078+
50595079
it('syncIndexes() supports hideIndexes (gh-14868)', async function() {
50605080
const opts = { autoIndex: false };
50615081
const schema = new Schema({ name: String }, opts);

0 commit comments

Comments
 (0)