Skip to content

Commit

Permalink
refactor: handle arrays underneath mixed paths for #6405
Browse files Browse the repository at this point in the history
  • Loading branch information
vkarpov15 committed Aug 1, 2019
1 parent 4b2f770 commit 01b182e
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 14 deletions.
11 changes: 10 additions & 1 deletion lib/document.js
Expand Up @@ -1346,7 +1346,16 @@ Document.prototype.get = function(path, type, options) {
adhoc = this.schema.interpretAsType(path, type, this.schema.options);
}

const schema = this.$__path(path) || this.schema.virtualpath(path);
let schema = this.$__path(path);
if (schema == null) {
schema = this.schema.virtualpath(path);
}
if (schema instanceof MixedSchema) {
const virtual = this.schema.virtualpath(path);
if (virtual != null) {
schema = virtual;
}
}
const pieces = path.split('.');
let obj = this._doc;

Expand Down
2 changes: 1 addition & 1 deletion lib/helpers/updateValidators.js
Expand Up @@ -100,7 +100,7 @@ module.exports = function(query, schema, castedDoc, options) {

// gh-4305: `_getSchema()` will report all sub-fields of a 'Mixed' path
// as 'Mixed', so avoid double validating them.
if (schemaPath instanceof Mixed && schemaPath.$fullPath !== updates[i]) {
if (schemaPath instanceof Mixed && schemaPath.path !== updates[i]) {
return;
}

Expand Down
49 changes: 38 additions & 11 deletions lib/schema.js
Expand Up @@ -543,16 +543,11 @@ warnings.increment = '`increment` should not be used as a schema path name ' +

Schema.prototype.path = function(path, obj) {
// Convert to '.$' to check subpaths re: gh-6405
const cleanPath = path.replace(/\.\d+\./g, '.$.').replace(/\.\d+$/, '.$');
const cleanPath = _pathToPositionalSyntax(path);
if (obj === undefined) {
if (this.paths.hasOwnProperty(path)) {
return this.paths[path];
}
if (this.subpaths.hasOwnProperty(cleanPath)) {
return this.subpaths[cleanPath];
}
if (this.singleNestedPaths.hasOwnProperty(cleanPath)) {
return this.singleNestedPaths[cleanPath];
let schematype = _getPath(this, path, cleanPath);
if (schematype != null) {
return schematype;
}

// Look for maps
Expand All @@ -561,6 +556,12 @@ Schema.prototype.path = function(path, obj) {
return mapPath;
}

// Look if a parent of this path is mixed
schematype = this.hasMixedParent(cleanPath);
if (schematype != null) {
return schematype;
}

// subpaths?
return /\.\d+\.?.*$/.test(path)
? getPositionalPath(this, path)
Expand Down Expand Up @@ -705,6 +706,32 @@ function gatherChildSchemas(schema) {
return childSchemas;
}

/*!
* ignore
*/

function _getPath(schema, path, cleanPath) {
if (schema.paths.hasOwnProperty(path)) {
return schema.paths[path];
}
if (schema.subpaths.hasOwnProperty(cleanPath)) {
return schema.subpaths[cleanPath];
}
if (schema.singleNestedPaths.hasOwnProperty(cleanPath)) {
return schema.singleNestedPaths[cleanPath];
}

return null;
}

/*!
* ignore
*/

function _pathToPositionalSyntax(path) {
return path.replace(/\.\d+\./g, '.$.').replace(/\.\d+$/, '.$');
}

/*!
* ignore
*/
Expand Down Expand Up @@ -1014,11 +1041,11 @@ Schema.prototype.hasMixedParent = function(path) {
path = i > 0 ? path + '.' + subpaths[i] : subpaths[i];
if (path in this.paths &&
this.paths[path] instanceof MongooseTypes.Mixed) {
return true;
return this.paths[path];
}
}

return false;
return null;
};

/**
Expand Down
2 changes: 1 addition & 1 deletion test/document.test.js
Expand Up @@ -7860,7 +7860,7 @@ describe('document', function() {
});
});

it('allows saving an unchanged document if populated path is null (gh-8018)', function() {
it('allows saving an unchanged document if required populated path is null (gh-8018)', function() {
const schema = Schema({ test: String });
const schema2 = Schema({
keyToPopulate: {
Expand Down
4 changes: 4 additions & 0 deletions test/es-next/virtuals.test.es6.js
Expand Up @@ -158,6 +158,10 @@ describe('Virtuals', function() {
const User = mongoose.model('User', userSchema);
const BlogPost = mongoose.model('BlogPost', blogPostSchema);

// acquit:ignore:start
await BlogPost.deleteMany({});
await User.deleteMany({});
// acquit:ignore:end
await BlogPost.create({ title: 'Introduction to Mongoose', authorId: 1 });
await User.create({ _id: 1, email: 'test@gmail.com' });

Expand Down

0 comments on commit 01b182e

Please sign in to comment.