Skip to content

Commit

Permalink
fix(populate): handle deselected foreign field with `perDocumentLimit…
Browse files Browse the repository at this point in the history
…` and multiple documents

Fix #9175
  • Loading branch information
vkarpov15 committed Jun 30, 2020
1 parent 1c8f565 commit 1a843e3
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 15 deletions.
31 changes: 31 additions & 0 deletions lib/helpers/populate/removeDeselectedForeignField.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
'use strict';

const get = require('../get');
const mpath = require('mpath');
const parseProjection = require('../projection/parseProjection');

/*!
* ignore
*/

module.exports = function removeDeselectedForeignField(foreignFields, options, docs) {
const projection = parseProjection(get(options, 'select', null), true) ||
parseProjection(get(options, 'options.select', null), true);

if (projection == null) {
return;
}
for (const foreignField of foreignFields) {
if (!projection.hasOwnProperty('-' + foreignField)) {
continue;
}

for (const val of docs) {
if (val.$__ != null) {
mpath.unset(foreignField, val._doc);
} else {
mpath.unset(foreignField, val);
}
}
}
}
21 changes: 6 additions & 15 deletions lib/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,19 @@ const castBulkWrite = require('./helpers/model/castBulkWrite');
const getDefaultBulkwriteResult = require('./helpers/getDefaultBulkwriteResult');
const discriminator = require('./helpers/model/discriminator');
const each = require('./helpers/each');
const get = require('./helpers/get');
const getDiscriminatorByValue = require('./helpers/discriminator/getDiscriminatorByValue');
const getModelsMapForPopulate = require('./helpers/populate/getModelsMapForPopulate');
const immediate = require('./helpers/immediate');
const internalToObjectOptions = require('./options').internalToObjectOptions;
const isDefaultIdIndex = require('./helpers/indexes/isDefaultIdIndex');
const isIndexEqual = require('./helpers/indexes/isIndexEqual');
const isPathSelectedInclusive = require('./helpers/projection/isPathSelectedInclusive');
const get = require('./helpers/get');
const leanPopulateMap = require('./helpers/populate/leanPopulateMap');
const modifiedPaths = require('./helpers/update/modifiedPaths');
const mpath = require('mpath');
const parallelLimit = require('./helpers/parallelLimit');
const promiseOrCallback = require('./helpers/promiseOrCallback');
const parseProjection = require('./helpers/projection/parseProjection');
const removeDeselectedForeignField = require('./helpers/populate/removeDeselectedForeignField');
const util = require('util');
const utils = require('./utils');

Expand Down Expand Up @@ -4465,6 +4464,10 @@ function populate(model, docs, options, callback) {
const assignmentOpts = arr[3];
_assign(model, vals, mod, assignmentOpts);
}

for (const arr of params) {
removeDeselectedForeignField(arr[0].foreignField, arr[0].options, vals);
}
callback();
}
}
Expand Down Expand Up @@ -4531,8 +4534,6 @@ function _assign(model, vals, mod, assignmentOpts) {
const justOne = mod.justOne;
let _val;
const lean = get(options, 'options.lean', false);
const projection = parseProjection(get(options, 'select', null), true) ||
parseProjection(get(options, 'options.select', null), true);
const len = vals.length;
const rawOrder = {};
const rawDocs = {};
Expand Down Expand Up @@ -4602,16 +4603,6 @@ function _assign(model, vals, mod, assignmentOpts) {
} else {
val.$__.wasPopulated = true;
}

// gh-8460: if user used `-foreignField`, assume this means they
// want the foreign field unset even if it isn't excluded in the query.
if (projection != null && projection.hasOwnProperty('-' + foreignField)) {
if (val.$__ != null) {
val.set(foreignField, void 0);
} else {
mpath.unset(foreignField, val);
}
}
}
}

Expand Down

0 comments on commit 1a843e3

Please sign in to comment.