diff --git a/docs/changelog/82830.yaml b/docs/changelog/82830.yaml new file mode 100644 index 0000000000000..e35dda2a6a0d7 --- /dev/null +++ b/docs/changelog/82830.yaml @@ -0,0 +1,5 @@ +pr: 82830 +summary: Speed up `MappingStats` Computation on Coordinating Node +area: Stats +type: enhancement +issues: [] diff --git a/server/src/internalClusterTest/java/org/elasticsearch/action/admin/cluster/stats/ClusterStatsIT.java b/server/src/internalClusterTest/java/org/elasticsearch/action/admin/cluster/stats/ClusterStatsIT.java index 9d4b23e1206b4..0a315dc7b8f99 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/action/admin/cluster/stats/ClusterStatsIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/action/admin/cluster/stats/ClusterStatsIT.java @@ -29,6 +29,7 @@ import java.io.IOException; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ExecutionException; @@ -276,7 +277,7 @@ public void testFieldTypes() { }""").get(); response = client().admin().cluster().prepareClusterStats().get(); assertThat(response.getIndicesStats().getMappings().getFieldTypeStats().size(), equalTo(3)); - Set stats = response.getIndicesStats().getMappings().getFieldTypeStats(); + List stats = response.getIndicesStats().getMappings().getFieldTypeStats(); for (FieldStats stat : stats) { if (stat.getName().equals("integer")) { assertThat(stat.getCount(), greaterThanOrEqualTo(1)); diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/stats/AnalysisStats.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/stats/AnalysisStats.java index 172f0d935476d..ed8a30e4ba34d 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/cluster/stats/AnalysisStats.java +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/stats/AnalysisStats.java @@ -27,6 +27,7 @@ import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; +import java.util.IdentityHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -51,6 +52,7 @@ public static AnalysisStats of(Metadata metadata, Runnable ensureNotCancelled) { final Map usedBuiltInTokenFilters = new HashMap<>(); final Map usedBuiltInAnalyzers = new HashMap<>(); + final Map mappingCounts = new IdentityHashMap<>(metadata.getMappingsByHash().size()); for (IndexMetadata indexMetadata : metadata) { ensureNotCancelled.run(); if (indexMetadata.isSystem()) { @@ -58,23 +60,6 @@ public static AnalysisStats of(Metadata metadata, Runnable ensureNotCancelled) { // we care about the user's indices. continue; } - Set indexAnalyzers = new HashSet<>(); - MappingMetadata mappingMetadata = indexMetadata.mapping(); - if (mappingMetadata != null) { - MappingVisitor.visitMapping(mappingMetadata.getSourceAsMap(), (field, fieldMapping) -> { - for (String key : new String[] { "analyzer", "search_analyzer", "search_quote_analyzer" }) { - Object analyzerO = fieldMapping.get(key); - if (analyzerO != null) { - final String analyzer = analyzerO.toString(); - IndexFeatureStats stats = usedBuiltInAnalyzers.computeIfAbsent(analyzer, IndexFeatureStats::new); - stats.count++; - if (indexAnalyzers.add(analyzer)) { - stats.indexCount++; - } - } - } - }); - } Set indexCharFilters = new HashSet<>(); Set indexTokenizers = new HashSet<>(); @@ -133,7 +118,27 @@ public static AnalysisStats of(Metadata metadata, Runnable ensureNotCancelled) { Map tokenFilterSettings = indexSettings.getGroups("index.analysis.filter"); usedBuiltInTokenFilters.keySet().removeAll(tokenFilterSettings.keySet()); aggregateAnalysisTypes(tokenFilterSettings.values(), usedTokenFilterTypes, indexTokenFilterTypes); + countMapping(mappingCounts, indexMetadata); + } + for (Map.Entry mappingAndCount : mappingCounts.entrySet()) { + ensureNotCancelled.run(); + Set indexAnalyzers = new HashSet<>(); + final int count = mappingAndCount.getValue(); + MappingVisitor.visitMapping(mappingAndCount.getKey().getSourceAsMap(), (field, fieldMapping) -> { + for (String key : new String[] { "analyzer", "search_analyzer", "search_quote_analyzer" }) { + Object analyzerO = fieldMapping.get(key); + if (analyzerO != null) { + final String analyzer = analyzerO.toString(); + IndexFeatureStats stats = usedBuiltInAnalyzers.computeIfAbsent(analyzer, IndexFeatureStats::new); + stats.count += count; + if (indexAnalyzers.add(analyzer)) { + stats.indexCount += count; + } + } + } + }); } + return new AnalysisStats( usedCharFilterTypes.values(), usedTokenizerTypes.values(), @@ -146,6 +151,14 @@ public static AnalysisStats of(Metadata metadata, Runnable ensureNotCancelled) { ); } + public static void countMapping(Map mappingCounts, IndexMetadata indexMetadata) { + final MappingMetadata mappingMetadata = indexMetadata.mapping(); + if (mappingMetadata == null) { + return; + } + mappingCounts.compute(mappingMetadata, (k, count) -> count == null ? 1 : count + 1); + } + private static void aggregateAnalysisTypes( Collection settings, Map stats, diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/stats/FieldScriptStats.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/stats/FieldScriptStats.java index a8cef70072a78..d3ed4203cb2fd 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/cluster/stats/FieldScriptStats.java +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/stats/FieldScriptStats.java @@ -68,14 +68,14 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws return builder; } - void update(int chars, long lines, int sourceUsages, int docUsages) { + void update(int chars, long lines, int sourceUsages, int docUsages, int count) { this.maxChars = Math.max(this.maxChars, chars); - this.totalChars += chars; + this.totalChars += (long) chars * count; this.maxLines = Math.max(this.maxLines, lines); - this.totalLines += lines; - this.totalSourceUsages += sourceUsages; + this.totalLines += lines * count; + this.totalSourceUsages += (long) sourceUsages * count; this.maxSourceUsages = Math.max(this.maxSourceUsages, sourceUsages); - this.totalDocUsages += docUsages; + this.totalDocUsages += (long) docUsages * count; this.maxDocUsages = Math.max(this.maxDocUsages, docUsages); } diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/stats/MappingStats.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/stats/MappingStats.java index 0c4276833cb3c..ebcd664abbd61 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/cluster/stats/MappingStats.java +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/stats/MappingStats.java @@ -25,7 +25,7 @@ import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedHashSet; +import java.util.IdentityHashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -48,85 +48,87 @@ public static MappingStats of(Metadata metadata, Runnable ensureNotCancelled) { Map fieldTypes = new HashMap<>(); Set concreteFieldNames = new HashSet<>(); Map runtimeFieldTypes = new HashMap<>(); + final Map mappingCounts = new IdentityHashMap<>(metadata.getMappingsByHash().size()); for (IndexMetadata indexMetadata : metadata) { - ensureNotCancelled.run(); if (indexMetadata.isSystem()) { // Don't include system indices in statistics about mappings, // we care about the user's indices. continue; } + AnalysisStats.countMapping(mappingCounts, indexMetadata); + } + for (Map.Entry mappingAndCount : mappingCounts.entrySet()) { + ensureNotCancelled.run(); Set indexFieldTypes = new HashSet<>(); Set indexRuntimeFieldTypes = new HashSet<>(); - MappingMetadata mappingMetadata = indexMetadata.mapping(); - if (mappingMetadata != null) { - final Map map = mappingMetadata.getSourceAsMap(); - MappingVisitor.visitMapping(map, (field, fieldMapping) -> { - concreteFieldNames.add(field); - String type = null; - Object typeO = fieldMapping.get("type"); - if (typeO != null) { - type = typeO.toString(); - } else if (fieldMapping.containsKey("properties")) { - type = "object"; - } - if (type != null) { - FieldStats stats = fieldTypes.computeIfAbsent(type, FieldStats::new); - stats.count++; - if (indexFieldTypes.add(type)) { - stats.indexCount++; - } - Object scriptObject = fieldMapping.get("script"); - if (scriptObject instanceof Map script) { - Object sourceObject = script.get("source"); - stats.scriptCount++; - updateScriptParams(sourceObject, stats.fieldScriptStats); - Object langObject = script.get("lang"); - if (langObject != null) { - stats.scriptLangs.add(langObject.toString()); - } - } - } - }); - - MappingVisitor.visitRuntimeMapping(map, (field, fieldMapping) -> { - Object typeObject = fieldMapping.get("type"); - if (typeObject == null) { - return; - } - String type = typeObject.toString(); - RuntimeFieldStats stats = runtimeFieldTypes.computeIfAbsent(type, RuntimeFieldStats::new); - stats.count++; - if (indexRuntimeFieldTypes.add(type)) { - stats.indexCount++; - } - if (concreteFieldNames.contains(field)) { - stats.shadowedCount++; + final int count = mappingAndCount.getValue(); + final Map map = mappingAndCount.getKey().getSourceAsMap(); + MappingVisitor.visitMapping(map, (field, fieldMapping) -> { + concreteFieldNames.add(field); + String type = null; + Object typeO = fieldMapping.get("type"); + if (typeO != null) { + type = typeO.toString(); + } else if (fieldMapping.containsKey("properties")) { + type = "object"; + } + if (type != null) { + FieldStats stats = fieldTypes.computeIfAbsent(type, FieldStats::new); + stats.count += count; + if (indexFieldTypes.add(type)) { + stats.indexCount += count; } Object scriptObject = fieldMapping.get("script"); - if (scriptObject == null) { - stats.scriptLessCount++; - } else if (scriptObject instanceof Map script) { + if (scriptObject instanceof Map script) { Object sourceObject = script.get("source"); - updateScriptParams(sourceObject, stats.fieldScriptStats); + stats.scriptCount += count; + updateScriptParams(sourceObject, stats.fieldScriptStats, count); Object langObject = script.get("lang"); if (langObject != null) { stats.scriptLangs.add(langObject.toString()); } } - }); - } + } + }); + + MappingVisitor.visitRuntimeMapping(map, (field, fieldMapping) -> { + Object typeObject = fieldMapping.get("type"); + if (typeObject == null) { + return; + } + String type = typeObject.toString(); + RuntimeFieldStats stats = runtimeFieldTypes.computeIfAbsent(type, RuntimeFieldStats::new); + stats.count += count; + if (indexRuntimeFieldTypes.add(type)) { + stats.indexCount += count; + } + if (concreteFieldNames.contains(field)) { + stats.shadowedCount += count; + } + Object scriptObject = fieldMapping.get("script"); + if (scriptObject == null) { + stats.scriptLessCount += count; + } else if (scriptObject instanceof Map script) { + Object sourceObject = script.get("source"); + updateScriptParams(sourceObject, stats.fieldScriptStats, count); + Object langObject = script.get("lang"); + if (langObject != null) { + stats.scriptLangs.add(langObject.toString()); + } + } + }); } return new MappingStats(fieldTypes.values(), runtimeFieldTypes.values()); } - private static void updateScriptParams(Object scriptSourceObject, FieldScriptStats scriptStats) { + private static void updateScriptParams(Object scriptSourceObject, FieldScriptStats scriptStats, int multiplier) { if (scriptSourceObject != null) { String scriptSource = scriptSourceObject.toString(); int chars = scriptSource.length(); long lines = scriptSource.lines().count(); int docUsages = countOccurrences(scriptSource, DOC_PATTERN); int sourceUsages = countOccurrences(scriptSource, SOURCE_PATTERN); - scriptStats.update(chars, lines, sourceUsages, docUsages); + scriptStats.update(chars, lines, sourceUsages, docUsages, multiplier); } } @@ -139,21 +141,21 @@ private static int countOccurrences(String script, Pattern pattern) { return occurrences; } - private final Set fieldTypeStats; - private final Set runtimeFieldStats; + private final List fieldTypeStats; + private final List runtimeFieldStats; MappingStats(Collection fieldTypeStats, Collection runtimeFieldStats) { List stats = new ArrayList<>(fieldTypeStats); stats.sort(Comparator.comparing(IndexFeatureStats::getName)); - this.fieldTypeStats = Collections.unmodifiableSet(new LinkedHashSet<>(stats)); + this.fieldTypeStats = Collections.unmodifiableList(stats); List runtimeStats = new ArrayList<>(runtimeFieldStats); runtimeStats.sort(Comparator.comparing(RuntimeFieldStats::type)); - this.runtimeFieldStats = Collections.unmodifiableSet(new LinkedHashSet<>(runtimeStats)); + this.runtimeFieldStats = Collections.unmodifiableList(runtimeStats); } MappingStats(StreamInput in) throws IOException { - fieldTypeStats = Collections.unmodifiableSet(new LinkedHashSet<>(in.readList(FieldStats::new))); - runtimeFieldStats = Collections.unmodifiableSet(new LinkedHashSet<>(in.readList(RuntimeFieldStats::new))); + fieldTypeStats = Collections.unmodifiableList(in.readList(FieldStats::new)); + runtimeFieldStats = Collections.unmodifiableList(in.readList(RuntimeFieldStats::new)); } @Override @@ -165,14 +167,14 @@ public void writeTo(StreamOutput out) throws IOException { /** * Return stats about field types. */ - public Set getFieldTypeStats() { + public List getFieldTypeStats() { return fieldTypeStats; } /** * Return stats about runtime field types. */ - public Set getRuntimeFieldStats() { + public List getRuntimeFieldStats() { return runtimeFieldStats; } diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/Metadata.java b/server/src/main/java/org/elasticsearch/cluster/metadata/Metadata.java index 836a2ffba5c74..25ddbbccd9c3a 100644 --- a/server/src/main/java/org/elasticsearch/cluster/metadata/Metadata.java +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/Metadata.java @@ -949,7 +949,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws return builder; } - Map getMappingsByHash() { + public Map getMappingsByHash() { return mappingsByHash; } diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/stats/AnalysisStatsTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/stats/AnalysisStatsTests.java index 6c3c81eb45dd5..66cf0ccdc6a14 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/cluster/stats/AnalysisStatsTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/stats/AnalysisStatsTests.java @@ -232,13 +232,39 @@ public void testAccountsRegularIndices() { .put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 4) .put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 1) .build(); - IndexMetadata.Builder indexMetadata = new IndexMetadata.Builder("foo").settings(settings).putMapping(mapping); - Metadata metadata = new Metadata.Builder().put(indexMetadata).build(); - AnalysisStats analysisStats = AnalysisStats.of(metadata, () -> {}); - IndexFeatureStats expectedStats = new IndexFeatureStats("german"); - expectedStats.count = 1; - expectedStats.indexCount = 1; - assertEquals(Collections.singleton(expectedStats), analysisStats.getUsedBuiltInAnalyzers()); + Metadata metadata = new Metadata.Builder().put(new IndexMetadata.Builder("foo").settings(settings).putMapping(mapping)).build(); + { + AnalysisStats analysisStats = AnalysisStats.of(metadata, () -> {}); + IndexFeatureStats expectedStats = new IndexFeatureStats("german"); + expectedStats.count = 1; + expectedStats.indexCount = 1; + assertEquals(Collections.singleton(expectedStats), analysisStats.getUsedBuiltInAnalyzers()); + } + + Metadata metadata2 = Metadata.builder(metadata) + .put(new IndexMetadata.Builder("bar").settings(settings).putMapping(mapping)) + .build(); + { + AnalysisStats analysisStats = AnalysisStats.of(metadata2, () -> {}); + IndexFeatureStats expectedStats = new IndexFeatureStats("german"); + expectedStats.count = 2; + expectedStats.indexCount = 2; + assertEquals(Collections.singleton(expectedStats), analysisStats.getUsedBuiltInAnalyzers()); + } + + Metadata metadata3 = Metadata.builder(metadata2).put(new IndexMetadata.Builder("baz").settings(settings).putMapping(""" + {"properties":{"bar1":{"type":"text","analyzer":"french"}, + "bar2":{"type":"text","analyzer":"french"},"bar3":{"type":"text","analyzer":"french"}}}""")).build(); + { + AnalysisStats analysisStats = AnalysisStats.of(metadata3, () -> {}); + IndexFeatureStats expectedStatsGerman = new IndexFeatureStats("german"); + expectedStatsGerman.count = 2; + expectedStatsGerman.indexCount = 2; + IndexFeatureStats expectedStatsFrench = new IndexFeatureStats("french"); + expectedStatsFrench.count = 3; + expectedStatsFrench.indexCount = 1; + assertEquals(Set.of(expectedStatsGerman, expectedStatsFrench), analysisStats.getUsedBuiltInAnalyzers()); + } } public void testIgnoreSystemIndices() { diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/stats/MappingStatsTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/stats/MappingStatsTests.java index a639d628536bf..6f5c53b199095 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/cluster/stats/MappingStatsTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/stats/MappingStatsTests.java @@ -20,6 +20,7 @@ import org.elasticsearch.tasks.TaskCancelledException; import org.elasticsearch.test.AbstractWireSerializingTestCase; import org.elasticsearch.test.VersionUtils; +import org.hamcrest.Matchers; import java.io.IOException; import java.util.ArrayList; @@ -29,73 +30,70 @@ public class MappingStatsTests extends AbstractWireSerializingTestCase { - public void testToXContent() { - Settings settings = Settings.builder() - .put("index.number_of_replicas", 0) - .put("index.number_of_shards", 1) - .put("index.version.created", Version.CURRENT) - .build(); - Script script1 = new Script("doc['field'] + doc.field + params._source.field"); - Script script2 = new Script("doc['field']"); - Script script3 = new Script("params._source.field + params._source.field \n + params._source.field"); - Script script4 = new Script("params._source.field"); - String mapping = """ - { - "runtime": { - "keyword1": { - "type": "keyword", - "script": %s - }, - "keyword2": { - "type": "keyword" - }, - "object.keyword3": { - "type": "keyword", - "script": %s - }, - "long": { - "type": "long", - "script": %s - }, - "long2": { - "type": "long", - "script": %s - } + private static final Settings SINGLE_SHARD_NO_REPLICAS = Settings.builder() + .put("index.number_of_replicas", 0) + .put("index.number_of_shards", 1) + .put("index.version.created", Version.CURRENT) + .build(); + + public static final String MAPPING_TEMPLATE = """ + { + "runtime": { + "keyword1": { + "type": "keyword", + "script": %s + }, + "keyword2": { + "type": "keyword" + }, + "object.keyword3": { + "type": "keyword", + "script": %s }, - "properties": { - "object": { - "type": "object", - "properties": { - "keyword3": { - "type": "keyword" - } + "long": { + "type": "long", + "script": %s + }, + "long2": { + "type": "long", + "script": %s + } + }, + "properties": { + "object": { + "type": "object", + "properties": { + "keyword3": { + "type": "keyword" } - }, - "long3": { - "type": "long", - "script": %s - }, - "long4": { - "type": "long", - "script": %s - }, - "keyword3": { - "type": "keyword", - "script": %s } + }, + "long3": { + "type": "long", + "script": %s + }, + "long4": { + "type": "long", + "script": %s + }, + "keyword3": { + "type": "keyword", + "script": %s } - }""".formatted( - Strings.toString(script1), - Strings.toString(script2), - Strings.toString(script3), - Strings.toString(script4), - Strings.toString(script3), - Strings.toString(script4), - Strings.toString(script1) - ); - IndexMetadata meta = IndexMetadata.builder("index").settings(settings).putMapping(mapping).build(); - IndexMetadata meta2 = IndexMetadata.builder("index2").settings(settings).putMapping(mapping).build(); + } + }"""; + + private static final String SCRIPT_1 = scriptAsJSON("doc['field'] + doc.field + params._source.field"); + private static final String SCRIPT_2 = scriptAsJSON("doc['field']"); + private static final String SCRIPT_3 = scriptAsJSON("params._source.field + params._source.field \n + params._source.field"); + private static final String SCRIPT_4 = scriptAsJSON("params._source.field"); + + public void testToXContent() { + String mapping = MAPPING_TEMPLATE.formatted(SCRIPT_1, SCRIPT_2, SCRIPT_3, SCRIPT_4, SCRIPT_3, SCRIPT_4, SCRIPT_1); + IndexMetadata meta = IndexMetadata.builder("index").settings(SINGLE_SHARD_NO_REPLICAS).putMapping(mapping).build(); + IndexMetadata meta2 = IndexMetadata.builder("index2").settings(SINGLE_SHARD_NO_REPLICAS).putMapping(mapping).build(); Metadata metadata = Metadata.builder().put(meta, false).put(meta2, false).build(); + assertThat(metadata.getMappingsByHash(), Matchers.aMapWithSize(1)); MappingStats mappingStats = MappingStats.of(metadata, () -> {}); assertEquals(""" { @@ -184,6 +182,109 @@ public void testToXContent() { }""", Strings.toString(mappingStats, true, true)); } + public void testToXContentWithSomeSharedMappings() { + IndexMetadata meta = IndexMetadata.builder("index") + .settings(SINGLE_SHARD_NO_REPLICAS) + .putMapping(MAPPING_TEMPLATE.formatted(SCRIPT_1, SCRIPT_2, SCRIPT_3, SCRIPT_4, SCRIPT_3, SCRIPT_4, SCRIPT_1)) + .build(); + // make mappings that are slightly different because we shuffled 2 scripts between fields + final String mappingString2 = MAPPING_TEMPLATE.formatted(SCRIPT_1, SCRIPT_2, SCRIPT_3, SCRIPT_4, SCRIPT_4, SCRIPT_3, SCRIPT_1); + IndexMetadata meta2 = IndexMetadata.builder("index2").settings(SINGLE_SHARD_NO_REPLICAS).putMapping(mappingString2).build(); + IndexMetadata meta3 = IndexMetadata.builder("index3").settings(SINGLE_SHARD_NO_REPLICAS).putMapping(mappingString2).build(); + Metadata metadata = Metadata.builder().put(meta, false).put(meta2, false).put(meta3, false).build(); + assertThat(metadata.getMappingsByHash(), Matchers.aMapWithSize(2)); + MappingStats mappingStats = MappingStats.of(metadata, () -> {}); + assertEquals(""" + { + "mappings" : { + "field_types" : [ + { + "name" : "keyword", + "count" : 6, + "index_count" : 3, + "script_count" : 3, + "lang" : [ + "painless" + ], + "lines_max" : 1, + "lines_total" : 3, + "chars_max" : 47, + "chars_total" : 141, + "source_max" : 1, + "source_total" : 3, + "doc_max" : 2, + "doc_total" : 6 + }, + { + "name" : "long", + "count" : 6, + "index_count" : 3, + "script_count" : 6, + "lang" : [ + "painless" + ], + "lines_max" : 2, + "lines_total" : 9, + "chars_max" : 68, + "chars_total" : 264, + "source_max" : 3, + "source_total" : 12, + "doc_max" : 0, + "doc_total" : 0 + }, + { + "name" : "object", + "count" : 3, + "index_count" : 3, + "script_count" : 0 + } + ], + "runtime_field_types" : [ + { + "name" : "keyword", + "count" : 9, + "index_count" : 3, + "scriptless_count" : 3, + "shadowed_count" : 3, + "lang" : [ + "painless" + ], + "lines_max" : 1, + "lines_total" : 6, + "chars_max" : 47, + "chars_total" : 177, + "source_max" : 1, + "source_total" : 3, + "doc_max" : 2, + "doc_total" : 9 + }, + { + "name" : "long", + "count" : 6, + "index_count" : 3, + "scriptless_count" : 0, + "shadowed_count" : 0, + "lang" : [ + "painless" + ], + "lines_max" : 2, + "lines_total" : 9, + "chars_max" : 68, + "chars_total" : 264, + "source_max" : 3, + "source_total" : 12, + "doc_max" : 0, + "doc_total" : 0 + } + ] + } + }""", Strings.toString(mappingStats, true, true)); + } + + private static String scriptAsJSON(String script) { + return Strings.toString(new Script(script)); + } + @Override protected Reader instanceReader() { return MappingStats::new; @@ -219,6 +320,7 @@ private static FieldStats randomFieldStats(String type) { randomIntBetween(1, 100), randomLongBetween(100, 1000), randomIntBetween(1, 10), + randomIntBetween(1, 10), randomIntBetween(1, 10) ); } @@ -237,6 +339,7 @@ private static RuntimeFieldStats randomRuntimeFieldStats(String type) { randomIntBetween(1, 100), randomLongBetween(100, 1000), randomIntBetween(1, 10), + randomIntBetween(1, 10), randomIntBetween(1, 10) ); } @@ -285,7 +388,7 @@ public void testAccountsRegularIndices() { FieldStats expectedStats = new FieldStats("long"); expectedStats.count = 1; expectedStats.indexCount = 1; - assertEquals(Collections.singleton(expectedStats), mappingStats.getFieldTypeStats()); + assertEquals(Collections.singletonList(expectedStats), mappingStats.getFieldTypeStats()); } public void testIgnoreSystemIndices() { @@ -299,7 +402,7 @@ public void testIgnoreSystemIndices() { IndexMetadata.Builder indexMetadata = new IndexMetadata.Builder("foo").settings(settings).putMapping(mapping).system(true); Metadata metadata = new Metadata.Builder().put(indexMetadata).build(); MappingStats mappingStats = MappingStats.of(metadata, () -> {}); - assertEquals(Collections.emptySet(), mappingStats.getFieldTypeStats()); + assertEquals(Collections.emptyList(), mappingStats.getFieldTypeStats()); } public void testChecksForCancellation() { @@ -308,7 +411,7 @@ public void testChecksForCancellation() { .put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 4) .put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 1) .build(); - IndexMetadata.Builder indexMetadata = new IndexMetadata.Builder("foo").settings(settings); + IndexMetadata.Builder indexMetadata = new IndexMetadata.Builder("foo").settings(settings).putMapping("{}"); Metadata metadata = new Metadata.Builder().put(indexMetadata).build(); expectThrows( TaskCancelledException.class,