20
20
import java .util .Arrays ;
21
21
import java .util .Collections ;
22
22
import java .util .HashMap ;
23
+ import java .util .LinkedHashMap ;
23
24
import java .util .HashSet ;
24
25
import java .util .List ;
25
26
import java .util .Map ;
26
- import java .util .Optional ;
27
+ import java .util .Map . Entry ;
27
28
import java .util .Set ;
28
29
import java .util .regex .Pattern ;
29
30
import java .util .stream .Collectors ;
31
+ import java .io .StringWriter ;
30
32
31
33
import org .apache .commons .lang3 .StringUtils ;
32
- import org .opensearch .client .indices .GetIndexResponse ;
33
- import org .opensearch .client .indices .IndexTemplateMetadata ;
34
- import org .opensearch .cluster .metadata .MappingMetadata ;
35
34
import org .slf4j .Logger ;
36
35
import org .slf4j .LoggerFactory ;
36
+ import org .opensearch .client .json .JsonpSerializable ;
37
+ import org .opensearch .client .json .jackson .JacksonJsonpGenerator ;
38
+ import org .opensearch .client .json .jackson .JacksonJsonpMapper ;
39
+ import org .opensearch .client .opensearch ._types .mapping .DynamicTemplate ;
40
+ import org .opensearch .client .opensearch ._types .mapping .TypeMapping ;
41
+ import org .opensearch .client .opensearch .indices .TemplateMapping ;
37
42
38
43
import com .fasterxml .jackson .annotation .PropertyAccessor ;
39
44
import com .fasterxml .jackson .annotation .JsonAutoDetect .Visibility ;
45
+ import com .fasterxml .jackson .core .JsonFactory ;
40
46
import com .fasterxml .jackson .core .JsonProcessingException ;
47
+ import com .fasterxml .jackson .core .type .TypeReference ;
41
48
import com .fasterxml .jackson .databind .ObjectMapper ;
42
49
import com .github .cafdataprocessing .elastic .tools .exceptions .GetIndexException ;
43
50
import com .github .cafdataprocessing .elastic .tools .exceptions .GetTemplatesException ;
@@ -55,6 +62,8 @@ public final class ElasticMappingUpdater
55
62
private static final String MAPPING_DYNAMIC_TEMPLATES_KEY = "dynamic_templates" ;
56
63
private static final String MAPPING_TYPE_KEY = "type" ;
57
64
65
+ private final ObjectMapper mapper = new ObjectMapper ();
66
+
58
67
private static final Set <String > MODIFIABLE_PROPERTIES = Collections .unmodifiableSet (
59
68
new HashSet <>(Arrays .asList (
60
69
"boost" ,
@@ -135,66 +144,53 @@ private ElasticMappingUpdater(
135
144
private void updateIndexes ()
136
145
throws IOException , GetIndexException , GetTemplatesException , UnexpectedResponseException
137
146
{
138
- final List <IndexTemplateMetadata > templates = elasticRequestHandler .getTemplates ();
139
- LOGGER .info ("Templates found in Elasticsearch: {}" ,
140
- templates .stream ().map (template -> template .name ()).collect (Collectors .toList ()));
141
- for (final IndexTemplateMetadata template : templates ) {
142
- updateIndexesForTemplate (template );
147
+ final Map <String , TemplateMapping > templates = elasticRequestHandler .getTemplates ();
148
+ LOGGER .info ("Templates found in Elasticsearch: {}" , templates .keySet ());
149
+ for (final Entry <String , TemplateMapping > template : templates .entrySet ()) {
150
+ updateIndexesForTemplate (template .getKey (), template .getValue ());
143
151
}
144
152
}
145
153
146
- private void updateIndexesForTemplate (final IndexTemplateMetadata template )
147
- throws IOException , GetIndexException , GetTemplatesException , UnexpectedResponseException
154
+ private void updateIndexesForTemplate (final String templateName , final TemplateMapping template )
155
+ throws IOException , GetIndexException , UnexpectedResponseException
148
156
{
149
- final String templateName = template .name ();
150
157
LOGGER .info ("---- Analyzing indexes matching template '{}' ----" , templateName );
151
158
152
- final List <String > patterns = template .patterns ();
159
+ final List <String > patterns = template .indexPatterns ();
153
160
154
- final MappingMetadata mapping = template .mappings ();
161
+ final TypeMapping mapping = template .mappings ();
155
162
if (mapping == null ) {
156
163
LOGGER .info ("No mappings in template '{}'. Indexes for this template will not be updated." , templateName );
157
164
return ;
158
165
}
159
166
160
- final Map <String , Object > templateTypeMappings = mapping .getSourceAsMap ();
161
-
162
- final Object templateProperties = Optional
163
- .ofNullable (templateTypeMappings .get (MAPPING_PROPS_KEY ))
164
- .orElseGet (Collections ::emptyMap );
167
+ final Map <String , Object > templateProperties = getObjectAsHashMap (mapping .properties ());
165
168
166
169
// Find all indices that match template patterns
167
170
final List <String > indexes = elasticRequestHandler .getIndexNames (patterns );
168
171
LOGGER .info ("Found {} index(es) that match template '{}'" , indexes .size (), templateName );
169
172
for (final String indexName : indexes ) {
170
- GetIndexResponse getIndexResponse = elasticRequestHandler .getIndex (indexName );
171
- MappingMetadata indexMappings = getIndexResponse .getMappings ().get (indexName );
172
- Map <String , Object > indexTypeMappings = indexMappings .getSourceAsMap ();
173
+ final TypeMapping indexMappings = elasticRequestHandler .getIndexMapping (indexName );
174
+ final Map <String , Object > indexProperties = getObjectAsHashMap (indexMappings .properties ());
173
175
174
176
LOGGER .info ("Comparing index mapping for '{}'" , indexName );
175
177
176
- final Object indexProperties = Optional
177
- .ofNullable (indexTypeMappings .get (MAPPING_PROPS_KEY ))
178
- .orElseGet (Collections ::emptyMap );
179
-
180
- @ SuppressWarnings ("unchecked" )
181
- final Map <String , Object > mappingsChanges = getMappingChanges (
182
- (Map <String , Object >) templateProperties ,
183
- (Map <String , Object >) indexProperties );
178
+ final Map <String , Object > mappingsChanges = getMappingChanges (templateProperties , indexProperties );
184
179
185
180
final Map <String , Object > mappingsRequest = new HashMap <>();
186
181
mappingsRequest .put (MAPPING_PROPS_KEY , mappingsChanges );
187
182
188
183
// Add all dynamic_templates in template to index mapping
189
- @ SuppressWarnings ("unchecked" )
190
- final List <Object > dynamicTemplatesInTemplate = (List <Object >) Optional
191
- .ofNullable (templateTypeMappings .get (MAPPING_DYNAMIC_TEMPLATES_KEY ))
192
- .orElseGet (Collections ::emptyList ); // Empty list will clear all existing dynamic_templates in index mapping
184
+ // Empty list will clear all existing dynamic_templates in index mapping
185
+ final List <Object > dynamicTemplatesInTemplate = new ArrayList <>();
186
+ for (final Map <String , DynamicTemplate > t : mapping .dynamicTemplates ()) {
187
+ dynamicTemplatesInTemplate .add (getObjectAsHashMap (t ));
188
+ }
193
189
194
- @ SuppressWarnings ( "unchecked" )
195
- final List < Object > dynamicTemplatesInIndex = ( List < Object >) Optional
196
- . ofNullable ( indexTypeMappings . get ( MAPPING_DYNAMIC_TEMPLATES_KEY ))
197
- . orElseGet ( Collections :: emptyList );
190
+ final List < Object > dynamicTemplatesInIndex = new ArrayList <>();
191
+ for ( final Map < String , DynamicTemplate > t : indexMappings . dynamicTemplates ()) {
192
+ dynamicTemplatesInIndex . add ( getObjectAsHashMap ( t ));
193
+ }
198
194
199
195
final List <Object > dynamicTemplatesUpdates = new ArrayList <>(dynamicTemplatesInTemplate );
200
196
@@ -353,8 +349,8 @@ private Map<String, Object> getMappingChanges(final Map<String, Object> template
353
349
// Check if 'type' has changed for object/nested properties
354
350
final Map <String , ValueDifference <Object >> typeDifferences = entriesDiffering .entrySet ().stream ()
355
351
.filter (e -> ((Map <?, ?>) (e .getValue ().leftValue ())).containsKey (MAPPING_PROPS_KEY )
356
- && (((Map <?, ?>) (e .getValue ().leftValue ())).containsKey (MAPPING_TYPE_KEY )
357
- || ((Map <?, ?>) (e .getValue ().rightValue ())).containsKey (MAPPING_TYPE_KEY )))
352
+ && (! ((Map <?, ?>) (e .getValue ().leftValue ())).get (MAPPING_TYPE_KEY ). equals ( "object" )
353
+ || ! ((Map <?, ?>) (e .getValue ().rightValue ())).get (MAPPING_TYPE_KEY ). equals ( "object" )))
358
354
.collect (Collectors .toMap (e -> e .getKey (), e -> e .getValue ()));
359
355
360
356
if (!typeDifferences .isEmpty ()) {
@@ -406,7 +402,7 @@ private Map<String, Object> getMappingChanges(final Map<String, Object> template
406
402
return mappingsChanges ;
407
403
}
408
404
409
- private boolean hasDynamicTemplateChanged (List <Object > dynamicTemplatesInTemplate , List <Object > dynamicTemplatesInIndex )
405
+ private boolean hasDynamicTemplateChanged (final List <Object > dynamicTemplatesInTemplate , final List <Object > dynamicTemplatesInIndex )
410
406
{
411
407
if (dynamicTemplatesInTemplate .size () != dynamicTemplatesInIndex .size ()) {
412
408
return true ;
@@ -451,4 +447,22 @@ private void removeUnsupportedFieldChange(final Map<String, Object> mappingsChan
451
447
}
452
448
}
453
449
450
+ private Map <String ,Object > getObjectAsHashMap (final Map <String , ? extends JsonpSerializable > obj ) throws JsonProcessingException , IOException
451
+ {
452
+ final Map <String , Object > mapFromString = new LinkedHashMap <>();
453
+ for (final Entry <String , ? extends JsonpSerializable > val : obj .entrySet ()) {
454
+ final String result = "{\" " + val .getKey () + "\" :" + getStringFromObject (val .getValue ()) + "}" ;
455
+ mapFromString .putAll (mapper .readValue (result , new TypeReference <Map <String , Object >>(){}));
456
+ }
457
+ return mapFromString ;
458
+ }
459
+
460
+ private String getStringFromObject (final JsonpSerializable value ) throws IOException
461
+ {
462
+ final StringWriter writer = new StringWriter ();
463
+ try (final JacksonJsonpGenerator generator = new JacksonJsonpGenerator (new JsonFactory ().createGenerator (writer ))) {
464
+ value .serialize (generator , new JacksonJsonpMapper ());
465
+ }
466
+ return writer .toString ();
467
+ }
454
468
}
0 commit comments