Skip to content

Commit

Permalink
Merge pull request #15114 from Automattic/vkarpov15/gh-15108
Browse files Browse the repository at this point in the history
fix(map): clean modified subpaths when overwriting values in map of subdocs
  • Loading branch information
vkarpov15 authored Dec 18, 2024
2 parents 0fd43c4 + 66a8b87 commit c393154
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 1 deletion.
9 changes: 8 additions & 1 deletion lib/types/map.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const handleSpreadDoc = require('../helpers/document/handleSpreadDoc');
const util = require('util');
const specialProperties = require('../helpers/specialProperties');
const isBsonType = require('../helpers/isBsonType');
const cleanModifiedSubpaths = require('../helpers/document/cleanModifiedSubpaths');

const populateModelSymbol = require('../helpers/symbols').populateModelSymbol;

Expand Down Expand Up @@ -157,7 +158,13 @@ class MongooseMap extends Map {
super.set(key, value);

if (parent != null && parent.$__ != null && !deepEqual(value, priorVal)) {
parent.markModified(fullPath.call(this));
const path = fullPath.call(this);
parent.markModified(path);
// If overwriting the full document array or subdoc, make sure to clean up any paths that were modified
// before re: #15108
if (this.$__schemaType.$isMongooseDocumentArray || this.$__schemaType.$isSingleNested) {
cleanModifiedSubpaths(parent, path);
}
}

// Delay calculating full path unless absolutely necessary, because string
Expand Down
47 changes: 47 additions & 0 deletions test/types.map.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1103,4 +1103,51 @@ describe('Map', function() {
assert.equal(doc.addresses.get('home').length, 1);
assert.equal(doc.addresses.get('home')[0].city, 'London');
});

it('clears nested changes in subdocs (gh-15108)', async function() {
const CarSchema = new mongoose.Schema({
owners: {
type: Map,
of: {
name: String
}
}
});
const CarModel = db.model('Car', CarSchema);
const car = await CarModel.create({
owners: { abc: { name: 'John' } }
});

car.owners.get('abc').name = undefined;
car.owners.delete('abc');
assert.deepStrictEqual(car.getChanges(), { $unset: { 'owners.abc': 1 } });
await car.save();

const doc = await CarModel.findById(car._id);
assert.strictEqual(doc.owners.get('abc'), undefined);
});

it('clears nested changes in doc arrays (gh-15108)', async function() {
const CarSchema = new mongoose.Schema({
owners: {
type: Map,
of: [{
_id: false,
name: String
}]
}
});
const CarModel = db.model('Car', CarSchema);
const car = await CarModel.create({
owners: { abc: [{ name: 'John' }] }
});

car.owners.get('abc')[0].name = undefined;
car.owners.set('abc', [{ name: 'Bill' }]);
assert.deepStrictEqual(car.getChanges(), { $inc: { __v: 1 }, $set: { 'owners.abc': [{ name: 'Bill' }] } });
await car.save();

const doc = await CarModel.findById(car._id);
assert.deepStrictEqual(doc.owners.get('abc').toObject(), [{ name: 'Bill' }]);
});
});

0 comments on commit c393154

Please sign in to comment.