From ba9d74b2656af02a684dc31c72f846d333606bb2 Mon Sep 17 00:00:00 2001 From: Daniel Diaz <39510674+IslandRhythms@users.noreply.github.com> Date: Wed, 19 Apr 2023 17:37:05 -0400 Subject: [PATCH 1/2] use `collection.findOne()` instead of `exists` Handles case where `save()` is called on a document with no changes. This prevents the `findOne` hook from running --- lib/model.js | 3 +-- test/model.test.js | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/model.js b/lib/model.js index 9d8f690fe1b..84eb3c7e937 100644 --- a/lib/model.js +++ b/lib/model.js @@ -324,7 +324,6 @@ Model.prototype.$__handleSave = function(options, callback) { // Make sure we don't treat it as a new object on error, // since it already exists this.$__.inserting = false; - const delta = this.$__delta(); if (delta) { if (delta instanceof MongooseError) { @@ -361,7 +360,7 @@ Model.prototype.$__handleSave = function(options, callback) { where[key] = val; } } - this.constructor.exists(where, optionsWithCustomValues) + this.constructor.collection.findOne(where, optionsWithCustomValues) .then(documentExists => { const matchedCount = !documentExists ? 0 : 1; callback(null, { $where: where, matchedCount }); diff --git a/test/model.test.js b/test/model.test.js index bd7e8f86dde..de81227bf67 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -6885,6 +6885,25 @@ describe('Model', function() { assert.equal(TestModel.staticFn(), 'Returned from staticFn'); }); }); + + describe('Bypass middleware', function() { + it('should bypass middleware if save is called on a document with no changes gh-13250', async function() { + const testSchema = new Schema({ + name: String + }); + let bypass = true; + testSchema.pre('findOne', function(next) { + bypass = false; + next(); + }); + const Test = db.model('gh13250', testSchema); + const doc = await Test.create({ + name: 'Test Testerson' + }); + await doc.save(); + assert(bypass); + }); + }); }); From 108215b1c4e6f77bdcf8c1452e8cce3d63652ec9 Mon Sep 17 00:00:00 2001 From: Daniel Diaz <39510674+IslandRhythms@users.noreply.github.com> Date: Wed, 19 Apr 2023 17:37:46 -0400 Subject: [PATCH 2/2] remove conflicting test since we are implementing a fix that removes exist, this test serves no purpose --- test/document.test.js | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/test/document.test.js b/test/document.test.js index 76029b27d31..d7bac350061 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -1968,25 +1968,6 @@ describe('document', function() { assert.equal(threw, true); }); - - it('passes save custom options to Model.exists(...) when no changes are present (gh-8739)', async function() { - const personSchema = new Schema({ name: String }); - - let optionInMiddleware; - - personSchema.pre('findOne', function(next) { - optionInMiddleware = this.getOptions().customOption; - - return next(); - }); - - const Person = db.model('Person', personSchema); - - const person = await Person.create({ name: 'Hafez' }); - await person.save({ customOption: 'test' }); - - assert.equal(optionInMiddleware, 'test'); - }); }); it('properly calls queue functions (gh-2856)', function() {