Skip to content

Commit

Permalink
fix(populate): avoid converting mixed paths into arrays if populating…
Browse files Browse the repository at this point in the history
… an object path under `Mixed`

Fix #8157
  • Loading branch information
vkarpov15 committed Sep 23, 2019
1 parent bdfce8f commit fb0bd0d
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 5 deletions.
10 changes: 7 additions & 3 deletions lib/helpers/populate/getModelsMapForPopulate.js
Expand Up @@ -166,7 +166,7 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
ret = localFieldPath.applyGetters(localFieldValue, hydratedDoc);
}
} else {
ret = convertTo_id(utils.getValue(localField, doc));
ret = convertTo_id(utils.getValue(localField, doc), schema);
}

const id = String(utils.getValue(foreignField, doc));
Expand Down Expand Up @@ -377,7 +377,7 @@ function handleRefFunction(ref, doc) {
* @return {Array|Document|Any}
*/

function convertTo_id(val) {
function convertTo_id(val, schema) {
if (val != null && val.$__ != null) return val._id;

if (Array.isArray(val)) {
Expand All @@ -395,7 +395,11 @@ function convertTo_id(val) {

// `populate('map')` may be an object if populating on a doc that hasn't
// been hydrated yet
if (val != null && val.constructor.name === 'Object') {
if (val != null &&
val.constructor.name === 'Object' &&
// The intent here is we should only flatten the object if we expect
// to get a Map in the end. Avoid doing this for mixed types.
(schema == null || schema[schemaMixedSymbol] == null)) {
const ret = [];
for (const key of Object.keys(val)) {
ret.push(val[key]);
Expand Down
8 changes: 6 additions & 2 deletions test/types.map.test.js
Expand Up @@ -371,7 +371,7 @@ describe('Map', function() {
});
});

it('avoid populating as map if populate on obj (gh-6460)', function() {
it('avoid populating as map if populate on obj (gh-6460) (gh-8157)', function() {
const UserSchema = new mongoose.Schema({
apiKeys: {}
});
Expand All @@ -387,8 +387,12 @@ describe('Map', function() {

const doc = yield User.create({ apiKeys: { github: key._id, twitter: key2._id } });

const populated = yield User.findById(doc).populate('apiKeys');
const populated = yield User.findById(doc).populate({
path: 'apiKeys',
skipInvalidIds: true
});
assert.ok(!(populated.apiKeys instanceof Map));
assert.ok(!Array.isArray(populated.apiKeys));
});
});

Expand Down

0 comments on commit fb0bd0d

Please sign in to comment.