Cleanup
This commit is contained in:
7
node_modules/mongoose/lib/helpers/populate/assignRawDocsToIdStructure.js
generated
vendored
7
node_modules/mongoose/lib/helpers/populate/assignRawDocsToIdStructure.js
generated
vendored
@@ -69,7 +69,12 @@ function assignRawDocsToIdStructure(rawIds, resultDocs, resultOrder, options, re
|
||||
if (recursed) {
|
||||
if (doc) {
|
||||
if (sorting) {
|
||||
newOrder[resultOrder[sid]] = doc;
|
||||
const _resultOrder = resultOrder[sid];
|
||||
if (Array.isArray(_resultOrder) && Array.isArray(doc) && _resultOrder.length === doc.length) {
|
||||
newOrder.push(doc);
|
||||
} else {
|
||||
newOrder[_resultOrder] = doc;
|
||||
}
|
||||
} else {
|
||||
newOrder.push(doc);
|
||||
}
|
||||
|
||||
109
node_modules/mongoose/lib/helpers/populate/assignVals.js
generated
vendored
109
node_modules/mongoose/lib/helpers/populate/assignVals.js
generated
vendored
@@ -5,24 +5,27 @@ const assignRawDocsToIdStructure = require('./assignRawDocsToIdStructure');
|
||||
const get = require('../get');
|
||||
const getVirtual = require('./getVirtual');
|
||||
const leanPopulateMap = require('./leanPopulateMap');
|
||||
const lookupLocalFields = require('./lookupLocalFields');
|
||||
const mpath = require('mpath');
|
||||
const sift = require('sift').default;
|
||||
const utils = require('../../utils');
|
||||
|
||||
module.exports = function assignVals(o) {
|
||||
// Options that aren't explicitly listed in `populateOptions`
|
||||
const userOptions = get(o, 'allOptions.options.options');
|
||||
const userOptions = Object.assign({}, get(o, 'allOptions.options.options'), get(o, 'allOptions.options'));
|
||||
// `o.options` contains options explicitly listed in `populateOptions`, like
|
||||
// `match` and `limit`.
|
||||
const populateOptions = Object.assign({}, o.options, userOptions, {
|
||||
justOne: o.justOne
|
||||
});
|
||||
populateOptions.$nullIfNotFound = o.isVirtual;
|
||||
const populatedModel = o.populatedModel;
|
||||
|
||||
const originalIds = [].concat(o.rawIds);
|
||||
|
||||
// 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
|
||||
@@ -31,6 +34,7 @@ module.exports = function assignVals(o) {
|
||||
const rawIds = o.rawIds;
|
||||
const options = o.options;
|
||||
const count = o.count && o.isVirtual;
|
||||
let i;
|
||||
|
||||
function setValue(val) {
|
||||
if (count) {
|
||||
@@ -39,17 +43,42 @@ module.exports = function assignVals(o) {
|
||||
if (val instanceof SkipPopulateValue) {
|
||||
return val.val;
|
||||
}
|
||||
if (o.justOne === true && Array.isArray(val)) {
|
||||
return valueFilter(val[0], options, populateOptions);
|
||||
} else if (o.justOne === false && !Array.isArray(val)) {
|
||||
return valueFilter([val], options, populateOptions);
|
||||
if (val === void 0) {
|
||||
return val;
|
||||
}
|
||||
return valueFilter(val, options, populateOptions);
|
||||
|
||||
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.
|
||||
const ret = [];
|
||||
for (const doc of val) {
|
||||
const _docPopulatedModel = leanPopulateMap.get(doc);
|
||||
if (_docPopulatedModel == null || _docPopulatedModel === populatedModel) {
|
||||
ret.push(doc);
|
||||
}
|
||||
}
|
||||
// Since we don't want to have to create a new mongoosearray, make sure to
|
||||
// modify the array in place
|
||||
while (val.length > ret.length) {
|
||||
Array.prototype.pop.apply(val, []);
|
||||
}
|
||||
for (let i = 0; i < ret.length; ++i) {
|
||||
val[i] = ret[i];
|
||||
}
|
||||
|
||||
return valueFilter(val[0], options, populateOptions, _allIds);
|
||||
} else if (o.justOne === false && !Array.isArray(val)) {
|
||||
return valueFilter([val], options, populateOptions, _allIds);
|
||||
}
|
||||
return valueFilter(val, options, populateOptions, _allIds);
|
||||
}
|
||||
|
||||
for (let i = 0; i < docs.length; ++i) {
|
||||
const existingVal = utils.getValue(o.path, docs[i]);
|
||||
if (existingVal == null && !getVirtual(o.originalModel.schema, o.path)) {
|
||||
for (i = 0; i < docs.length; ++i) {
|
||||
const _path = o.path.endsWith('.$*') ? o.path.slice(0, -3) : o.path;
|
||||
const existingVal = mpath.get(_path, docs[i], lookupLocalFields);
|
||||
if (existingVal == null && !getVirtual(o.originalModel.schema, _path)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -58,8 +87,8 @@ module.exports = function assignVals(o) {
|
||||
valueToSet = numDocs(rawIds[i]);
|
||||
} else if (Array.isArray(o.match)) {
|
||||
valueToSet = Array.isArray(rawIds[i]) ?
|
||||
sift(o.match[i], rawIds[i]) :
|
||||
sift(o.match[i], [rawIds[i]])[0];
|
||||
rawIds[i].filter(sift(o.match[i])) :
|
||||
[rawIds[i]].filter(sift(o.match[i]))[0];
|
||||
} else {
|
||||
valueToSet = rawIds[i];
|
||||
}
|
||||
@@ -73,7 +102,7 @@ module.exports = function assignVals(o) {
|
||||
utils.isPOJO(existingVal);
|
||||
// If we pass the first check, also make sure the local field's schematype
|
||||
// is map (re: gh-6460)
|
||||
isMap = isMap && get(originalSchema._getSchema(o.path), '$isSchemaMap');
|
||||
isMap = isMap && get(originalSchema._getSchema(_path), '$isSchemaMap');
|
||||
if (!o.isVirtual && isMap) {
|
||||
const _keys = existingVal instanceof Map ?
|
||||
Array.from(existingVal.keys()) :
|
||||
@@ -84,15 +113,25 @@ module.exports = function assignVals(o) {
|
||||
}, new Map());
|
||||
}
|
||||
|
||||
if (isDoc && Array.isArray(valueToSet)) {
|
||||
for (const val of valueToSet) {
|
||||
if (val != null && val.$__ != null) {
|
||||
val.$__.parent = docs[i];
|
||||
}
|
||||
}
|
||||
} else if (isDoc && valueToSet != null && valueToSet.$__ != null) {
|
||||
valueToSet.$__.parent = docs[i];
|
||||
}
|
||||
|
||||
if (o.isVirtual && isDoc) {
|
||||
docs[i].populated(o.path, o.justOne ? originalIds[0] : originalIds, o.allOptions);
|
||||
docs[i].populated(_path, o.justOne ? originalIds[0] : originalIds, o.allOptions);
|
||||
// If virtual populate and doc is already init-ed, need to walk through
|
||||
// the actual doc to set rather than setting `_doc` directly
|
||||
mpath.set(o.path, valueToSet, docs[i], setValue);
|
||||
mpath.set(_path, valueToSet, docs[i], setValue);
|
||||
continue;
|
||||
}
|
||||
|
||||
const parts = o.path.split('.');
|
||||
const parts = _path.split('.');
|
||||
let cur = docs[i];
|
||||
const curPath = parts[0];
|
||||
for (let j = 0; j < parts.length - 1; ++j) {
|
||||
@@ -102,13 +141,17 @@ module.exports = function assignVals(o) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (parts[j] === '$*') {
|
||||
break;
|
||||
}
|
||||
|
||||
if (cur[parts[j]] == null) {
|
||||
// If nothing to set, avoid creating an unnecessary array. Otherwise
|
||||
// we'll end up with a single doc in the array with only defaults.
|
||||
// See gh-8342, gh-8455
|
||||
const schematype = originalSchema._getSchema(curPath);
|
||||
if (valueToSet == null && schematype != null && schematype.$isMongooseArray) {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
cur[parts[j]] = {};
|
||||
}
|
||||
@@ -116,17 +159,17 @@ module.exports = function assignVals(o) {
|
||||
// If the property in MongoDB is a primitive, we won't be able to populate
|
||||
// the nested path, so skip it. See gh-7545
|
||||
if (typeof cur !== 'object') {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (docs[i].$__) {
|
||||
docs[i].populated(o.path, o.allIds[i], o.allOptions);
|
||||
docs[i].populated(_path, o.allIds[i], o.allOptions);
|
||||
}
|
||||
|
||||
// If lean, need to check that each individual virtual respects
|
||||
// `justOne`, because you may have a populated virtual with `justOne`
|
||||
// underneath an array. See gh-6867
|
||||
utils.setValue(o.path, valueToSet, docs[i], setValue, false);
|
||||
mpath.set(_path, valueToSet, docs[i], lookupLocalFields, setValue, false);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -160,15 +203,20 @@ function numDocs(v) {
|
||||
* that population mapping can occur.
|
||||
*/
|
||||
|
||||
function valueFilter(val, assignmentOpts, populateOptions) {
|
||||
function valueFilter(val, assignmentOpts, populateOptions, allIds) {
|
||||
const userSpecifiedTransform = typeof populateOptions.transform === 'function';
|
||||
const transform = userSpecifiedTransform ? populateOptions.transform : noop;
|
||||
if (Array.isArray(val)) {
|
||||
// find logic
|
||||
const ret = [];
|
||||
const numValues = val.length;
|
||||
for (let i = 0; i < numValues; ++i) {
|
||||
const subdoc = val[i];
|
||||
if (!isPopulatedObject(subdoc) && (!populateOptions.retainNullValues || subdoc != null)) {
|
||||
let subdoc = val[i];
|
||||
const _allIds = Array.isArray(allIds) ? allIds[i] : allIds;
|
||||
if (!isPopulatedObject(subdoc) && (!populateOptions.retainNullValues || subdoc != null) && !userSpecifiedTransform) {
|
||||
continue;
|
||||
} else if (userSpecifiedTransform) {
|
||||
subdoc = transform(isPopulatedObject(subdoc) ? subdoc : null, _allIds);
|
||||
}
|
||||
maybeRemoveId(subdoc, assignmentOpts);
|
||||
ret.push(subdoc);
|
||||
@@ -190,22 +238,19 @@ function valueFilter(val, assignmentOpts, populateOptions) {
|
||||
}
|
||||
|
||||
// findOne
|
||||
if (isPopulatedObject(val)) {
|
||||
if (isPopulatedObject(val) || utils.isPOJO(val)) {
|
||||
maybeRemoveId(val, assignmentOpts);
|
||||
return val;
|
||||
return transform(val, allIds);
|
||||
}
|
||||
|
||||
if (val instanceof Map) {
|
||||
return val;
|
||||
}
|
||||
|
||||
if (populateOptions.justOne === true) {
|
||||
return (val == null ? val : null);
|
||||
}
|
||||
if (populateOptions.justOne === false) {
|
||||
return [];
|
||||
}
|
||||
return val;
|
||||
|
||||
return val == null ? transform(val, allIds) : transform(null, allIds);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -213,7 +258,7 @@ function valueFilter(val, assignmentOpts, populateOptions) {
|
||||
*/
|
||||
|
||||
function maybeRemoveId(subdoc, assignmentOpts) {
|
||||
if (assignmentOpts.excludeId) {
|
||||
if (subdoc != null && assignmentOpts.excludeId) {
|
||||
if (typeof subdoc.$__setValue === 'function') {
|
||||
delete subdoc._doc._id;
|
||||
} else {
|
||||
@@ -236,4 +281,8 @@ function isPopulatedObject(obj) {
|
||||
obj.$isMongooseMap ||
|
||||
obj.$__ != null ||
|
||||
leanPopulateMap.has(obj);
|
||||
}
|
||||
|
||||
function noop(v) {
|
||||
return v;
|
||||
}
|
||||
127
node_modules/mongoose/lib/helpers/populate/getModelsMapForPopulate.js
generated
vendored
127
node_modules/mongoose/lib/helpers/populate/getModelsMapForPopulate.js
generated
vendored
@@ -5,8 +5,11 @@ const SkipPopulateValue = require('./SkipPopulateValue');
|
||||
const get = require('../get');
|
||||
const getDiscriminatorByValue = require('../discriminator/getDiscriminatorByValue');
|
||||
const isPathExcluded = require('../projection/isPathExcluded');
|
||||
const getConstructorName = require('../getConstructorName');
|
||||
const getSchemaTypes = require('./getSchemaTypes');
|
||||
const getVirtual = require('./getVirtual');
|
||||
const lookupLocalFields = require('./lookupLocalFields');
|
||||
const mpath = require('mpath');
|
||||
const normalizeRefPath = require('./normalizeRefPath');
|
||||
const util = require('util');
|
||||
const utils = require('../../utils');
|
||||
@@ -28,7 +31,6 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
let currentOptions;
|
||||
let modelNames;
|
||||
let modelName;
|
||||
let modelForFindSchema;
|
||||
|
||||
const originalModel = options.model;
|
||||
let isVirtual = false;
|
||||
@@ -40,7 +42,7 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
doc = docs[i];
|
||||
|
||||
let justOne = null;
|
||||
schema = getSchemaTypes(modelSchema, doc, options.path);
|
||||
// Special case: populating a path that's a DocumentArray unless
|
||||
// there's an explicit `ref` or `refPath` re: gh-8946
|
||||
@@ -52,7 +54,7 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
}
|
||||
// Populating a nested path should always be a no-op re: #9073.
|
||||
// People shouldn't do this, but apparently they do.
|
||||
if (modelSchema.nested[options.path]) {
|
||||
if (options._localModel != null && options._localModel.schema.nested[options.path]) {
|
||||
continue;
|
||||
}
|
||||
const isUnderneathDocArray = schema && schema.$isUnderneathDocArray;
|
||||
@@ -64,6 +66,7 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
modelNames = null;
|
||||
let isRefPath = !!_firstWithRefPath;
|
||||
let normalizedRefPath = _firstWithRefPath ? get(_firstWithRefPath, 'options.refPath', null) : null;
|
||||
let schemaOptions = null;
|
||||
|
||||
if (Array.isArray(schema)) {
|
||||
const schemasArray = schema;
|
||||
@@ -76,6 +79,7 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
isRefPath = isRefPath || res.isRefPath;
|
||||
normalizedRefPath = normalizeRefPath(normalizedRefPath, doc, options.path) ||
|
||||
res.refPath;
|
||||
justOne = res.justOne;
|
||||
} catch (error) {
|
||||
return error;
|
||||
}
|
||||
@@ -99,6 +103,8 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
modelNames = res.modelNames;
|
||||
isRefPath = res.isRefPath;
|
||||
normalizedRefPath = res.refPath;
|
||||
justOne = res.justOne;
|
||||
schemaOptions = get(schema, 'options.populate', null);
|
||||
} catch (error) {
|
||||
return error;
|
||||
}
|
||||
@@ -118,6 +124,8 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
_virtualRes.nestedSchemaPath + '.' : '';
|
||||
if (typeof virtual.options.localField === 'function') {
|
||||
localField = virtualPrefix + virtual.options.localField.call(doc, doc);
|
||||
} else if (Array.isArray(virtual.options.localField)) {
|
||||
localField = virtual.options.localField.map(field => virtualPrefix + field);
|
||||
} else {
|
||||
localField = virtualPrefix + virtual.options.localField;
|
||||
}
|
||||
@@ -142,7 +150,6 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
// `justOne = null` means we don't know from the schema whether the end
|
||||
// result should be an array or a single doc. This can result from
|
||||
// populating a POJO using `Model.populate()`
|
||||
let justOne = null;
|
||||
if ('justOne' in options && options.justOne !== void 0) {
|
||||
justOne = options.justOne;
|
||||
} else if (virtual && virtual.options && virtual.options.refPath) {
|
||||
@@ -166,9 +173,11 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
}
|
||||
} else if (schema && !schema[schemaMixedSymbol]) {
|
||||
// Skip Mixed types because we explicitly don't do casting on those.
|
||||
justOne = Array.isArray(schema) ?
|
||||
schema.every(schema => !schema.$isMongooseArray) :
|
||||
!schema.$isMongooseArray;
|
||||
if (options.path.endsWith('.' + schema.path)) {
|
||||
justOne = Array.isArray(schema) ?
|
||||
schema.every(schema => !schema.$isMongooseArray) :
|
||||
!schema.$isMongooseArray;
|
||||
}
|
||||
}
|
||||
|
||||
if (!modelNames) {
|
||||
@@ -189,6 +198,27 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
foreignField = foreignField.call(doc);
|
||||
}
|
||||
|
||||
let match = get(options, 'match', null) ||
|
||||
get(currentOptions, 'match', null) ||
|
||||
get(options, 'virtual.options.match', null) ||
|
||||
get(options, 'virtual.options.options.match', null);
|
||||
|
||||
let hasMatchFunction = typeof match === 'function';
|
||||
if (hasMatchFunction) {
|
||||
match = match.call(doc, doc);
|
||||
}
|
||||
|
||||
if (Array.isArray(localField) && Array.isArray(foreignField) && localField.length === foreignField.length) {
|
||||
match = Object.assign({}, match);
|
||||
for (let i = 1; i < localField.length; ++i) {
|
||||
match[foreignField[i]] = convertTo_id(mpath.get(localField[i], doc, lookupLocalFields), schema);
|
||||
hasMatchFunction = true;
|
||||
}
|
||||
|
||||
localField = localField[0];
|
||||
foreignField = foreignField[0];
|
||||
}
|
||||
|
||||
const localFieldPathType = modelSchema._getPathType(localField);
|
||||
const localFieldPath = localFieldPathType === 'real' ? modelSchema.path(localField) : localFieldPathType.schema;
|
||||
const localFieldGetters = localFieldPath && localFieldPath.getters ? localFieldPath.getters : [];
|
||||
@@ -201,31 +231,21 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
options.isVirtual && get(virtual, 'options.getters', false);
|
||||
if (localFieldGetters.length > 0 && getters) {
|
||||
const hydratedDoc = (doc.$__ != null) ? doc : model.hydrate(doc);
|
||||
const localFieldValue = utils.getValue(localField, doc);
|
||||
const localFieldValue = mpath.get(localField, doc, lookupLocalFields);
|
||||
if (Array.isArray(localFieldValue)) {
|
||||
const localFieldHydratedValue = utils.getValue(localField.split('.').slice(0, -1), hydratedDoc);
|
||||
const localFieldHydratedValue = mpath.get(localField.split('.').slice(0, -1), hydratedDoc, lookupLocalFields);
|
||||
ret = localFieldValue.map((localFieldArrVal, localFieldArrIndex) =>
|
||||
localFieldPath.applyGetters(localFieldArrVal, localFieldHydratedValue[localFieldArrIndex]));
|
||||
} else {
|
||||
ret = localFieldPath.applyGetters(localFieldValue, hydratedDoc);
|
||||
}
|
||||
} else {
|
||||
ret = convertTo_id(utils.getValue(localField, doc), schema);
|
||||
ret = convertTo_id(mpath.get(localField, doc, lookupLocalFields), schema);
|
||||
}
|
||||
|
||||
const id = String(utils.getValue(foreignField, doc));
|
||||
options._docs[id] = Array.isArray(ret) ? ret.slice() : ret;
|
||||
|
||||
let match = get(options, 'match', null) ||
|
||||
get(currentOptions, 'match', null) ||
|
||||
get(options, 'virtual.options.match', null) ||
|
||||
get(options, 'virtual.options.options.match', null);
|
||||
|
||||
const hasMatchFunction = typeof match === 'function';
|
||||
if (hasMatchFunction) {
|
||||
match = match.call(doc, doc);
|
||||
}
|
||||
|
||||
// Re: gh-8452. Embedded discriminators may not have `refPath`, so clear
|
||||
// out embedded discriminator docs that don't have a `refPath` on the
|
||||
// populated path.
|
||||
@@ -280,7 +300,12 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
originalModel :
|
||||
modelName[modelSymbol] ? modelName : connection.model(modelName);
|
||||
} catch (error) {
|
||||
return error;
|
||||
// If `ret` is undefined, we'll add an empty entry to modelsMap. We shouldn't
|
||||
// execute a query, but it is necessary to make sure `justOne` gets handled
|
||||
// correctly for setting an empty array (see gh-8455)
|
||||
if (ret !== undefined) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
let ids = ret;
|
||||
@@ -290,13 +315,15 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
ids = flat.filter((val, i) => modelNames[i] === modelName);
|
||||
}
|
||||
|
||||
if (!available[modelName] || currentOptions.perDocumentLimit != null) {
|
||||
if (!available[modelName] || currentOptions.perDocumentLimit != null || get(currentOptions, 'options.perDocumentLimit') != null) {
|
||||
currentOptions = {
|
||||
model: Model
|
||||
};
|
||||
|
||||
if (isVirtual && get(virtual, 'options.options')) {
|
||||
currentOptions.options = utils.clone(virtual.options.options);
|
||||
} else if (schemaOptions != null) {
|
||||
currentOptions.options = Object.assign({}, schemaOptions);
|
||||
}
|
||||
utils.merge(currentOptions, options);
|
||||
|
||||
@@ -332,13 +359,13 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return map;
|
||||
|
||||
function _getModelNames(doc, schema) {
|
||||
let modelNames;
|
||||
let discriminatorKey;
|
||||
let isRefPath = false;
|
||||
let justOne = null;
|
||||
|
||||
if (schema && schema.caster) {
|
||||
schema = schema.caster;
|
||||
@@ -378,28 +405,26 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
} else {
|
||||
let modelForCurrentDoc = model;
|
||||
let schemaForCurrentDoc;
|
||||
let discriminatorValue;
|
||||
|
||||
if (!schema && discriminatorKey) {
|
||||
modelForFindSchema = utils.getValue(discriminatorKey, doc);
|
||||
if (modelForFindSchema) {
|
||||
// `modelForFindSchema` is the discriminator value, so we might need
|
||||
// find the discriminated model name
|
||||
const discriminatorModel = getDiscriminatorByValue(model, modelForFindSchema);
|
||||
if (discriminatorModel != null) {
|
||||
modelForCurrentDoc = discriminatorModel;
|
||||
} else {
|
||||
try {
|
||||
modelForCurrentDoc = model.db.model(modelForFindSchema);
|
||||
} catch (error) {
|
||||
return error;
|
||||
}
|
||||
if (!schema && discriminatorKey && (discriminatorValue = utils.getValue(discriminatorKey, doc))) {
|
||||
// `modelNameForFind` is the discriminator value, so we might need
|
||||
// find the discriminated model name
|
||||
const discriminatorModel = getDiscriminatorByValue(model.discriminators, discriminatorValue) || model;
|
||||
if (discriminatorModel != null) {
|
||||
modelForCurrentDoc = discriminatorModel;
|
||||
} else {
|
||||
try {
|
||||
modelForCurrentDoc = model.db.model(discriminatorValue);
|
||||
} catch (error) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
schemaForCurrentDoc = modelForCurrentDoc.schema._getSchema(options.path);
|
||||
schemaForCurrentDoc = modelForCurrentDoc.schema._getSchema(options.path);
|
||||
|
||||
if (schemaForCurrentDoc && schemaForCurrentDoc.caster) {
|
||||
schemaForCurrentDoc = schemaForCurrentDoc.caster;
|
||||
}
|
||||
if (schemaForCurrentDoc && schemaForCurrentDoc.caster) {
|
||||
schemaForCurrentDoc = schemaForCurrentDoc.caster;
|
||||
}
|
||||
} else {
|
||||
schemaForCurrentDoc = schema;
|
||||
@@ -407,6 +432,10 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
const _virtualRes = getVirtual(modelForCurrentDoc.schema, options.path);
|
||||
const virtual = _virtualRes == null ? null : _virtualRes.virtual;
|
||||
|
||||
if (schemaForCurrentDoc != null) {
|
||||
justOne = !schemaForCurrentDoc.$isMongooseArray && !schemaForCurrentDoc._arrayPath;
|
||||
}
|
||||
|
||||
let ref;
|
||||
let refPath;
|
||||
|
||||
@@ -440,14 +469,14 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
}
|
||||
|
||||
if (!modelNames) {
|
||||
return { modelNames: modelNames, isRefPath: isRefPath, refPath: normalizedRefPath };
|
||||
return { modelNames: modelNames, isRefPath: isRefPath, refPath: normalizedRefPath, justOne: justOne };
|
||||
}
|
||||
|
||||
if (!Array.isArray(modelNames)) {
|
||||
modelNames = [modelNames];
|
||||
}
|
||||
|
||||
return { modelNames: modelNames, isRefPath: isRefPath, refPath: normalizedRefPath };
|
||||
return { modelNames: modelNames, isRefPath: isRefPath, refPath: normalizedRefPath, justOne: justOne };
|
||||
}
|
||||
};
|
||||
|
||||
@@ -470,7 +499,12 @@ function handleRefFunction(ref, doc) {
|
||||
*/
|
||||
|
||||
function convertTo_id(val, schema) {
|
||||
if (val != null && val.$__ != null) return val._id;
|
||||
if (val != null && val.$__ != null) {
|
||||
return val._id;
|
||||
}
|
||||
if (val != null && val._id != null && (schema == null || !schema.$isSchemaMap)) {
|
||||
return val._id;
|
||||
}
|
||||
|
||||
if (Array.isArray(val)) {
|
||||
for (let i = 0; i < val.length; ++i) {
|
||||
@@ -479,7 +513,7 @@ function convertTo_id(val, schema) {
|
||||
}
|
||||
}
|
||||
if (val.isMongooseArray && val.$schema()) {
|
||||
return val.$schema().cast(val, val.$parent());
|
||||
return val.$schema()._castForPopulate(val, val.$parent());
|
||||
}
|
||||
|
||||
return [].concat(val);
|
||||
@@ -487,8 +521,7 @@ function convertTo_id(val, schema) {
|
||||
|
||||
// `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 (getConstructorName(val) === '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)) {
|
||||
|
||||
35
node_modules/mongoose/lib/helpers/populate/getSchemaTypes.js
generated
vendored
35
node_modules/mongoose/lib/helpers/populate/getSchemaTypes.js
generated
vendored
@@ -20,7 +20,6 @@ const populateModelSymbol = require('../symbols').populateModelSymbol;
|
||||
module.exports = function getSchemaTypes(schema, doc, path) {
|
||||
const pathschema = schema.path(path);
|
||||
const topLevelDoc = doc;
|
||||
|
||||
if (pathschema) {
|
||||
return pathschema;
|
||||
}
|
||||
@@ -33,7 +32,6 @@ module.exports = function getSchemaTypes(schema, doc, path) {
|
||||
while (p--) {
|
||||
trypath = parts.slice(0, p).join('.');
|
||||
foundschema = schema.path(trypath);
|
||||
|
||||
if (foundschema == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -52,7 +50,8 @@ module.exports = function getSchemaTypes(schema, doc, path) {
|
||||
const keys = subdoc ? mpath.get(discriminatorKeyPath, subdoc) || [] : [];
|
||||
schemas = Object.keys(discriminators).
|
||||
reduce(function(cur, discriminator) {
|
||||
if (doc == null || keys.indexOf(discriminator) !== -1) {
|
||||
const tiedValue = discriminators[discriminator].discriminatorMapping.value;
|
||||
if (doc == null || keys.indexOf(discriminator) !== -1 || keys.indexOf(tiedValue) !== -1) {
|
||||
cur.push(discriminators[discriminator]);
|
||||
}
|
||||
return cur;
|
||||
@@ -117,24 +116,40 @@ module.exports = function getSchemaTypes(schema, doc, path) {
|
||||
ret.$isUnderneathDocArray = ret.$isUnderneathDocArray ||
|
||||
!foundschema.schema.$isSingleNested;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
} else if (p !== parts.length &&
|
||||
foundschema.$isMongooseArray &&
|
||||
foundschema.casterConstructor.$isMongooseArray) {
|
||||
// Nested arrays. Drill down to the bottom of the nested array.
|
||||
// Ignore discriminators.
|
||||
let type = foundschema;
|
||||
while (type.$isMongooseArray && !type.$isMongooseDocumentArray) {
|
||||
type = type.casterConstructor;
|
||||
}
|
||||
return search(
|
||||
|
||||
const ret = search(
|
||||
parts.slice(p),
|
||||
type.schema,
|
||||
null,
|
||||
nestedPath.concat(parts.slice(0, p))
|
||||
);
|
||||
if (ret != null) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (type.schema.discriminators) {
|
||||
const discriminatorPaths = [];
|
||||
for (const discriminatorName of Object.keys(type.schema.discriminators)) {
|
||||
const _schema = type.schema.discriminators[discriminatorName] || type.schema;
|
||||
const ret = search(parts.slice(p), _schema, null, nestedPath.concat(parts.slice(0, p)));
|
||||
if (ret != null) {
|
||||
discriminatorPaths.push(ret);
|
||||
}
|
||||
}
|
||||
if (discriminatorPaths.length > 0) {
|
||||
return discriminatorPaths;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,7 +168,6 @@ module.exports = function getSchemaTypes(schema, doc, path) {
|
||||
ret.$isUnderneathDocArray = ret.$isUnderneathDocArray ||
|
||||
!model.schema.$isSingleNested;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -173,19 +187,16 @@ module.exports = function getSchemaTypes(schema, doc, path) {
|
||||
nestedPath.concat(parts.slice(0, p))
|
||||
);
|
||||
|
||||
if (ret) {
|
||||
if (ret != null) {
|
||||
ret.$isUnderneathDocArray = ret.$isUnderneathDocArray ||
|
||||
!schema.$isSingleNested;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return foundschema;
|
||||
}
|
||||
}
|
||||
|
||||
// look for arrays
|
||||
const parts = path.split('.');
|
||||
for (let i = 0; i < parts.length; ++i) {
|
||||
|
||||
Reference in New Issue
Block a user