Skip to content

Commit

Permalink
fix(populate): mostly working transform option for virtual populate…
Browse files Browse the repository at this point in the history
… re: #3775
  • Loading branch information
vkarpov15 committed Feb 25, 2021
1 parent 78efd9f commit e5e2937
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 4 deletions.
11 changes: 7 additions & 4 deletions lib/helpers/populate/assignVals.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ module.exports = function assignVals(o) {

// replace the original ids in our intermediate _ids structure
// with the documents found by query
o.allIds = [].concat(o.allIds);
assignRawDocsToIdStructure(o.rawIds, o.rawDocs, o.rawOrder, populateOptions);

// now update the original documents being populated using the
Expand All @@ -44,6 +45,8 @@ module.exports = function assignVals(o) {
return val.val;
}

const _allIds = o.allIds[i];

if (o.justOne === true && Array.isArray(val)) {
// Might be an embedded discriminator (re: gh-9244) with multiple models, so make sure to pick the right
// model before assigning.
Expand All @@ -63,11 +66,11 @@ module.exports = function assignVals(o) {
val[i] = ret[i];
}

return valueFilter(val[0], options, populateOptions, o.allIds[i]);
return valueFilter(val[0], options, populateOptions, _allIds);
} else if (o.justOne === false && !Array.isArray(val)) {
return valueFilter([val], options, populateOptions, o.allIds[i]);
return valueFilter([val], options, populateOptions, _allIds);
}
return valueFilter(val, options, populateOptions, o.allIds[i]);
return valueFilter(val, options, populateOptions, _allIds);
}

for (i = 0; i < docs.length; ++i) {
Expand Down Expand Up @@ -209,7 +212,7 @@ function valueFilter(val, assignmentOpts, populateOptions, allIds) {
if (!isPopulatedObject(subdoc) && (!populateOptions.retainNullValues || subdoc != null) && !userSpecifiedTransform) {
continue;
} else if (userSpecifiedTransform) {
subdoc = transform(isPopulatedObject(subdoc) ? subdoc : null, allIds[i]);
subdoc = transform(isPopulatedObject(subdoc) ? subdoc : null, allIds);
}
maybeRemoveId(subdoc, assignmentOpts);
ret.push(subdoc);
Expand Down
84 changes: 84 additions & 0 deletions test/model.populate.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10078,4 +10078,88 @@ describe('model: populate:', function() {
assert.equal(called[0].id.toHexString(), newId.toHexString());
});
});

it('transform with virtual populate, justOne = true (gh-3375)', function() {
const parentSchema = new Schema({
name: String
});
parentSchema.virtual('child', {
ref: 'Child',
localField: '_id',
foreignField: 'parentId',
justOne: true
});
const Parent = db.model('Parent', parentSchema);

const Child = db.model('Child', Schema({ name: String, parentId: 'ObjectId' }));

return co(function*() {
let p = yield Parent.create({ name: 'Anakin' });
const child = yield Child.create({ name: 'Luke', parentId: p._id });

let called = [];

p = yield Parent.findById(p).populate({
path: 'child',
transform: function(doc, id) {
called.push({
doc: doc,
id: id
});

return id;
}
});

assert.equal(called.length, 1);
assert.strictEqual(called[0].doc.parentId.toHexString(), p._id.toHexString());
assert.equal(called[0].id.toHexString(), p._id.toHexString());
});
});

it('transform with virtual populate, justOne = false (gh-3375) XYZ', function() {
const parentSchema = new Schema({
name: String
});
parentSchema.virtual('children', {
ref: 'Child',
localField: '_id',
foreignField: 'parentId',
justOne: false
});
const Parent = db.model('Parent', parentSchema);

const Child = db.model('Child', Schema({ name: String, parentId: 'ObjectId' }));

return co(function*() {
let p = yield Parent.create({ name: 'Anakin' });
const children = yield Child.create([
{ name: 'Luke', parentId: p._id },
{ name: 'Leia', parentId: p._id }
]);

let called = [];

p = yield Parent.findById(p).populate({
path: 'children',
transform: function(doc, id) {
called.push({
doc: doc,
id: id
});

return id;
}
});

assert.equal(called.length, 2);
assert.deepEqual(called.map(c => c.doc.name).sort(), ['Leia', 'Luke']);

assert.strictEqual(called[0].doc.parentId.toHexString(), p._id.toHexString());
assert.equal(called[0].id.toHexString(), p._id.toHexString());

assert.strictEqual(called[1].doc.parentId.toHexString(), p._id.toHexString());
assert.equal(called[1].id.toHexString(), p._id.toHexString());
});
});
});

0 comments on commit e5e2937

Please sign in to comment.