|
@@ -18,6 +18,7 @@ import org.elasticsearch.action.search.SearchResponse;
|
|
|
import org.elasticsearch.action.support.WriteRequest;
|
|
|
import org.elasticsearch.cluster.ClusterState;
|
|
|
import org.elasticsearch.cluster.ClusterStateUpdateTask;
|
|
|
+import org.elasticsearch.cluster.metadata.IndexMetadata;
|
|
|
import org.elasticsearch.cluster.metadata.MappingMetadata;
|
|
|
import org.elasticsearch.cluster.service.ClusterService;
|
|
|
import org.elasticsearch.common.Randomness;
|
|
@@ -213,6 +214,71 @@ public class DynamicMappingIT extends ESIntegTestCase {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ public void testTotalFieldsLimitWithRuntimeFields() {
|
|
|
+ Settings indexSettings = Settings.builder()
|
|
|
+ .put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1)
|
|
|
+ .put(INDEX_MAPPING_TOTAL_FIELDS_LIMIT_SETTING.getKey(), 4)
|
|
|
+ .build();
|
|
|
+
|
|
|
+ String mapping = """
|
|
|
+ {
|
|
|
+ "dynamic":"runtime",
|
|
|
+ "runtime": {
|
|
|
+ "my_object.rfield1": {
|
|
|
+ "type": "keyword"
|
|
|
+ },
|
|
|
+ "rfield2": {
|
|
|
+ "type": "keyword"
|
|
|
+ }
|
|
|
+ },
|
|
|
+ "properties": {
|
|
|
+ "field3" : {
|
|
|
+ "type": "keyword"
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ """;
|
|
|
+
|
|
|
+ client().admin().indices().prepareCreate("index1").setSettings(indexSettings).setMapping(mapping).get();
|
|
|
+ ensureGreen("index1");
|
|
|
+
|
|
|
+ {
|
|
|
+ // introduction of a new object with 2 new sub-fields fails
|
|
|
+ final IndexRequestBuilder indexRequestBuilder = client().prepareIndex("index1")
|
|
|
+ .setId("1")
|
|
|
+ .setSource("field3", "value3", "my_object2", Map.of("new_field1", "value1", "new_field2", "value2"));
|
|
|
+ Exception exc = expectThrows(MapperParsingException.class, () -> indexRequestBuilder.get(TimeValue.timeValueSeconds(10)));
|
|
|
+ assertThat(exc.getMessage(), Matchers.containsString("failed to parse"));
|
|
|
+ assertThat(exc.getCause(), instanceOf(IllegalArgumentException.class));
|
|
|
+ assertThat(
|
|
|
+ exc.getCause().getMessage(),
|
|
|
+ Matchers.containsString("Limit of total fields [4] has been exceeded while adding new fields [2]")
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ {
|
|
|
+ // introduction of a new single field succeeds
|
|
|
+ client().prepareIndex("index1").setId("2").setSource("field3", "value3", "new_field4", 100).get();
|
|
|
+ }
|
|
|
+
|
|
|
+ {
|
|
|
+ // remove 2 runtime field mappings
|
|
|
+ assertAcked(client().admin().indices().preparePutMapping("index1").setSource("""
|
|
|
+ {
|
|
|
+ "runtime": {
|
|
|
+ "my_object.rfield1": null,
|
|
|
+ "rfield2" : null
|
|
|
+ }
|
|
|
+ }
|
|
|
+ """, XContentType.JSON));
|
|
|
+
|
|
|
+ // introduction of a new object with 2 new sub-fields succeeds
|
|
|
+ client().prepareIndex("index1")
|
|
|
+ .setId("1")
|
|
|
+ .setSource("field3", "value3", "my_object2", Map.of("new_field1", "value1", "new_field2", "value2"));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
public void testMappingVersionAfterDynamicMappingUpdate() throws Exception {
|
|
|
createIndex("test");
|
|
|
final ClusterService clusterService = internalCluster().clusterService();
|