104104import static org .elasticsearch .cluster .metadata .MetadataCreateIndexService .buildIndexMetadata ;
105105import static org .elasticsearch .cluster .metadata .MetadataCreateIndexService .clusterStateCreateIndex ;
106106import static org .elasticsearch .cluster .metadata .MetadataCreateIndexService .getIndexNumberOfRoutingShards ;
107- import static org .elasticsearch .cluster .metadata .MetadataCreateIndexService .parseMappings ;
107+ import static org .elasticsearch .cluster .metadata .MetadataCreateIndexService .parseV1Mappings ;
108108import static org .elasticsearch .cluster .metadata .MetadataCreateIndexService .resolveAndValidateAliases ;
109109import static org .elasticsearch .cluster .shards .ClusterShardLimitIT .ShardCounts .forDataNodeCount ;
110110import static org .elasticsearch .index .IndexSettings .INDEX_SOFT_DELETES_SETTING ;
@@ -647,7 +647,7 @@ public void testParseMappingsAppliesDataFromTemplateAndRequest() throws Exceptio
647647 });
648648 request .mappings (singletonMap ("type" , createMapping ("mapping_from_request" , "text" ).string ()));
649649
650- Map <String , Map <String , Object >> parsedMappings = MetadataCreateIndexService .parseMappings (request .mappings (),
650+ Map <String , Map <String , Object >> parsedMappings = MetadataCreateIndexService .parseV1Mappings (request .mappings (),
651651 Collections .singletonList (convertMappings (templateMetadata .getMappings ())), NamedXContentRegistry .EMPTY );
652652
653653 assertThat (parsedMappings , hasKey ("type" ));
@@ -705,7 +705,7 @@ public void testRequestDataHavePriorityOverTemplateData() throws Exception {
705705 request .aliases (singleton (new Alias ("alias" ).searchRouting ("fromRequest" )));
706706 request .settings (Settings .builder ().put ("key1" , "requestValue" ).build ());
707707
708- Map <String , Map <String , Object >> parsedMappings = MetadataCreateIndexService .parseMappings (request .mappings (),
708+ Map <String , Map <String , Object >> parsedMappings = MetadataCreateIndexService .parseV1Mappings (request .mappings (),
709709 Collections .singletonList (convertMappings (templateMetadata .mappings ())), xContentRegistry ());
710710 List <AliasMetadata > resolvedAliases = resolveAndValidateAliases (request .index (), request .aliases (),
711711 MetadataIndexTemplateService .resolveAliases (Collections .singletonList (templateMetadata )),
@@ -878,7 +878,7 @@ public void testParseMappingsWithTypedTemplateAndTypelessIndexMapping() throws E
878878 }
879879 });
880880
881- Map <String , Map <String , Object >> mappings = parseMappings (singletonMap (MapperService .SINGLE_MAPPING_NAME , "{\" _doc\" :{}}" ),
881+ Map <String , Map <String , Object >> mappings = parseV1Mappings (singletonMap (MapperService .SINGLE_MAPPING_NAME , "{\" _doc\" :{}}" ),
882882 Collections .singletonList (convertMappings (templateMetadata .mappings ())), xContentRegistry ());
883883 assertThat (mappings , Matchers .hasKey (MapperService .SINGLE_MAPPING_NAME ));
884884 }
@@ -892,7 +892,7 @@ public void testParseMappingsWithTypedTemplate() throws Exception {
892892 ExceptionsHelper .reThrowIfNotNull (e );
893893 }
894894 });
895- Map <String , Map <String , Object >> mappings = parseMappings (emptyMap (),
895+ Map <String , Map <String , Object >> mappings = parseV1Mappings (emptyMap (),
896896 Collections .singletonList (convertMappings (templateMetadata .mappings ())), xContentRegistry ());
897897 assertThat (mappings , Matchers .hasKey ("type" ));
898898 }
@@ -905,7 +905,7 @@ public void testParseMappingsWithTypelessTemplate() throws Exception {
905905 ExceptionsHelper .reThrowIfNotNull (e );
906906 }
907907 });
908- Map <String , Map <String , Object >> mappings = parseMappings (emptyMap (),
908+ Map <String , Map <String , Object >> mappings = parseV1Mappings (emptyMap (),
909909 Collections .singletonList (convertMappings (templateMetadata .mappings ())), xContentRegistry ());
910910 assertThat (mappings , Matchers .hasKey (MapperService .SINGLE_MAPPING_NAME ));
911911 }
@@ -1001,6 +1001,69 @@ public void testValidateTranslogRetentionSettings() {
10011001 + "and [index.translog.retention.size] are deprecated and effectively ignored. They will be removed in a future version." );
10021002 }
10031003
1004+ @ SuppressWarnings ("unchecked" )
1005+ public void testMappingsMergingIsSmart () throws Exception {
1006+ Template ctt1 = new Template (null ,
1007+ new CompressedXContent ("{\" _doc\" :{\" _source\" :{\" enabled\" : false},\" _meta\" :{\" ct1\" :{\" ver\" : \" text\" }}," +
1008+ "\" properties\" :{\" foo\" :{\" type\" :\" text\" ,\" ignore_above\" :7,\" analyzer\" :\" english\" }}}}" ), null );
1009+ Template ctt2 = new Template (null ,
1010+ new CompressedXContent ("{\" _doc\" :{\" _meta\" :{\" ct1\" :{\" ver\" : \" keyword\" },\" ct2\" :\" potato\" }," +
1011+ "\" properties\" :{\" foo\" :{\" type\" :\" keyword\" ,\" ignore_above\" :13}}}}" ), null );
1012+
1013+ ComponentTemplate ct1 = new ComponentTemplate (ctt1 , null , null );
1014+ ComponentTemplate ct2 = new ComponentTemplate (ctt2 , null , null );
1015+
1016+ boolean shouldBeText = randomBoolean ();
1017+ List <String > composedOf = shouldBeText ? Arrays .asList ("ct2" , "ct1" ) : Arrays .asList ("ct1" , "ct2" );
1018+ logger .info ("--> the {} analyzer should win ({})" , shouldBeText ? "text" : "keyword" , composedOf );
1019+ IndexTemplateV2 template = new IndexTemplateV2 (Collections .singletonList ("index" ), null , composedOf , null , null , null );
1020+
1021+ ClusterState state = ClusterState .builder (ClusterState .EMPTY_STATE )
1022+ .metadata (Metadata .builder (Metadata .EMPTY_METADATA )
1023+ .put ("ct1" , ct1 )
1024+ .put ("ct2" , ct2 )
1025+ .put ("index-template" , template )
1026+ .build ())
1027+ .build ();
1028+
1029+ Map <String , Map <String , Object >> resolved =
1030+ MetadataCreateIndexService .resolveV2Mappings ("{\" _doc\" :{\" _meta\" :{\" ct2\" :\" eggplant\" }," +
1031+ "\" properties\" :{\" bar\" :{\" type\" :\" text\" }}}}" , state ,
1032+ "index-template" , new NamedXContentRegistry (Collections .emptyList ()));
1033+
1034+ assertThat ("expected exactly one type but was: " + resolved , resolved .size (), equalTo (1 ));
1035+ Map <String , Object > innerResolved = (Map <String , Object >) resolved .get (MapperService .SINGLE_MAPPING_NAME );
1036+ assertThat ("was: " + innerResolved , innerResolved .size (), equalTo (3 ));
1037+
1038+ Map <String , Object > nonProperties = new HashMap <>(innerResolved );
1039+ nonProperties .remove ("properties" );
1040+ Map <String , Object > expectedNonProperties = new HashMap <>();
1041+ expectedNonProperties .put ("_source" , Collections .singletonMap ("enabled" , false ));
1042+ Map <String , Object > meta = new HashMap <>();
1043+ meta .put ("ct2" , "eggplant" );
1044+ if (shouldBeText ) {
1045+ meta .put ("ct1" , Collections .singletonMap ("ver" , "text" ));
1046+ } else {
1047+ meta .put ("ct1" , Collections .singletonMap ("ver" , "keyword" ));
1048+ }
1049+ expectedNonProperties .put ("_meta" , meta );
1050+ assertThat (nonProperties , equalTo (expectedNonProperties ));
1051+
1052+ Map <String , Object > innerInnerResolved = (Map <String , Object >) innerResolved .get ("properties" );
1053+ assertThat (innerInnerResolved .size (), equalTo (2 ));
1054+ assertThat (innerInnerResolved .get ("bar" ), equalTo (Collections .singletonMap ("type" , "text" )));
1055+ Map <String , Object > fooMappings = new HashMap <>();
1056+ if (shouldBeText ) {
1057+ fooMappings .put ("type" , "text" );
1058+ fooMappings .put ("ignore_above" , 7 );
1059+ fooMappings .put ("analyzer" , "english" );
1060+ } else {
1061+ fooMappings .put ("type" , "keyword" );
1062+ fooMappings .put ("ignore_above" , 13 );
1063+ }
1064+ assertThat (innerInnerResolved .get ("foo" ), equalTo (fooMappings ));
1065+ }
1066+
10041067 private IndexTemplateMetadata addMatchingTemplate (Consumer <IndexTemplateMetadata .Builder > configurator ) {
10051068 IndexTemplateMetadata .Builder builder = templateMetadataBuilder ("template1" , "te*" );
10061069 configurator .accept (builder );
0 commit comments