Skip to content

Commit

Permalink
Merge pull request #13197 from Automattic/vkarpov15/gh-13189
Browse files Browse the repository at this point in the history
fix(schema): make creating top-level virtual underneath subdocument equivalent to creating virtual on the subdocument
  • Loading branch information
vkarpov15 committed Mar 23, 2023
2 parents 0ddb0f6 + 2739950 commit 228e853
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 6 deletions.
8 changes: 6 additions & 2 deletions lib/schema.js
Expand Up @@ -2217,11 +2217,15 @@ Schema.prototype.virtual = function(name, options) {
}

// Workaround for gh-8198: if virtual is under document array, make a fake
// virtual. See gh-8210
// virtual. See gh-8210, gh-13189
const parts = name.split('.');
let cur = parts[0];
for (let i = 0; i < parts.length - 1; ++i) {
if (this.paths[cur] != null && this.paths[cur].$isMongooseDocumentArray) {
if (this.paths[cur] == null) {
continue;
}

if (this.paths[cur].$isMongooseDocumentArray || this.paths[cur].$isSingleNested) {
const remnant = parts.slice(i + 1).join('.');
this.paths[cur].schema.virtual(remnant, options);
break;
Expand Down
27 changes: 23 additions & 4 deletions test/model.populate.test.js
Expand Up @@ -7934,31 +7934,50 @@ describe('model: populate:', function() {
assert.equal(res.nested.events[0].nestedLayer.users_$[0].name, 'test');
});

it('accessing populate virtual prop (gh-8198)', async function() {
it('accessing populate virtual prop (gh-13189) (gh-8198)', async function() {
const FooSchema = new Schema({
name: String,
children: [{
barId: { type: Schema.Types.ObjectId, ref: 'Test' },
quantity: Number
}]
}],
child: new Schema({
barId: {
type: 'ObjectId',
ref: 'Test'
}
})
});
FooSchema.virtual('children.bar', {
ref: 'Test',
localField: 'children.barId',
foreignField: '_id',
justOne: true
});
FooSchema.virtual('child.bars', {
ref: 'Test',
localField: 'child.barId',
foreignField: '_id'
});
const BarSchema = Schema({ name: String });
const Foo = db.model('Test1', FooSchema);
const Bar = db.model('Test', BarSchema);

const bar = await Bar.create({ name: 'bar' });
const foo = await Foo.create({
name: 'foo',
children: [{ barId: bar._id, quantity: 1 }]
children: [{ barId: bar._id, quantity: 1 }],
child: {
barId: bar._id
}
});
const foo2 = await Foo.findById(foo._id).populate('children.bar');
const foo2 = await Foo.findById(foo._id).populate('children.bar child.bars');
assert.equal(foo2.children[0].bar.name, 'bar');
assert.equal(foo2.child.bars[0].name, 'bar');

const asObject = foo2.toObject({ virtuals: true });
assert.equal(asObject.children[0].bar.name, 'bar');
assert.equal(asObject.child.bars[0].name, 'bar');
});

describe('gh-8247', function() {
Expand Down

0 comments on commit 228e853

Please sign in to comment.