Skip to content

Commit

Permalink
Merge pull request #14437 from Automattic/vkarpov15/gh-14420
Browse files Browse the repository at this point in the history
fix(model): improve update minimizing to only minimize top-level properties in the update
  • Loading branch information
vkarpov15 committed Mar 15, 2024
2 parents 5fca922 + ca623ef commit 5ea6e38
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 6 deletions.
22 changes: 16 additions & 6 deletions lib/model.js
Expand Up @@ -351,12 +351,22 @@ Model.prototype.$__handleSave = function(options, callback) {

const update = delta[1];
if (this.$__schema.options.minimize) {
minimize(update);
// minimize might leave us with an empty object, which would
// lead to MongoDB throwing a "Update document requires atomic operators" error
if (Object.keys(update).length === 0) {
handleEmptyUpdate.call(this);
return;
for (const updateOp of Object.values(update)) {
if (updateOp == null) {
continue;
}
for (const key of Object.keys(updateOp)) {
if (updateOp[key] == null || typeof updateOp[key] !== 'object') {
continue;
}
if (!utils.isPOJO(updateOp[key])) {
continue;
}
minimize(updateOp[key]);
if (Object.keys(updateOp[key]).length === 0) {
updateOp[key] = null;
}
}
}
}

Expand Down
45 changes: 45 additions & 0 deletions test/document.test.js
Expand Up @@ -13041,6 +13041,51 @@ describe('document', function() {
assert.ok(doc.docArr.toString().includes('child'), doc.docArr.toString());
assert.ok(doc.docArr.toString().includes('test child'), doc.docArr.toString());
});

it('minimizes when updating existing documents (gh-13782)', async function() {
const schema = new Schema({
metadata: {
type: {},
default: {},
required: true,
_id: false
}
}, { minimize: true });
const Model = db.model('Test', schema);
const m = new Model({ metadata: {} });
await m.save();

const x = await Model.findById(m._id).exec();
x.metadata = {};
await x.save();

const { metadata } = await Model.findById(m._id).orFail();
assert.strictEqual(metadata, null);
});

it('saves when setting subdocument to empty object (gh-14420) (gh-13782)', async function() {
const SubSchema = new mongoose.Schema({
name: { type: String },
age: Number
}, { _id: false });

const MainSchema = new mongoose.Schema({
sub: {
type: SubSchema
}
});

const MainModel = db.model('Test', MainSchema);

const doc = new MainModel({ sub: { name: 'Hello World', age: 42 } });
await doc.save();

doc.sub = {};
await doc.save();

const savedDoc = await MainModel.findById(doc.id).orFail();
assert.strictEqual(savedDoc.sub, null);
});
});

describe('Check if instance function that is supplied in schema option is availabe', function() {
Expand Down

0 comments on commit 5ea6e38

Please sign in to comment.