From 77b9d99ec5f4d6562fbb61091e375d07100fef05 Mon Sep 17 00:00:00 2001 From: "richard.deavila" Date: Mon, 6 Mar 2023 09:19:30 -0800 Subject: [PATCH 1/3] Updated the isIndexEqual function to take into account non-text indexes when checking compound indexes that include both text and non-text indexes --- lib/helpers/indexes/isIndexEqual.js | 12 ++++-- test/model.indexes.test.js | 66 +++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 4 deletions(-) diff --git a/lib/helpers/indexes/isIndexEqual.js b/lib/helpers/indexes/isIndexEqual.js index d59d73438fc..eb0553d5794 100644 --- a/lib/helpers/indexes/isIndexEqual.js +++ b/lib/helpers/indexes/isIndexEqual.js @@ -28,15 +28,19 @@ module.exports = function isIndexEqual(key, options, dbIndex) { // textIndexVersion: 3 // } if (dbIndex.textIndexVersion != null) { - const weights = dbIndex.weights; - if (Object.keys(weights).length !== Object.keys(key).length) { + // If a compound index involves both text and non-text indexes, we want to extract both (gh-13136) + const weightsAndKeys = Object.assign({}, dbIndex.weights); + Object.keys(dbIndex.key) + .filter(function(key) { return !(key.startsWith('_fts'));}) + .forEach(function(key) { weightsAndKeys[key] = dbIndex.key[key];}); + if (Object.keys(weightsAndKeys).length !== Object.keys(key).length) { return false; } - for (const prop of Object.keys(weights)) { + for (const prop of Object.keys(weightsAndKeys)) { if (!(prop in key)) { return false; } - const weight = weights[prop]; + const weight = weightsAndKeys[prop]; if (weight !== get(options, 'weights.' + prop) && !(weight === 1 && get(options, 'weights.' + prop) == null)) { return false; } diff --git a/test/model.indexes.test.js b/test/model.indexes.test.js index 41ba6d97e23..b43dde62935 100644 --- a/test/model.indexes.test.js +++ b/test/model.indexes.test.js @@ -650,6 +650,72 @@ describe('model', function() { }); }); + it('should not re-create a compound text index that involves non-text indexes, using syncIndexes (gh-13136)', function(done) { + const Test = new Schema({ + title: { + type: String + }, + description: { + type: String + }, + age: { + type: Number + } + }, { + autoIndex: false + }); + + Test.index({ + title: 'text', + description: 'text', + age: 1 + }); + + const TestModel = db.model('Test', Test); + TestModel.syncIndexes().then((results1) => { + assert.strictEqual(results1, []); + // second call to syncIndexes should return an empty array, representing 0 deleted indexes + TestModel.syncIndexes().then((results2) => { + assert.strictEqual(results2, []); + done(); + }); + }); + }); + + it('should not find a diff when calling diffIndexes after syncIndexes involving a text and non-text compound index (gh-13136)', function(done) { + const Test = new Schema({ + title: { + type: String + }, + description: { + type: String + }, + age: { + type: Number + } + }, { + autoIndex: false + }); + + Test.index({ + title: 'text', + description: 'text', + age: 1 + }); + + const TestModel = db.model('Test', Test); + + TestModel.diffIndexes().then((diff) => { + assert.deepEqual(diff, { toCreate: [{ age: 1, title: 'text', description: 'text' }], toDrop: [] }); + TestModel.syncIndexes().then(() => { + TestModel.diffIndexes().then((diff2) => { + assert.deepEqual(diff2, { toCreate: [], toDrop: [] }); + done(); + }); + }); + }); + }); + it('cleanIndexes (gh-6676)', function() { return co(function*() { let M = db.model('Test', new Schema({ From 7364264c483d78f92444d2f56975e2d5ab03b78f Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 13 Mar 2023 11:28:16 -0400 Subject: [PATCH 2/3] Update model.indexes.test.js --- test/model.indexes.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/model.indexes.test.js b/test/model.indexes.test.js index b43dde62935..67eb116b9a5 100644 --- a/test/model.indexes.test.js +++ b/test/model.indexes.test.js @@ -676,7 +676,7 @@ describe('model', function() { assert.strictEqual(results1, []); // second call to syncIndexes should return an empty array, representing 0 deleted indexes TestModel.syncIndexes().then((results2) => { - assert.strictEqual(results2, []); + assert.deepEqual(results2, []); done(); }); }); From c8191dac3df40b97e34dc75f70410641136eafcc Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 13 Mar 2023 11:49:11 -0400 Subject: [PATCH 3/3] Update model.indexes.test.js --- test/model.indexes.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/model.indexes.test.js b/test/model.indexes.test.js index 67eb116b9a5..e785a3f6015 100644 --- a/test/model.indexes.test.js +++ b/test/model.indexes.test.js @@ -673,7 +673,7 @@ describe('model', function() { const TestModel = db.model('Test', Test); TestModel.syncIndexes().then((results1) => { - assert.strictEqual(results1, []); + assert.deepEqual(results1, []); // second call to syncIndexes should return an empty array, representing 0 deleted indexes TestModel.syncIndexes().then((results2) => { assert.deepEqual(results2, []);