Skip to content

Commit 2d65e00

Browse files
authored
Merge pull request #14135 from Automattic/vkarpov15/gh-14073
Call transform object with single id instead of array when populating a justOne path under an array
2 parents 778d8de + 0282f50 commit 2d65e00

File tree

2 files changed

+63
-0
lines changed

2 files changed

+63
-0
lines changed

lib/helpers/populate/assignVals.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,10 @@ module.exports = function assignVals(o) {
3939
const options = o.options;
4040
const count = o.count && o.isVirtual;
4141
let i;
42+
let setValueIndex = 0;
4243

4344
function setValue(val) {
45+
++setValueIndex;
4446
if (count) {
4547
return val;
4648
}
@@ -80,11 +82,14 @@ module.exports = function assignVals(o) {
8082
return valueFilter(val[0], options, populateOptions, _allIds);
8183
} else if (o.justOne === false && !Array.isArray(val)) {
8284
return valueFilter([val], options, populateOptions, _allIds);
85+
} else if (o.justOne === true && !Array.isArray(val) && Array.isArray(_allIds)) {
86+
return valueFilter(val, options, populateOptions, val == null ? val : _allIds[setValueIndex - 1]);
8387
}
8488
return valueFilter(val, options, populateOptions, _allIds);
8589
}
8690

8791
for (i = 0; i < docs.length; ++i) {
92+
setValueIndex = 0;
8893
const _path = o.path.endsWith('.$*') ? o.path.slice(0, -3) : o.path;
8994
const existingVal = mpath.get(_path, docs[i], lookupLocalFields);
9095
if (existingVal == null && !getVirtual(o.originalModel.schema, _path)) {

test/model.populate.test.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10776,4 +10776,62 @@ describe('model: populate:', function() {
1077610776
new Date('2015-06-01').toString()
1077710777
);
1077810778
});
10779+
10780+
it('calls transform with single ObjectId when populating justOne path underneath array (gh-14073)', async function() {
10781+
const mySchema = mongoose.Schema({
10782+
name: { type: String },
10783+
items: [{
10784+
_id: false,
10785+
name: { type: String },
10786+
brand: { type: mongoose.Schema.Types.ObjectId, ref: 'Brand' }
10787+
}]
10788+
});
10789+
10790+
const brandSchema = mongoose.Schema({
10791+
name: 'String',
10792+
quantity: Number
10793+
});
10794+
10795+
const myModel = db.model('MyModel', mySchema);
10796+
const brandModel = db.model('Brand', brandSchema);
10797+
const { _id: id1 } = await brandModel.create({
10798+
name: 'test',
10799+
quantity: 1
10800+
});
10801+
const { _id: id2 } = await brandModel.create({
10802+
name: 'test1',
10803+
quantity: 1
10804+
});
10805+
const { _id: id3 } = await brandModel.create({
10806+
name: 'test2',
10807+
quantity: 2
10808+
});
10809+
const brands = await brandModel.find();
10810+
const test = new myModel({ name: 'Test Model' });
10811+
for (let i = 0; i < brands.length; i++) {
10812+
test.items.push({ name: `${i}`, brand: brands[i]._id });
10813+
}
10814+
10815+
const id4 = new mongoose.Types.ObjectId();
10816+
test.items.push({ name: '4', brand: id4 });
10817+
await test.save();
10818+
10819+
const ids = [];
10820+
await myModel
10821+
.findOne()
10822+
.populate([
10823+
{
10824+
path: 'items.brand',
10825+
transform: (doc, id) => {
10826+
ids.push(id);
10827+
return doc;
10828+
}
10829+
}
10830+
]);
10831+
assert.equal(ids.length, 4);
10832+
assert.deepStrictEqual(
10833+
ids.map(id => id?.toHexString()),
10834+
[id1.toString(), id2.toString(), id3.toString(), id4.toString()]
10835+
);
10836+
});
1077910837
});

0 commit comments

Comments
 (0)