9
9
package org .elasticsearch .index .mapper ;
10
10
11
11
import org .apache .lucene .index .LeafReader ;
12
+ import org .apache .lucene .util .BytesRef ;
12
13
import org .elasticsearch .ElasticsearchParseException ;
13
14
import org .elasticsearch .common .Explicit ;
14
15
import org .elasticsearch .common .logging .DeprecationCategory ;
15
16
import org .elasticsearch .common .logging .DeprecationLogger ;
16
17
import org .elasticsearch .common .xcontent .support .XContentMapValues ;
17
- import org .elasticsearch .core .CheckedConsumer ;
18
18
import org .elasticsearch .core .Nullable ;
19
19
import org .elasticsearch .index .IndexVersion ;
20
20
import org .elasticsearch .index .IndexVersions ;
32
32
import java .util .List ;
33
33
import java .util .Locale ;
34
34
import java .util .Map ;
35
+ import java .util .Objects ;
35
36
import java .util .TreeMap ;
36
37
import java .util .stream .Stream ;
37
38
@@ -74,7 +75,7 @@ DynamicFieldsBuilder getDynamicFieldsBuilder() {
74
75
* If no dynamic settings are explicitly configured, we default to {@link #TRUE}
75
76
*/
76
77
static Dynamic getRootDynamic (MappingLookup mappingLookup ) {
77
- ObjectMapper . Dynamic rootDynamic = mappingLookup .getMapping ().getRoot ().dynamic ;
78
+ Dynamic rootDynamic = mappingLookup .getMapping ().getRoot ().dynamic ;
78
79
return rootDynamic == null ? Defaults .DYNAMIC : rootDynamic ;
79
80
}
80
81
}
@@ -142,13 +143,13 @@ public final void addDynamic(String name, String prefix, Mapper mapper, Document
142
143
int firstDotIndex = name .indexOf ('.' );
143
144
String immediateChild = name .substring (0 , firstDotIndex );
144
145
String immediateChildFullName = prefix == null ? immediateChild : prefix + "." + immediateChild ;
145
- ObjectMapper . Builder parentBuilder = findObjectBuilder (immediateChildFullName , context );
146
+ Builder parentBuilder = findObjectBuilder (immediateChildFullName , context );
146
147
parentBuilder .addDynamic (name .substring (firstDotIndex + 1 ), immediateChildFullName , mapper , context );
147
148
add (parentBuilder );
148
149
}
149
150
}
150
151
151
- private static ObjectMapper . Builder findObjectBuilder (String fullName , DocumentParserContext context ) {
152
+ private static Builder findObjectBuilder (String fullName , DocumentParserContext context ) {
152
153
// does the object mapper already exist? if so, use that
153
154
ObjectMapper objectMapper = context .mappingLookup ().objectMappers ().get (fullName );
154
155
if (objectMapper != null ) {
@@ -215,7 +216,7 @@ public Mapper.Builder parse(String name, Map<String, Object> node, MappingParser
215
216
throws MapperParsingException {
216
217
parserContext .incrementMappingObjectDepth (); // throws MapperParsingException if depth limit is exceeded
217
218
Explicit <Boolean > subobjects = parseSubobjects (node );
218
- ObjectMapper . Builder builder = new Builder (name , subobjects );
219
+ Builder builder = new Builder (name , subobjects );
219
220
parseObjectFields (node , parserContext , builder );
220
221
parserContext .decrementMappingObjectDepth ();
221
222
return builder ;
@@ -237,7 +238,7 @@ protected static boolean parseObjectOrDocumentTypeProperties(
237
238
String fieldName ,
238
239
Object fieldNode ,
239
240
MappingParserContext parserContext ,
240
- ObjectMapper . Builder builder
241
+ Builder builder
241
242
) {
242
243
if (fieldName .equals ("dynamic" )) {
243
244
String value = fieldNode .toString ();
@@ -284,11 +285,7 @@ protected static Explicit<Boolean> parseSubobjects(Map<String, Object> node) {
284
285
return Defaults .SUBOBJECTS ;
285
286
}
286
287
287
- protected static void parseProperties (
288
- ObjectMapper .Builder objBuilder ,
289
- Map <String , Object > propsNode ,
290
- MappingParserContext parserContext
291
- ) {
288
+ protected static void parseProperties (Builder objBuilder , Map <String , Object > propsNode , MappingParserContext parserContext ) {
292
289
Iterator <Map .Entry <String , Object >> iterator = propsNode .entrySet ().iterator ();
293
290
while (iterator .hasNext ()) {
294
291
Map .Entry <String , Object > entry = iterator .next ();
@@ -347,7 +344,7 @@ protected static void parseProperties(
347
344
for (int i = fieldNameParts .length - 2 ; i >= 0 ; --i ) {
348
345
String intermediateObjectName = fieldNameParts [i ];
349
346
validateFieldName (intermediateObjectName , parserContext .indexVersionCreated ());
350
- ObjectMapper . Builder intermediate = new ObjectMapper . Builder (intermediateObjectName , Defaults .SUBOBJECTS );
347
+ Builder intermediate = new Builder (intermediateObjectName , Defaults .SUBOBJECTS );
351
348
intermediate .add (fieldBuilder );
352
349
fieldBuilder = intermediate ;
353
350
}
@@ -417,8 +414,8 @@ private static void validateFieldName(String fieldName, IndexVersion indexCreate
417
414
/**
418
415
* @return a Builder that will produce an empty ObjectMapper with the same configuration as this one
419
416
*/
420
- public ObjectMapper . Builder newBuilder (IndexVersion indexVersionCreated ) {
421
- ObjectMapper . Builder builder = new ObjectMapper . Builder (leafName (), subobjects );
417
+ public Builder newBuilder (IndexVersion indexVersionCreated ) {
418
+ Builder builder = new Builder (leafName (), subobjects );
422
419
builder .enabled = this .enabled ;
423
420
builder .dynamic = this .dynamic ;
424
421
return builder ;
@@ -507,7 +504,7 @@ protected record MergeResult(
507
504
Explicit <Boolean > enabled ,
508
505
Explicit <Boolean > subObjects ,
509
506
Explicit <Boolean > trackArraySource ,
510
- ObjectMapper . Dynamic dynamic ,
507
+ Dynamic dynamic ,
511
508
Map <String , Mapper > mappers
512
509
) {
513
510
static MergeResult build (ObjectMapper existing , ObjectMapper mergeWithObject , MapperMergeContext parentMergeContext ) {
@@ -789,9 +786,9 @@ public Stream<Map.Entry<String, StoredFieldLoader>> storedFieldLoaders() {
789
786
790
787
@ Override
791
788
public DocValuesLoader docValuesLoader (LeafReader leafReader , int [] docIdsInLeaf ) throws IOException {
792
- List <SourceLoader . SyntheticFieldLoader . DocValuesLoader > loaders = new ArrayList <>();
789
+ List <DocValuesLoader > loaders = new ArrayList <>();
793
790
for (SourceLoader .SyntheticFieldLoader field : fields ) {
794
- SourceLoader . SyntheticFieldLoader . DocValuesLoader loader = field .docValuesLoader (leafReader , docIdsInLeaf );
791
+ DocValuesLoader loader = field .docValuesLoader (leafReader , docIdsInLeaf );
795
792
if (loader != null ) {
796
793
loaders .add (loader );
797
794
}
@@ -803,7 +800,7 @@ public DocValuesLoader docValuesLoader(LeafReader leafReader, int[] docIdsInLeaf
803
800
}
804
801
805
802
private class ObjectDocValuesLoader implements DocValuesLoader {
806
- private final List <SourceLoader . SyntheticFieldLoader . DocValuesLoader > loaders ;
803
+ private final List <DocValuesLoader > loaders ;
807
804
808
805
private ObjectDocValuesLoader (List <DocValuesLoader > loaders ) {
809
806
this .loaders = loaders ;
@@ -812,7 +809,7 @@ private ObjectDocValuesLoader(List<DocValuesLoader> loaders) {
812
809
@ Override
813
810
public boolean advanceToDoc (int docId ) throws IOException {
814
811
boolean anyLeafHasDocValues = false ;
815
- for (SourceLoader . SyntheticFieldLoader . DocValuesLoader docValueLoader : loaders ) {
812
+ for (DocValuesLoader docValueLoader : loaders ) {
816
813
boolean leafHasValue = docValueLoader .advanceToDoc (docId );
817
814
anyLeafHasDocValues |= leafHasValue ;
818
815
}
@@ -848,18 +845,24 @@ public void write(XContentBuilder b) throws IOException {
848
845
849
846
if (ignoredValues != null && ignoredValues .isEmpty () == false ) {
850
847
// Use an ordered map between field names and writer functions, to order writing by field name.
851
- Map <String , CheckedConsumer < XContentBuilder , IOException > > orderedFields = new TreeMap <>();
848
+ Map <String , FieldWriter > orderedFields = new TreeMap <>();
852
849
for (IgnoredSourceFieldMapper .NameValue value : ignoredValues ) {
853
- orderedFields .put (value .name (), value ::write );
850
+ var existing = orderedFields .get (value .name ());
851
+ if (existing == null ) {
852
+ orderedFields .put (value .name (), new FieldWriter .IgnoredSource (value ));
853
+ } else if (existing instanceof FieldWriter .IgnoredSource isw ) {
854
+ isw .mergeWith (value );
855
+ }
854
856
}
855
857
for (SourceLoader .SyntheticFieldLoader field : fields ) {
856
858
if (field .hasValue ()) {
857
859
// Skip if the field source is stored separately, to avoid double-printing.
858
- orderedFields .putIfAbsent (field .fieldName (), field :: write );
860
+ orderedFields .computeIfAbsent (field .fieldName (), k -> new FieldWriter . FieldLoader ( field ) );
859
861
}
860
862
}
863
+
861
864
for (var writer : orderedFields .values ()) {
862
- writer .accept (b );
865
+ writer .writeTo (b );
863
866
}
864
867
ignoredValues = null ;
865
868
} else {
@@ -890,6 +893,42 @@ public boolean setIgnoredValues(Map<String, List<IgnoredSourceFieldMapper.NameVa
890
893
public String fieldName () {
891
894
return ObjectMapper .this .fullPath ();
892
895
}
896
+
897
+ interface FieldWriter {
898
+ void writeTo (XContentBuilder builder ) throws IOException ;
899
+
900
+ record FieldLoader (SourceLoader .SyntheticFieldLoader loader ) implements FieldWriter {
901
+ @ Override
902
+ public void writeTo (XContentBuilder builder ) throws IOException {
903
+ loader .write (builder );
904
+ }
905
+ }
906
+
907
+ class IgnoredSource implements FieldWriter {
908
+ private final String fieldName ;
909
+ private final String leafName ;
910
+ private final List <BytesRef > values ;
911
+
912
+ IgnoredSource (IgnoredSourceFieldMapper .NameValue initialValue ) {
913
+ this .fieldName = initialValue .name ();
914
+ this .leafName = initialValue .getFieldName ();
915
+ this .values = new ArrayList <>();
916
+ this .values .add (initialValue .value ());
917
+ }
918
+
919
+ @ Override
920
+ public void writeTo (XContentBuilder builder ) throws IOException {
921
+ XContentDataHelper .writeMerged (builder , leafName , values );
922
+ }
923
+
924
+ public FieldWriter mergeWith (IgnoredSourceFieldMapper .NameValue nameValue ) {
925
+ assert Objects .equals (nameValue .name (), fieldName ) : "IgnoredSource is merged with wrong field data" ;
926
+
927
+ values .add (nameValue .value ());
928
+ return this ;
929
+ }
930
+ }
931
+ }
893
932
}
894
933
895
934
protected boolean isRoot () {
0 commit comments