This commit is contained in:
Jonasz Bigda
2023-03-25 21:51:42 +01:00
parent 0db1d5117e
commit b332e9ceb0
1044 changed files with 37502 additions and 63938 deletions

View File

@@ -56,6 +56,9 @@ function applyQueryMiddleware(Query, model) {
if (hook.name === 'validate' || hook.name === 'remove') {
return !!contexts.query;
}
if (hook.query != null || hook.document != null) {
return !!hook.query;
}
return true;
});

View File

@@ -25,7 +25,7 @@ module.exports = function castFilterPath(query, schematype, val) {
if (nested && schematype && !schematype.caster) {
const _keys = Object.keys(nested);
if (_keys.length && isOperator(_keys[0])) {
for (const key in nested) {
for (const key of Object.keys(nested)) {
nested[key] = schematype.castForQueryWrapper({
$conditional: key,
val: nested[key],

View File

@@ -6,10 +6,12 @@ const StrictModeError = require('../../error/strict');
const ValidationError = require('../../error/validation');
const castNumber = require('../../cast/number');
const cast = require('../../cast');
const getConstructorName = require('../getConstructorName');
const getEmbeddedDiscriminatorPath = require('./getEmbeddedDiscriminatorPath');
const handleImmutable = require('./handleImmutable');
const moveImmutableProperties = require('../update/moveImmutableProperties');
const schemaMixedSymbol = require('../../schema/symbols').schemaMixedSymbol;
const setDottedPath = require('../path/setDottedPath');
const utils = require('../../utils');
/*!
@@ -105,6 +107,14 @@ module.exports = function castUpdate(schema, obj, options, context, filter) {
}
}
if (Object.keys(ret).length === 0 &&
options.upsert &&
Object.keys(filter).length > 0) {
// Trick the driver into allowing empty upserts to work around
// https://github.com/mongodb/node-mongodb-native/pull/2490
return { $setOnInsert: filter };
}
return ret;
};
@@ -191,11 +201,19 @@ function walkUpdatePath(schema, obj, op, options, context, filter, pref) {
}
}
if (val && val.constructor.name === 'Object') {
if (getConstructorName(val) === 'Object') {
// watch for embedded doc schemas
schematype = schema._getSchema(prefix + key);
if (handleImmutable(schematype, strict, obj, key, prefix + key, context)) {
if (schematype == null) {
const _res = getEmbeddedDiscriminatorPath(schema, obj, filter, prefix + key, options);
if (_res.schematype != null) {
schematype = _res.schematype;
}
}
if (op !== '$setOnInsert' &&
handleImmutable(schematype, strict, obj, key, prefix + key, context)) {
continue;
}
@@ -308,7 +326,7 @@ function walkUpdatePath(schema, obj, op, options, context, filter, pref) {
// If no schema type, check for embedded discriminators because the
// filter or update may imply an embedded discriminator type. See #8378
if (schematype == null) {
const _res = getEmbeddedDiscriminatorPath(schema, obj, filter, checkPath);
const _res = getEmbeddedDiscriminatorPath(schema, obj, filter, checkPath, options);
if (_res.schematype != null) {
schematype = _res.schematype;
pathDetails = _res.type;
@@ -344,7 +362,15 @@ function walkUpdatePath(schema, obj, op, options, context, filter, pref) {
}
try {
obj[key] = castUpdateVal(schematype, val, op, key, context, prefix + key);
if (prefix.length === 0 || key.indexOf('.') === -1) {
obj[key] = castUpdateVal(schematype, val, op, key, context, prefix + key);
} else {
// Setting a nested dotted path that's in the schema. We don't allow paths with '.' in
// a schema, so replace the dotted path with a nested object to avoid ending up with
// dotted properties in the updated object. See (gh-10200)
setDottedPath(obj, key, castUpdateVal(schematype, val, op, key, context, prefix + key));
delete obj[key];
}
} catch (error) {
aggregatedError = _handleCastError(error, context, key, aggregatedError);
}

View File

@@ -1,6 +1,7 @@
'use strict';
const helpers = require('../../queryhelpers');
const immediate = require('../immediate');
module.exports = completeMany;
@@ -29,10 +30,10 @@ function completeMany(model, docs, fields, userProvidedFields, opts, callback) {
error = error || _error;
}
if (error != null) {
--count || process.nextTick(() => callback(error));
--count || immediate(() => callback(error));
return;
}
--count || process.nextTick(() => callback(error, arr));
--count || immediate(() => callback(error, arr));
}
for (let i = 0; i < len; ++i) {
@@ -42,6 +43,9 @@ function completeMany(model, docs, fields, userProvidedFields, opts, callback) {
} catch (error) {
init(error);
}
arr[i].$session(opts.session);
if (opts.session != null) {
arr[i].$session(opts.session);
}
}
}

View File

@@ -3,19 +3,23 @@
const cleanPositionalOperators = require('../schema/cleanPositionalOperators');
const get = require('../get');
const getDiscriminatorByValue = require('../discriminator/getDiscriminatorByValue');
const updatedPathsByArrayFilter = require('../update/updatedPathsByArrayFilter');
/*!
* Like `schema.path()`, except with a document, because impossible to
* determine path type without knowing the embedded discriminator key.
*/
module.exports = function getEmbeddedDiscriminatorPath(schema, update, filter, path) {
module.exports = function getEmbeddedDiscriminatorPath(schema, update, filter, path, options) {
const parts = path.split('.');
let schematype = null;
let type = 'adhocOrUndefined';
filter = filter || {};
update = update || {};
const arrayFilters = options != null && Array.isArray(options.arrayFilters) ?
options.arrayFilters : [];
const updatedPathsByFilter = updatedPathsByArrayFilter(update);
for (let i = 0; i < parts.length; ++i) {
const subpath = cleanPositionalOperators(parts.slice(0, i + 1).join('.'));
@@ -39,6 +43,7 @@ module.exports = function getEmbeddedDiscriminatorPath(schema, update, filter, p
if (discriminatorFilterPath in filter) {
discriminatorKey = filter[discriminatorFilterPath];
}
const wrapperPath = subpath.replace(/\.\d+$/, '');
if (schematype.$isMongooseDocumentArrayElement &&
get(filter[wrapperPath], '$elemMatch.' + key) != null) {
@@ -49,11 +54,22 @@ module.exports = function getEmbeddedDiscriminatorPath(schema, update, filter, p
discriminatorKey = update[discriminatorValuePath];
}
for (const filterKey of Object.keys(updatedPathsByFilter)) {
const schemaKey = updatedPathsByFilter[filterKey] + '.' + key;
const arrayFilterKey = filterKey + '.' + key;
if (schemaKey === discriminatorFilterPath) {
const filter = arrayFilters.find(filter => filter.hasOwnProperty(arrayFilterKey));
if (filter != null) {
discriminatorKey = filter[arrayFilterKey];
}
}
}
if (discriminatorKey == null) {
continue;
}
const discriminatorSchema = getDiscriminatorByValue(schematype.caster, discriminatorKey).schema;
const discriminatorSchema = getDiscriminatorByValue(schematype.caster.discriminators, discriminatorKey).schema;
const rest = parts.slice(i + 1).join('.');
schematype = discriminatorSchema.path(rest);

View File

@@ -1,28 +1,31 @@
'use strict';
const isExclusive = require('../projection/isExclusive');
const isInclusive = require('../projection/isInclusive');
/*!
* ignore
*/
module.exports = function selectPopulatedFields(query) {
const opts = query._mongooseOptions;
module.exports = function selectPopulatedFields(fields, userProvidedFields, populateOptions) {
if (populateOptions == null) {
return;
}
if (opts.populate != null) {
const paths = Object.keys(opts.populate);
const userProvidedFields = query._userProvidedFields || {};
if (query.selectedInclusively()) {
for (const path of paths) {
if (!isPathInFields(userProvidedFields, path)) {
query.select(path);
} else if (userProvidedFields[path] === 0) {
delete query._fields[path];
}
const paths = Object.keys(populateOptions);
userProvidedFields = userProvidedFields || {};
if (isInclusive(fields)) {
for (const path of paths) {
if (!isPathInFields(userProvidedFields, path)) {
fields[path] = 1;
} else if (userProvidedFields[path] === 0) {
delete fields[path];
}
} else if (query.selectedExclusively()) {
for (const path of paths) {
if (userProvidedFields[path] == null) {
delete query._fields[path];
}
}
} else if (isExclusive(fields)) {
for (const path of paths) {
if (userProvidedFields[path] == null) {
delete fields[path];
}
}
}
@@ -37,10 +40,10 @@ function isPathInFields(userProvidedFields, path) {
const len = pieces.length;
let cur = pieces[0];
for (let i = 1; i < len; ++i) {
if (userProvidedFields[cur] != null) {
if (userProvidedFields[cur] != null || userProvidedFields[cur + '.$'] != null) {
return true;
}
cur += '.' + pieces[i];
}
return userProvidedFields[cur] != null;
return userProvidedFields[cur] != null || userProvidedFields[cur + '.$'] != null;
}