Closed matanarbel closed 2 years ago
This looks like it might be a dupe of https://github.com/Automattic/mongoose/issues/11395? They seem similar at least.
const mongoose = require('mongoose');
const {Schema} = mongoose;
const testModel = new Schema({
fakeId: Number,
foo: {
bar: { type: Number }
}
});
const TestModel = mongoose.model('TestModel', testModel);
run().catch(err => console.log(err));
async function run() {
await mongoose.connect('mongodb://localhost:27017/test-mongoose', {});
await mongoose.connection.dropDatabase();
await TestModel.create({
fakeId: 1,
foo: {
bar: 2
}
});
const entry = await TestModel.findOne();
console.log(entry);
entry.foo = {bar: 10};
console.log(entry);
entry.foo = {bar: 10};
console.log(entry);
await entry.save();
console.log(entry);
const otherEntry = await TestModel.findOne();
otherEntry.foo.bar = 5;
console.log(otherEntry);
otherEntry.foo = otherEntry.foo;
console.log(otherEntry)
}
@sean-daley They do look similar but I think the key difference causing the problem is either how no entry is created or the way the schema is declared.
@sean-daley They do look similar but I think the key difference causing the problem is either how no entry is created or the way the schema is declared.
Cool. I'll definitely trust you guys when it comes to the final say on dupes like that ;)
const mongoose = require('mongoose'); const {Schema} = mongoose; const testModel = new Schema({ fakeId: Number, foo: { bar: { type: Number } } }); const TestModel = mongoose.model('TestModel', testModel); run().catch(err => console.log(err)); async function run() { await mongoose.connect('mongodb://localhost:27017/test-mongoose', {}); await mongoose.connection.dropDatabase(); await TestModel.create({ fakeId: 1, foo: { bar: 2 } }); const entry = await TestModel.findOne(); console.log(entry); entry.foo = {bar: 10}; console.log(entry); entry.foo = {bar: 10}; console.log(entry); await entry.save(); console.log(entry); const otherEntry = await TestModel.findOne(); otherEntry.foo.bar = 5; console.log(otherEntry); otherEntry.foo = otherEntry.foo; console.log(otherEntry) }
You did reproduce the issue, but in the first example, after the save, you checked the object in memory (which is updated). If you'd run findOne
after the save, you'd see that the value wasn't actually saved to the DB.
const mongoose = require('mongoose');
const {Schema} = mongoose;
const testModel = new Schema({
fakeId: Number,
foo: {
bar: { type: Number }
}
});
const TestModel = mongoose.model('TestModel', testModel);
run().catch(err => console.log(err));
async function run() {
await mongoose.connect('mongodb://localhost:27017/test-mongoose', {});
await mongoose.connection.dropDatabase();
await TestModel.create({
fakeId: 1,
foo: {
bar: 2
}
});
const entry = await TestModel.findOne();
console.log(entry);
entry.foo = {bar: 10};
console.log(entry);
entry.foo = {bar: 10};
console.log(entry);
await entry.save();
console.log('After save', entry);
const otherEntry = await TestModel.findOne();
console.log('new find operation', otherEntry);
otherEntry.foo.bar = 5;
console.log(otherEntry);
otherEntry.foo = otherEntry.foo;
console.log('No save', otherEntry)
}
I confirmed this was fixed in v6.2.4 with #11428.
Do you want to request a feature or report a bug? bug
What is the current behavior? When changing a nested object twice to the same value, the change is ignored (the field is marked as not modified).
If the current behavior is a bug, please provide the steps to reproduce. Schema:
Code segment:
What is the expected behavior? I expect
doc.foo.bar
to be set to10
.Some extra info: Running
doc.foo = { bar: 10 };
only once works. Manually runningdoc.markModified('foo');
after the 2nd update also works. After debugging mongoose code, I believe that the issue is in lib/document.js:1225:The first time I change
foo
,utils.deepEqual
compares{bar: 3}
to{bar: 10}
, making theif
expression returnfalse
, and thus markingfoo
as modified. The second time I changefoo
,utils.deepEqual
compares{bar: 10}
to{bar: 10}
, making theif
expression returntrue
, and thus unmarkingfoo
as modified.I'd suggest not unmarking already marked "Modified" fields, to avoid such cases, but since there's a code that explicitly unmarks modified - I guess there're other reasons why it's needed. Maybe a reference to the "original" document (as saved in the DB) should be kept, and the comparison should be against it (this "original" document should be updated only after saving the changes).
What are the versions of Node.js, Mongoose and MongoDB you are using? Note that "latest" is not a version. Node.js 16.13.0 Mongoose 6.2.3 MongoDB 3.6.6