From 1a01713b93ffb8b079b7bd5553eff450482eb6aa Mon Sep 17 00:00:00 2001 From: "Dr. Sergey Pogodin" Date: Mon, 23 Sep 2019 23:46:21 +0200 Subject: [PATCH 1/2] [#8093] Fixes performance of update validator, and flatten function logic Before this commit the `flatten(..)` function failed to deliver what it promised. Namely, it entered into Mixed paths of objects. Update validator, on its side, did not pass the casted doc schema into `flatten(..)`. If the casted doc contained a large Mixed field, all its paths were added into the list of updated paths. They were lated ignored by now removed check for schemaPath type, but performance was already hurt. This commit makes sure that inner sub-paths of Mixed paths are not included into the array of paths at all, thus no further checks of that are necessary, and the performance is restored. Fixes #8093 --- lib/helpers/common.js | 7 +++---- lib/helpers/updateValidators.js | 10 ++-------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/lib/helpers/common.js b/lib/helpers/common.js index b0a8f1b1fd9..b5fb9e4738d 100644 --- a/lib/helpers/common.js +++ b/lib/helpers/common.js @@ -33,15 +33,14 @@ function flatten(update, path, options, schema) { result[path + key] = val; // Avoid going into mixed paths if schema is specified - if (schema != null && schema.paths[path + key] != null && schema.paths[path + key].instance === 'Mixed') { - continue; - } + const keySchema = schema && schema.path(path + key); + if (keySchema && keySchema.instance === 'Mixed') continue; if (shouldFlatten(val)) { if (options && options.skipArrays && Array.isArray(val)) { continue; } - const flat = flatten(val, path + key, options); + const flat = flatten(val, path + key, options, schema); for (const k in flat) { result[k] = flat[k]; } diff --git a/lib/helpers/updateValidators.js b/lib/helpers/updateValidators.js index 6b68ebc9b99..92c088ee6b1 100644 --- a/lib/helpers/updateValidators.js +++ b/lib/helpers/updateValidators.js @@ -54,7 +54,7 @@ module.exports = function(query, schema, castedDoc, options, callback) { continue; } modifiedPaths(castedDoc[keys[i]], '', modified); - const flat = flatten(castedDoc[keys[i]]); + const flat = flatten(castedDoc[keys[i]], null, null, schema); const paths = Object.keys(flat); const numPaths = paths.length; for (let j = 0; j < numPaths; ++j) { @@ -79,7 +79,7 @@ module.exports = function(query, schema, castedDoc, options, callback) { if (!hasDollarUpdate) { modifiedPaths(castedDoc, '', modified); - updatedValues = flatten(castedDoc); + updatedValues = flatten(castedDoc, null, null, schema); updatedKeys = Object.keys(updatedValues); } @@ -97,12 +97,6 @@ module.exports = function(query, schema, castedDoc, options, callback) { return; } - // gh-4305: `_getSchema()` will report all sub-fields of a 'Mixed' path - // as 'Mixed', so avoid double validating them. - if (schemaPath instanceof Mixed && schemaPath.path !== updates[i]) { - return; - } - if (v && Array.isArray(v.$in)) { v.$in.forEach((v, i) => { validatorsToExecute.push(function(callback) { From c76e06267fcc9f99b561f6962783fa7d2e2b8cf5 Mon Sep 17 00:00:00 2001 From: "Dr. Sergey Pogodin" Date: Tue, 24 Sep 2019 00:23:17 +0200 Subject: [PATCH 2/2] Fixes the previous commit --- lib/helpers/common.js | 2 +- lib/helpers/updateValidators.js | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/helpers/common.js b/lib/helpers/common.js index b5fb9e4738d..3398f4cbe09 100644 --- a/lib/helpers/common.js +++ b/lib/helpers/common.js @@ -33,7 +33,7 @@ function flatten(update, path, options, schema) { result[path + key] = val; // Avoid going into mixed paths if schema is specified - const keySchema = schema && schema.path(path + key); + const keySchema = schema && schema.path && schema.path(path + key); if (keySchema && keySchema.instance === 'Mixed') continue; if (shouldFlatten(val)) { diff --git a/lib/helpers/updateValidators.js b/lib/helpers/updateValidators.js index 92c088ee6b1..199ef0677f7 100644 --- a/lib/helpers/updateValidators.js +++ b/lib/helpers/updateValidators.js @@ -4,7 +4,6 @@ * Module dependencies. */ -const Mixed = require('../schema/mixed'); const ValidationError = require('../error/validation'); const cleanPositionalOperators = require('./schema/cleanPositionalOperators'); const flatten = require('./common').flatten;