Skip to content

Commit

Permalink
fix(document): avoid manually populating documents that are manually …
Browse files Browse the repository at this point in the history
…populated in another doc with different unpopulatedValue

Fix #11442
  • Loading branch information
vkarpov15 committed May 29, 2022
1 parent 996e48d commit 74a3b6b
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 1 deletion.
2 changes: 1 addition & 1 deletion lib/document.js
Original file line number Diff line number Diff line change
Expand Up @@ -1378,7 +1378,7 @@ Document.prototype.$set = function $set(path, val, type, options) {
})();

let didPopulate = false;
if (refMatches && val instanceof Document) {
if (refMatches && val instanceof Document && (!val.$__.wasPopulated || utils.deepEqual(val.$__.wasPopulated.value, val._id))) {
const unpopulatedValue = (schema && schema.$isSingleNested) ? schema.cast(val, this) : val._id;
this.$populated(path, unpopulatedValue, { [populateModelSymbol]: val.constructor });
val.$__.wasPopulated = { value: unpopulatedValue };
Expand Down
62 changes: 62 additions & 0 deletions test/document.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11392,4 +11392,66 @@ describe('document', function() {
doc = await Test.findById(doc);
assert.strictEqual(doc.list[0].toObject().quantity, null);
});

it('avoids manually populating document that is manually populated in another doc with different unpopulatedValue (gh-11442) (gh-11008)', async function() {
const BarSchema = new Schema({
name: String,
more: String
});
const Bar = db.model('Bar', BarSchema);

// Denormalised Bar schema with just the name, for use on the Foo model
const BarNameSchema = new Schema({
_id: {
type: Schema.Types.ObjectId,
ref: 'Bar'
},
name: String
});

// Foo model, which contains denormalized bar data (just the name)
const FooSchema = new Schema({
something: String,
other: Number,
bar: {
type: BarNameSchema,
ref: 'Bar'
}
});
const Foo = db.model('Foo', FooSchema);

const Baz = db.model('Baz', new Schema({ bar: { type: 'ObjectId', ref: 'Bar' } }));

const bar = await Bar.create({
name: 'I am another Bar',
more: 'With even more data'
});
const foo = await Foo.create({
something: 'I am another Foo',
other: 4
});
foo.bar = bar;
const baz = await Baz.create({});
baz.bar = bar;

assert.ok(foo.populated('bar'));
assert.ok(!baz.populated('bar'));

let res = foo.toObject({ depopulate: true });
assert.strictEqual(res.bar._id.toString(), bar._id.toString());
assert.strictEqual(res.bar.name, 'I am another Bar');

res = baz.toObject({ depopulate: true });
assert.strictEqual(res.bar.toString(), bar._id.toString());

const bar2 = await Bar.create({
name: 'test2'
});
baz.bar = bar2;
assert.ok(baz.populated('bar'));

const baz2 = await Baz.create({});
baz2.bar = bar2;
assert.ok(baz.populated('bar'));
});
});

0 comments on commit 74a3b6b

Please sign in to comment.