21
21
22
22
import org .apache .lucene .document .Field ;
23
23
import org .apache .lucene .index .IndexableField ;
24
+ import org .apache .lucene .search .Query ;
24
25
import org .elasticsearch .ElasticsearchParseException ;
25
26
import org .elasticsearch .Version ;
26
27
import org .elasticsearch .common .Strings ;
29
30
import org .elasticsearch .common .time .DateFormatter ;
30
31
import org .elasticsearch .common .xcontent .LoggingDeprecationHandler ;
31
32
import org .elasticsearch .common .xcontent .NamedXContentRegistry ;
33
+ import org .elasticsearch .common .xcontent .XContentBuilder ;
32
34
import org .elasticsearch .common .xcontent .XContentHelper ;
33
35
import org .elasticsearch .common .xcontent .XContentParser ;
34
36
import org .elasticsearch .common .xcontent .XContentType ;
35
37
import org .elasticsearch .index .mapper .DynamicTemplate .XContentFieldType ;
38
+ import org .elasticsearch .index .query .QueryShardContext ;
39
+ import org .elasticsearch .search .lookup .SearchLookup ;
36
40
37
41
import java .io .IOException ;
38
42
import java .time .format .DateTimeParseException ;
39
43
import java .util .ArrayList ;
40
44
import java .util .Collections ;
45
+ import java .util .Comparator ;
41
46
import java .util .Iterator ;
42
47
import java .util .List ;
43
48
import java .util .Objects ;
@@ -224,7 +229,7 @@ static Mapping createDynamicUpdate(Mapping mapping, DocumentMapper docMapper, Li
224
229
// We build a mapping by first sorting the mappers, so that all mappers containing a common prefix
225
230
// will be processed in a contiguous block. When the prefix is no longer seen, we pop the extra elements
226
231
// off the stack, merging them upwards into the existing mappers.
227
- Collections .sort (dynamicMappers , (Mapper o1 , Mapper o2 ) -> o1 . name (). compareTo ( o2 . name () ));
232
+ dynamicMappers .sort (Comparator . comparing (Mapper :: name ));
228
233
Iterator <Mapper > dynamicMapperItr = dynamicMappers .iterator ();
229
234
List <ObjectMapper > parentMappers = new ArrayList <>();
230
235
Mapper firstUpdate = dynamicMapperItr .next ();
@@ -829,14 +834,14 @@ private static Tuple<Integer, ObjectMapper> getDynamicParentMapper(ParseContext
829
834
int pathsAdded = 0 ;
830
835
ObjectMapper parent = mapper ;
831
836
for (int i = 0 ; i < paths .length -1 ; i ++) {
832
- String currentPath = context .path ().pathAsText (paths [i ]);
833
- Mapper existingFieldMapper = context .docMapper ().mappers ().getMapper (currentPath );
834
- if (existingFieldMapper != null ) {
835
- throw new MapperParsingException (
837
+ String currentPath = context .path ().pathAsText (paths [i ]);
838
+ Mapper existingFieldMapper = context .docMapper ().mappers ().getMapper (currentPath );
839
+ if (existingFieldMapper != null ) {
840
+ throw new MapperParsingException (
836
841
"Could not dynamically add mapping for field [{}]. Existing mapping for [{}] must be of type object but found [{}]." ,
837
842
null , String .join ("." , paths ), currentPath , existingFieldMapper .typeName ());
838
- }
839
- mapper = context .docMapper ().mappers ().objectMappers ().get (currentPath );
843
+ }
844
+ mapper = context .docMapper ().mappers ().objectMappers ().get (currentPath );
840
845
if (mapper == null ) {
841
846
// One mapping is missing, check if we are allowed to create a dynamic one.
842
847
ObjectMapper .Dynamic dynamic = dynamicOrDefault (parent , context );
@@ -905,7 +910,7 @@ private static Mapper getMapper(final ParseContext context, ObjectMapper objectM
905
910
906
911
for (int i = 0 ; i < subfields .length - 1 ; ++i ) {
907
912
mapper = objectMapper .getMapper (subfields [i ]);
908
- if (mapper == null || ( mapper instanceof ObjectMapper ) == false ) {
913
+ if (mapper instanceof ObjectMapper == false ) {
909
914
return null ;
910
915
}
911
916
objectMapper = (ObjectMapper )mapper ;
@@ -915,6 +920,93 @@ private static Mapper getMapper(final ParseContext context, ObjectMapper objectM
915
920
+ mapper .name () + "]" );
916
921
}
917
922
}
918
- return objectMapper .getMapper (subfields [subfields .length - 1 ]);
923
+ String leafName = subfields [subfields .length - 1 ];
924
+ mapper = objectMapper .getMapper (leafName );
925
+ if (mapper != null ) {
926
+ return mapper ;
927
+ }
928
+ //concrete fields take the precedence over runtime fields when parsing documents, though when a field is defined as runtime field
929
+ //only, and not under properties, it is ignored when it is sent as part of _source
930
+ RuntimeFieldType runtimeFieldType = context .docMapper ().mapping ().root .getRuntimeFieldType (fieldPath );
931
+ if (runtimeFieldType != null ) {
932
+ return new NoOpFieldMapper (leafName , runtimeFieldType );
933
+ }
934
+ return null ;
935
+ }
936
+
937
+ private static class NoOpFieldMapper extends FieldMapper {
938
+ NoOpFieldMapper (String simpleName , RuntimeFieldType runtimeField ) {
939
+ super (simpleName , new MappedFieldType (runtimeField .name (), false , false , false , TextSearchInfo .NONE , Collections .emptyMap ()) {
940
+ @ Override
941
+ public ValueFetcher valueFetcher (QueryShardContext context , SearchLookup searchLookup , String format ) {
942
+ throw new UnsupportedOperationException ();
943
+ }
944
+
945
+ @ Override
946
+ public String typeName () {
947
+ throw new UnsupportedOperationException ();
948
+ }
949
+
950
+ @ Override
951
+ public Query termQuery (Object value , QueryShardContext context ) {
952
+ throw new UnsupportedOperationException ();
953
+ }
954
+ }, MultiFields .empty (), CopyTo .empty ());
955
+ }
956
+
957
+ @ Override
958
+ protected void parseCreateField (ParseContext context ) throws IOException {
959
+ //field defined as runtime field, don't index anything
960
+ }
961
+
962
+ @ Override
963
+ public String name () {
964
+ throw new UnsupportedOperationException ();
965
+ }
966
+
967
+ @ Override
968
+ public String typeName () {
969
+ throw new UnsupportedOperationException ();
970
+ }
971
+
972
+ @ Override
973
+ public MappedFieldType fieldType () {
974
+ throw new UnsupportedOperationException ();
975
+ }
976
+
977
+ @ Override
978
+ public MultiFields multiFields () {
979
+ throw new UnsupportedOperationException ();
980
+ }
981
+
982
+ @ Override
983
+ public Iterator <Mapper > iterator () {
984
+ throw new UnsupportedOperationException ();
985
+ }
986
+
987
+ @ Override
988
+ protected void doValidate (MappingLookup mappers ) {
989
+ throw new UnsupportedOperationException ();
990
+ }
991
+
992
+ @ Override
993
+ protected void checkIncomingMergeType (FieldMapper mergeWith ) {
994
+ throw new UnsupportedOperationException ();
995
+ }
996
+
997
+ @ Override
998
+ public Builder getMergeBuilder () {
999
+ throw new UnsupportedOperationException ();
1000
+ }
1001
+
1002
+ @ Override
1003
+ public XContentBuilder toXContent (XContentBuilder builder , Params params ) throws IOException {
1004
+ throw new UnsupportedOperationException ();
1005
+ }
1006
+
1007
+ @ Override
1008
+ protected String contentType () {
1009
+ throw new UnsupportedOperationException ();
1010
+ }
919
1011
}
920
1012
}
0 commit comments