From b8d354fa3d0a6795d08fa18b3da351fb989c204e Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 27 Dec 2024 15:45:03 -0500 Subject: [PATCH 1/2] fix(schema): make duplicate index error a warning for now to prevent blocking upgrading Fix #15109 Re: #15112 --- lib/schema.js | 2 +- test/schema.test.js | 55 ++++++++++++++++++++++++++++----------------- 2 files changed, 36 insertions(+), 21 deletions(-) diff --git a/lib/schema.js b/lib/schema.js index ddde465929..9f27e2ce23 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -2148,7 +2148,7 @@ Schema.prototype.index = function(fields, options) { for (const existingIndex of this.indexes()) { if (options.name == null && existingIndex[1].name == null && isIndexSpecEqual(existingIndex[0], fields)) { - throw new MongooseError(`Schema already has an index on ${JSON.stringify(fields)}`); + utils.warn(`Duplicate schema index on ${JSON.stringify(fields)} found. This is often due to declaring an index using both "index: true" and "schema.index()". Please remove the duplicate index definition.`); } } diff --git a/test/schema.test.js b/test/schema.test.js index e7c8a720cb..a5ad43360e 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -19,6 +19,7 @@ const DocumentObjectId = mongoose.Types.ObjectId; const vm = require('vm'); const idGetter = require('../lib/helpers/schema/idGetter'); const applyPlugins = require('../lib/helpers/schema/applyPlugins'); +const utils = require('../lib/utils'); /** * Test Document constructor. @@ -3279,29 +3280,43 @@ describe('schema', function() { assert.equal(subdoc.getAnswer(), 42); }); it('throws "already has an index" error if duplicate index definition (gh-15056)', function() { - const ObjectKeySchema = new mongoose.Schema({ - key: { - type: String, - required: true, - unique: true - }, - type: { - type: String, - required: false - } - }); + sinon.stub(utils, 'warn').callsFake(() => {}); + try { + const ObjectKeySchema = new mongoose.Schema({ + key: { + type: String, + required: true, + unique: true + }, + type: { + type: String, + required: false + } + }); - assert.throws(() => { ObjectKeySchema.index({ key: 1 }); - }, /MongooseError.*already has an index/); + assert.equal(utils.warn.getCalls().length, 1); + let [message] = utils.warn.getCalls()[0].args; + assert.equal( + message, + 'Duplicate schema index on {"key":1} found. This is often due to declaring an index using both "index: true" and "schema.index()". Please remove the duplicate index definition.' + ); - ObjectKeySchema.index({ key: 1, type: 1 }); - assert.throws(() => { ObjectKeySchema.index({ key: 1, type: 1 }); - }, /MongooseError.*already has an index/); - - ObjectKeySchema.index({ type: 1, key: 1 }); - ObjectKeySchema.index({ key: 1, type: -1 }); - ObjectKeySchema.index({ key: 1, type: 1 }, { unique: true, name: 'special index' }); + assert.equal(utils.warn.getCalls().length, 1); + ObjectKeySchema.index({ key: 1, type: 1 }); + assert.equal(utils.warn.getCalls().length, 2); + [message] = utils.warn.getCalls()[1].args; + assert.equal( + message, + 'Duplicate schema index on {"key":1,"type":1} found. This is often due to declaring an index using both "index: true" and "schema.index()". Please remove the duplicate index definition.' + ); + + ObjectKeySchema.index({ type: 1, key: 1 }); + ObjectKeySchema.index({ key: 1, type: -1 }); + ObjectKeySchema.index({ key: 1, type: 1 }, { unique: true, name: 'special index' }); + } finally { + sinon.restore(); + } }); }); From a5e4e61f76b9c90ac3ac005fb55f5e944e1ed94d Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 30 Dec 2024 15:08:04 -0500 Subject: [PATCH 2/2] test: add missing assertion to assert no further warnings --- test/schema.test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/schema.test.js b/test/schema.test.js index a5ad43360e..b8f4daf21a 100644 --- a/test/schema.test.js +++ b/test/schema.test.js @@ -3315,6 +3315,7 @@ describe('schema', function() { ObjectKeySchema.index({ type: 1, key: 1 }); ObjectKeySchema.index({ key: 1, type: -1 }); ObjectKeySchema.index({ key: 1, type: 1 }, { unique: true, name: 'special index' }); + assert.equal(utils.warn.getCalls().length, 2); } finally { sinon.restore(); }