2121
2222import  org .apache .lucene .document .Field ;
2323import  org .apache .lucene .index .IndexableField ;
24+ import  org .apache .lucene .search .Query ;
2425import  org .elasticsearch .ElasticsearchParseException ;
2526import  org .elasticsearch .Version ;
2627import  org .elasticsearch .common .Strings ;
2930import  org .elasticsearch .common .time .DateFormatter ;
3031import  org .elasticsearch .common .xcontent .LoggingDeprecationHandler ;
3132import  org .elasticsearch .common .xcontent .NamedXContentRegistry ;
33+ import  org .elasticsearch .common .xcontent .XContentBuilder ;
3234import  org .elasticsearch .common .xcontent .XContentHelper ;
3335import  org .elasticsearch .common .xcontent .XContentParser ;
3436import  org .elasticsearch .common .xcontent .XContentType ;
3537import  org .elasticsearch .index .mapper .DynamicTemplate .XContentFieldType ;
38+ import  org .elasticsearch .index .query .QueryShardContext ;
39+ import  org .elasticsearch .search .lookup .SearchLookup ;
3640
3741import  java .io .IOException ;
3842import  java .time .format .DateTimeParseException ;
3943import  java .util .ArrayList ;
4044import  java .util .Collections ;
45+ import  java .util .Comparator ;
4146import  java .util .Iterator ;
4247import  java .util .List ;
4348import  java .util .function .Function ;
@@ -209,7 +214,7 @@ static Mapping createDynamicUpdate(Mapping mapping, DocumentMapper docMapper, Li
209214        // We build a mapping by first sorting the mappers, so that all mappers containing a common prefix 
210215        // will be processed in a contiguous block. When the prefix is no longer seen, we pop the extra elements 
211216        // off the stack, merging them upwards into the existing mappers. 
212-         Collections .sort (dynamicMappers ,  (Mapper   o1 ,  Mapper   o2 ) ->  o1 . name (). compareTo ( o2 . name () ));
217+         dynamicMappers .sort (Comparator . comparing (Mapper :: name ));
213218        Iterator <Mapper > dynamicMapperItr  = dynamicMappers .iterator ();
214219        List <ObjectMapper > parentMappers  = new  ArrayList <>();
215220        Mapper  firstUpdate  = dynamicMapperItr .next ();
@@ -814,14 +819,14 @@ private static Tuple<Integer, ObjectMapper> getDynamicParentMapper(ParseContext
814819        int  pathsAdded  = 0 ;
815820        ObjectMapper  parent  = mapper ;
816821        for  (int  i  = 0 ; i  < paths .length -1 ; i ++) {
817-         String  currentPath  = context .path ().pathAsText (paths [i ]);
818-         Mapper  existingFieldMapper  = context .docMapper ().mappers ().getMapper (currentPath );
819-         if  (existingFieldMapper  != null ) {
820-             throw  new  MapperParsingException (
822+              String  currentPath  = context .path ().pathAsText (paths [i ]);
823+              Mapper  existingFieldMapper  = context .docMapper ().mappers ().getMapper (currentPath );
824+              if  (existingFieldMapper  != null ) {
825+                  throw  new  MapperParsingException (
821826                    "Could not dynamically add mapping for field [{}]. Existing mapping for [{}] must be of type object but found [{}]." ,
822827                    null , String .join ("." , paths ), currentPath , existingFieldMapper .typeName ());
823-         }
824-         mapper  = context .docMapper ().mappers ().objectMappers ().get (currentPath );
828+              }
829+              mapper  = context .docMapper ().mappers ().objectMappers ().get (currentPath );
825830            if  (mapper  == null ) {
826831                // One mapping is missing, check if we are allowed to create a dynamic one. 
827832                ObjectMapper .Dynamic  dynamic  = dynamicOrDefault (parent , context );
@@ -890,7 +895,7 @@ private static Mapper getMapper(final ParseContext context, ObjectMapper objectM
890895
891896        for  (int  i  = 0 ; i  < subfields .length  - 1 ; ++i ) {
892897            mapper  = objectMapper .getMapper (subfields [i ]);
893-             if  (mapper  ==  null  || ( mapper   instanceof  ObjectMapper )  == false ) {
898+             if  (mapper  instanceof  ObjectMapper  == false ) {
894899                return  null ;
895900            }
896901            objectMapper  = (ObjectMapper )mapper ;
@@ -900,6 +905,93 @@ private static Mapper getMapper(final ParseContext context, ObjectMapper objectM
900905                        + mapper .name () + "]" );
901906            }
902907        }
903-         return  objectMapper .getMapper (subfields [subfields .length  - 1 ]);
908+         String  leafName  = subfields [subfields .length  - 1 ];
909+         mapper  = objectMapper .getMapper (leafName );
910+         if  (mapper  != null ) {
911+             return  mapper ;
912+         }
913+         //concrete fields take the precedence over runtime fields when parsing documents, though when a field is defined as runtime field 
914+         //only, and not under properties, it is ignored when it is sent as part of _source 
915+         RuntimeFieldType  runtimeFieldType  = context .docMapper ().mapping ().root .getRuntimeFieldType (fieldPath );
916+         if  (runtimeFieldType  != null ) {
917+             return  new  NoOpFieldMapper (leafName , runtimeFieldType );
918+         }
919+         return  null ;
920+     }
921+ 
922+     private  static  class  NoOpFieldMapper  extends  FieldMapper  {
923+         NoOpFieldMapper (String  simpleName , RuntimeFieldType  runtimeField ) {
924+             super (simpleName , new  MappedFieldType (runtimeField .name (), false , false , false , TextSearchInfo .NONE , Collections .emptyMap ()) {
925+                 @ Override 
926+                 public  ValueFetcher  valueFetcher (QueryShardContext  context , SearchLookup  searchLookup , String  format ) {
927+                     throw  new  UnsupportedOperationException ();
928+                 }
929+ 
930+                 @ Override 
931+                 public  String  typeName () {
932+                     throw  new  UnsupportedOperationException ();
933+                 }
934+ 
935+                 @ Override 
936+                 public  Query  termQuery (Object  value , QueryShardContext  context ) {
937+                     throw  new  UnsupportedOperationException ();
938+                 }
939+             }, MultiFields .empty (), CopyTo .empty ());
940+         }
941+ 
942+         @ Override 
943+         protected  void  parseCreateField (ParseContext  context ) throws  IOException  {
944+             //field defined as runtime field, don't index anything 
945+         }
946+ 
947+         @ Override 
948+         public  String  name () {
949+             throw  new  UnsupportedOperationException ();
950+         }
951+ 
952+         @ Override 
953+         public  String  typeName () {
954+             throw  new  UnsupportedOperationException ();
955+         }
956+ 
957+         @ Override 
958+         public  MappedFieldType  fieldType () {
959+             throw  new  UnsupportedOperationException ();
960+         }
961+ 
962+         @ Override 
963+         public  MultiFields  multiFields () {
964+             throw  new  UnsupportedOperationException ();
965+         }
966+ 
967+         @ Override 
968+         public  Iterator <Mapper > iterator () {
969+             throw  new  UnsupportedOperationException ();
970+         }
971+ 
972+         @ Override 
973+         protected  void  doValidate (MappingLookup  mappers ) {
974+             throw  new  UnsupportedOperationException ();
975+         }
976+ 
977+         @ Override 
978+         protected  void  checkIncomingMergeType (FieldMapper  mergeWith ) {
979+             throw  new  UnsupportedOperationException ();
980+         }
981+ 
982+         @ Override 
983+         public  Builder  getMergeBuilder () {
984+             throw  new  UnsupportedOperationException ();
985+         }
986+ 
987+         @ Override 
988+         public  XContentBuilder  toXContent (XContentBuilder  builder , Params  params ) throws  IOException  {
989+             throw  new  UnsupportedOperationException ();
990+         }
991+ 
992+         @ Override 
993+         protected  String  contentType () {
994+             throw  new  UnsupportedOperationException ();
995+         }
904996    }
905997}
0 commit comments