17
17
18
18
import java .io .IOException ;
19
19
import java .util .ArrayList ;
20
+ import java .util .Arrays ;
20
21
import java .util .Collections ;
21
22
import java .util .HashMap ;
22
23
import java .util .HashSet ;
27
28
import java .util .regex .Pattern ;
28
29
import java .util .stream .Collectors ;
29
30
31
+ import org .apache .commons .lang3 .StringUtils ;
30
32
import org .elasticsearch .client .indices .GetIndexResponse ;
31
33
import org .elasticsearch .client .indices .IndexTemplateMetaData ;
32
34
import org .elasticsearch .cluster .metadata .MappingMetaData ;
@@ -53,6 +55,9 @@ public final class ElasticMappingUpdater
53
55
private static final String MAPPING_DYNAMIC_TEMPLATES_KEY = "dynamic_templates" ;
54
56
private static final String MAPPING_TYPE_KEY = "type" ;
55
57
58
+ private static final Set <String > UNSUPPORTED_PARAMS = Collections .unmodifiableSet (
59
+ new HashSet <>(Arrays .asList ("doc_values" , "store" )));
60
+
56
61
private final ObjectMapper objectMapper ;
57
62
private final ElasticRequestHandler elasticRequestHandler ;
58
63
private final boolean dryRun ;
@@ -212,43 +217,83 @@ private void updateIndexesForTemplate(final IndexTemplateMetaData template)
212
217
private static boolean isMappingChangeSafe (
213
218
final Map <String , Object > templateMapping ,
214
219
final Map <String , Object > indexMapping ,
215
- final Set <String > allowedFieldDifferences
220
+ final Set <String > allowedFieldDifferences ,
221
+ final Set <String > unSupportedFieldDifferences
216
222
)
217
223
throws JsonProcessingException
218
224
{
219
225
final Map <String , Object > ftemplateMapping = FlatMapUtil .flatten (templateMapping );
220
226
final Map <String , Object > findexMapping = FlatMapUtil .flatten (indexMapping );
221
227
final MapDifference <String , Object > diff = Maps .difference (ftemplateMapping , findexMapping );
222
228
final Map <String , ValueDifference <Object >> entriesDiffering = diff .entriesDiffering ();
229
+ boolean safeChangesOnly ;
223
230
if (entriesDiffering .isEmpty ()) {
224
- return true ;
231
+ safeChangesOnly = true ;
225
232
} else {
226
233
// Elasticsearch would throw IllegalArgumentException if any such
227
234
// change is included in the index mapping updates
228
235
entriesDiffering .forEach ((key , value ) -> {
229
236
LOGGER .warn ("Unsupported mapping change : {} - current: {} target: {}" ,
230
237
key , value .rightValue (), value .leftValue ());
231
- allowedFieldDifferences .remove (getFieldName (key ));
238
+ if (key .contains (MAPPING_PROPS_KEY ))
239
+ {
240
+ // nested field
241
+ unSupportedFieldDifferences .add (key );
242
+ }
243
+ else
244
+ {
245
+ allowedFieldDifferences .remove (getFieldName (key ));
246
+ }
232
247
});
233
- return false ;
248
+ safeChangesOnly = false ;
249
+ }
250
+ final Set <String > unsupportedParamChanges = new HashSet <>();
251
+ final Map <String , Object > entriesOnlyInIndex = diff .entriesOnlyOnRight ();
252
+ // Field parameters that are currently set on a field in the index are now being removed
253
+ entriesOnlyInIndex .entrySet ().stream ()
254
+ .filter (e -> isUnsupportedParam (e .getKey ()))
255
+ .forEach (e -> {
256
+ LOGGER .warn ("Unsupported mapping change : field parameter being removed : {}:{}" , e .getKey (), e .getValue ());
257
+ unsupportedParamChanges .add (e .getKey ());
258
+ }
259
+ );
260
+ if (!unsupportedParamChanges .isEmpty ())
261
+ {
262
+ unSupportedFieldDifferences .addAll (unsupportedParamChanges );
263
+ safeChangesOnly = false ;
234
264
}
265
+ return safeChangesOnly ;
266
+ }
267
+
268
+ private static boolean isUnsupportedParam (final String fieldPath )
269
+ {
270
+ final String paramName = getParamName (fieldPath );
271
+ return UNSUPPORTED_PARAMS .contains (paramName );
235
272
}
236
273
237
274
private static String getFieldName (final String key )
238
275
{
239
276
return key .split (Pattern .quote ("/" ))[1 ];
240
277
}
241
278
279
+ private static String getParamName (final String key )
280
+ {
281
+ final String [] path = key .split (Pattern .quote ("/" ));
282
+ return path [path .length - 1 ];
283
+ }
284
+
242
285
private Map <String , Object > getMappingChanges (final Map <String , Object > templateMapping , final Map <String , Object > indexMapping )
243
286
throws JsonProcessingException
244
287
{
245
288
final Map <String , Object > mappingsChanges = new HashMap <>();
246
289
final MapDifference <String , Object > diff = Maps .difference (templateMapping , indexMapping );
247
290
final Map <String , ValueDifference <Object >> entriesDiffering = diff .entriesDiffering ();
248
291
final Set <String > allowedFieldDifferences = new HashSet <>(entriesDiffering .keySet ());
292
+ final Set <String > unSupportedFieldDifferences = new HashSet <>();
249
293
250
294
boolean unsupportedObjectChanges = false ;
251
295
if (!entriesDiffering .isEmpty ()) {
296
+ // Template has mapping changes to existing properties
252
297
LOGGER .info ("--Differences between template and index mapping--" );
253
298
entriesDiffering .forEach ((key , value ) -> LOGGER .info (" {} - current: {} target: {}" ,
254
299
key , value .rightValue (), value .leftValue ()));
@@ -286,7 +331,8 @@ private Map<String, Object> getMappingChanges(final Map<String, Object> template
286
331
}
287
332
}
288
333
289
- if (!isMappingChangeSafe (templateMapping , indexMapping , allowedFieldDifferences ) || unsupportedObjectChanges ) {
334
+ if (!isMappingChangeSafe (templateMapping , indexMapping , allowedFieldDifferences , unSupportedFieldDifferences )
335
+ || unsupportedObjectChanges ) {
290
336
LOGGER .warn ("Unsupported mapping changes will not be applied to the index." );
291
337
}
292
338
@@ -297,6 +343,15 @@ private Map<String, Object> getMappingChanges(final Map<String, Object> template
297
343
mappingsChanges .put (field , ((ValueDifference <?>) entriesDiffering .get (field )).leftValue ());
298
344
}
299
345
346
+ // Remove any unsupportedMappings
347
+ LOGGER .info ("{}" , unSupportedFieldDifferences .isEmpty ()
348
+ ? "No unsupported field changes."
349
+ : "Unsupported field changes that will not be included in the update: " + unSupportedFieldDifferences );
350
+ for (final String field : unSupportedFieldDifferences ) {
351
+ removeUnsupportedFieldChange (mappingsChanges , field );
352
+ }
353
+
354
+ // Add new properties defined in the template
300
355
final Map <String , Object > entriesOnlyInTemplate = diff .entriesOnlyOnLeft ();
301
356
final Set <String > newProperties = entriesOnlyInTemplate .keySet ();
302
357
LOGGER .info ("{}" , newProperties .isEmpty ()
@@ -314,4 +369,31 @@ private boolean hasDynamicTemplateChanged(List<Object> dynamicTemplatesInTemplat
314
369
return dynamicTemplatesInTemplate .retainAll (dynamicTemplatesInIndex );
315
370
}
316
371
372
+ @ SuppressWarnings ("unchecked" )
373
+ private void removeUnsupportedFieldChange (final Map <String , Object > mappingsChanges , final String fieldPath ) {
374
+ final List <String > path = Arrays .asList (StringUtils .split (fieldPath .trim (), "/" ));
375
+ final int size = path .size ();
376
+ int index = 0 ;
377
+ if (size == 2 )
378
+ {
379
+ // for a field path like, /LANGUAGE_CODES/properties/CODE/type, the 'fieldName' to be removed here is 'CODE'
380
+ // remove property with unsupported mapping change
381
+ final String fieldName = path .get (0 );
382
+ mappingsChanges .remove (fieldName );
383
+ }
384
+ else
385
+ {
386
+ while (index != size - 2 ) {
387
+ final int i = index ++;
388
+ final String currentFieldName = path .get (i );
389
+ final Object field = mappingsChanges .get (path .get (i ));
390
+ if (field instanceof Map <?, ?>) {
391
+ final Map <String , Object > currentField = (Map <String , Object >) field ;
392
+ final String subPath = fieldPath .substring (fieldPath .indexOf (currentFieldName ) + currentFieldName .length ());
393
+ removeUnsupportedFieldChange (currentField , subPath );
394
+ }
395
+ }
396
+ }
397
+ }
398
+
317
399
}
0 commit comments