@@ -2721,12 +2721,33 @@ function _getPathsToValidate(doc, pathsToValidate, pathsToSkip, isNestedValidate
27212721 function addToPaths ( p ) { paths . add ( p ) ; }
27222722
27232723 if ( ! isNestedValidate ) {
2724- // If we're validating a subdocument, all this logic will run anyway on the top-level document, so skip for subdocuments
2725- const subdocs = doc . $getAllSubdocs ( { useCache : true } ) ;
2724+ // If we're validating a subdocument, all this logic will run anyway on the top-level document, so skip for subdocuments.
2725+ // But only run for top-level subdocuments, because we're looking for subdocuments that are not modified at top-level but
2726+ // have a modified path. If that is the case, we will run validation on the top-level subdocument, and via that run validation
2727+ // on any subdocuments down to the modified path.
2728+ const topLevelSubdocs = [ ] ;
2729+ for ( const path of Object . keys ( doc . $__schema . paths ) ) {
2730+ const schemaType = doc . $__schema . path ( path ) ;
2731+ if ( schemaType . $isSingleNested ) {
2732+ const subdoc = doc . $get ( path ) ;
2733+ if ( subdoc ) {
2734+ topLevelSubdocs . push ( subdoc ) ;
2735+ }
2736+ } else if ( schemaType . $isMongooseDocumentArray ) {
2737+ const arr = doc . $get ( path ) ;
2738+ if ( arr && arr . length ) {
2739+ for ( const subdoc of arr ) {
2740+ if ( subdoc ) {
2741+ topLevelSubdocs . push ( subdoc ) ;
2742+ }
2743+ }
2744+ }
2745+ }
2746+ }
27262747 const modifiedPaths = doc . modifiedPaths ( ) ;
2727- for ( const subdoc of subdocs ) {
2748+ for ( const subdoc of topLevelSubdocs ) {
27282749 if ( subdoc . $basePath ) {
2729- const fullPathToSubdoc = subdoc . $isSingleNested ? subdoc . $ __pathRelativeToParent( ) : subdoc . $__fullPathWithIndexes ( ) ;
2750+ const fullPathToSubdoc = subdoc . $__pathRelativeToParent ( ) ;
27302751
27312752 // Remove child paths for now, because we'll be validating the whole
27322753 // subdoc.
@@ -2736,11 +2757,12 @@ function _getPathsToValidate(doc, pathsToValidate, pathsToSkip, isNestedValidate
27362757 paths . delete ( fullPathToSubdoc + '.' + modifiedPath ) ;
27372758 }
27382759
2760+ const subdocParent = subdoc . $parent ( ) ;
27392761 if ( doc . $isModified ( fullPathToSubdoc , null , modifiedPaths ) &&
27402762 // Avoid using isDirectModified() here because that does additional checks on whether the parent path
27412763 // is direct modified, which can cause performance issues re: gh-14897
2742- ! doc . $__ . activePaths . getStatePaths ( 'modify' ) . hasOwnProperty ( fullPathToSubdoc ) &&
2743- ! doc . $isDefault ( fullPathToSubdoc ) ) {
2764+ ! subdocParent . $__ . activePaths . getStatePaths ( 'modify' ) . hasOwnProperty ( fullPathToSubdoc ) &&
2765+ ! subdocParent . $isDefault ( fullPathToSubdoc ) ) {
27442766 paths . add ( fullPathToSubdoc ) ;
27452767
27462768 if ( doc . $__ . pathsToScopes == null ) {
0 commit comments