From 9b1dd407f0d0c6c67aa4176a0fa41dd7f2dee4a7 Mon Sep 17 00:00:00 2001 From: Martijn van Groningen Date: Fri, 17 Feb 2023 16:37:47 +0100 Subject: [PATCH 1/5] Include supported aggregations in field caps api response Improve field caps api to include what aggregations are supported on a per field bases. For fields that are aggregatable, a list of supported aggregations is included. Closes #93539 --- .../action/fieldcaps/FieldCapabilities.java | 89 ++++++++++++++----- .../fieldcaps/FieldCapabilitiesFetcher.java | 4 + .../fieldcaps/IndexFieldCapabilities.java | 40 +++++++-- .../TransportFieldCapabilitiesAction.java | 3 +- .../support/ValuesSourceRegistry.java | 32 ++++++- .../FieldCapabilitiesIndexResponseTests.java | 1 + .../FieldCapabilitiesNodeResponseTests.java | 8 +- .../FieldCapabilitiesResponseTests.java | 9 +- .../fieldcaps/FieldCapabilitiesTests.java | 79 ++++++++++++---- .../MergedFieldCapabilitiesResponseTests.java | 24 ++++- .../fieldcaps/ResponseRewriterTests.java | 3 +- 11 files changed, 229 insertions(+), 63 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/action/fieldcaps/FieldCapabilities.java b/server/src/main/java/org/elasticsearch/action/fieldcaps/FieldCapabilities.java index daa9ee30bf9aa..38bbfa8bd4965 100644 --- a/server/src/main/java/org/elasticsearch/action/fieldcaps/FieldCapabilities.java +++ b/server/src/main/java/org/elasticsearch/action/fieldcaps/FieldCapabilities.java @@ -13,6 +13,7 @@ import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.io.stream.Writeable; +import org.elasticsearch.common.util.set.Sets; import org.elasticsearch.index.mapper.TimeSeriesParams; import org.elasticsearch.xcontent.ConstructingObjectParser; import org.elasticsearch.xcontent.InstantiatingObjectParser; @@ -58,6 +59,8 @@ public class FieldCapabilities implements Writeable, ToXContentObject { private static final ParseField METRIC_CONFLICTS_INDICES_FIELD = new ParseField("metric_conflicts_indices"); private static final ParseField META_FIELD = new ParseField("meta"); + private static final ParseField SUPPORTED_AGGREGATIONS = new ParseField("supported_aggregations"); + private final String name; private final String type; private final boolean isMetadataField; @@ -74,24 +77,28 @@ public class FieldCapabilities implements Writeable, ToXContentObject { private final Map> meta; + private final Set supportedAggregations; + /** * Constructor for a set of indices. - * @param name The name of the field - * @param type The type associated with the field. - * @param isMetadataField Whether this field is a metadata field. - * @param isSearchable Whether this field is indexed for search. - * @param isAggregatable Whether this field can be aggregated on. - * @param isDimension Whether this field can be used as dimension - * @param metricType If this field is a metric field, returns the metric's type or null for non-metrics fields - * @param indices The list of indices where this field name is defined as {@code type}, - * or null if all indices have the same {@code type} for the field. - * @param nonSearchableIndices The list of indices where this field is not searchable, - * or null if the field is searchable in all indices. + * + * @param name The name of the field + * @param type The type associated with the field. + * @param isMetadataField Whether this field is a metadata field. + * @param isSearchable Whether this field is indexed for search. + * @param isAggregatable Whether this field can be aggregated on. + * @param isDimension Whether this field can be used as dimension + * @param metricType If this field is a metric field, returns the metric's type or null for non-metrics fields + * @param indices The list of indices where this field name is defined as {@code type}, + * or null if all indices have the same {@code type} for the field. + * @param nonSearchableIndices The list of indices where this field is not searchable, + * or null if the field is searchable in all indices. * @param nonAggregatableIndices The list of indices where this field is not aggregatable, * or null if the field is aggregatable in all indices. - * @param nonDimensionIndices The list of indices where this field is not a dimension + * @param nonDimensionIndices The list of indices where this field is not a dimension * @param metricConflictsIndices The list of indices where this field is has different metric types or not mark as a metric - * @param meta Merged metadata across indices. + * @param meta Merged metadata across indices. + * @param supportedAggregations If the field is aggregatable then the list of supported aggregations */ public FieldCapabilities( String name, @@ -106,7 +113,8 @@ public FieldCapabilities( String[] nonAggregatableIndices, String[] nonDimensionIndices, String[] metricConflictsIndices, - Map> meta + Map> meta, + Set supportedAggregations ) { this.name = name; this.type = type; @@ -121,6 +129,7 @@ public FieldCapabilities( this.nonDimensionIndices = nonDimensionIndices; this.metricConflictsIndices = metricConflictsIndices; this.meta = Objects.requireNonNull(meta); + this.supportedAggregations = Objects.requireNonNull(supportedAggregations); } /** @@ -163,9 +172,9 @@ public FieldCapabilities( nonAggregatableIndices, null, null, - meta + meta, + Set.of() ); - } /** @@ -217,7 +226,8 @@ public FieldCapabilities( nonAggregatableIndices != null ? nonAggregatableIndices.toArray(new String[0]) : null, nonDimensionIndices != null ? nonDimensionIndices.toArray(new String[0]) : null, metricConflictsIndices != null ? metricConflictsIndices.toArray(new String[0]) : null, - meta != null ? meta : Collections.emptyMap() + meta != null ? meta : Collections.emptyMap(), + Set.of() ); } @@ -245,6 +255,9 @@ public FieldCapabilities( this.metricConflictsIndices = null; } meta = in.readMap(StreamInput::readString, i -> i.readSet(StreamInput::readString)); + supportedAggregations = in.getTransportVersion().onOrAfter(TransportVersion.V_8_8_0) + ? in.readSet(StreamInput::readString) + : Set.of(); } @Override @@ -266,6 +279,9 @@ public void writeTo(StreamOutput out) throws IOException { out.writeOptionalStringArray(metricConflictsIndices); } out.writeMap(meta, StreamOutput::writeString, (o, set) -> o.writeCollection(set, StreamOutput::writeString)); + if (out.getTransportVersion().onOrAfter(TransportVersion.V_8_8_0)) { + out.writeCollection(supportedAggregations, StreamOutput::writeString); + } } @Override @@ -307,6 +323,9 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws } builder.endObject(); } + if (isAggregatable) { + builder.array(SUPPORTED_AGGREGATIONS.getPreferredName(), supportedAggregations); + } builder.endObject(); return builder; } @@ -454,12 +473,23 @@ public boolean equals(Object o) { && Arrays.equals(nonAggregatableIndices, that.nonAggregatableIndices) && Arrays.equals(nonDimensionIndices, that.nonDimensionIndices) && Arrays.equals(metricConflictsIndices, that.metricConflictsIndices) - && Objects.equals(meta, that.meta); + && Objects.equals(meta, that.meta) + && Objects.equals(supportedAggregations, that.supportedAggregations); } @Override public int hashCode() { - int result = Objects.hash(name, type, isMetadataField, isSearchable, isAggregatable, isDimension, metricType, meta); + int result = Objects.hash( + name, + type, + isMetadataField, + isSearchable, + isAggregatable, + isDimension, + metricType, + meta, + supportedAggregations + ); result = 31 * result + Arrays.hashCode(indices); result = 31 * result + Arrays.hashCode(nonSearchableIndices); result = 31 * result + Arrays.hashCode(nonAggregatableIndices); @@ -474,7 +504,7 @@ public String toString() { } static FieldCapabilities buildBasic(String field, String type, String[] indices) { - return new FieldCapabilities(field, type, false, false, false, false, null, indices, null, null, null, null, Map.of()); + return new FieldCapabilities(field, type, false, false, false, false, null, indices, null, null, null, null, Map.of(), Set.of()); } static class Builder { @@ -522,7 +552,8 @@ void add( boolean agg, boolean isDimension, TimeSeriesParams.MetricType metricType, - Map meta + Map meta, + Set supportedAggregations ) { assert assertIndicesSorted(indices); totalIndices += indices.length; @@ -544,7 +575,7 @@ void add( hasConflictMetricType = true; this.metricType = null; } - indicesList.add(new IndexCaps(indices, search, agg, isDimension, metricType)); + indicesList.add(new IndexCaps(indices, search, agg, isDimension, metricType, supportedAggregations)); for (Map.Entry entry : meta.entrySet()) { this.meta.computeIfAbsent(entry.getKey(), key -> new HashSet<>()).add(entry.getValue()); } @@ -613,6 +644,14 @@ FieldCapabilities build(boolean withIndices) { Map> immutableMeta = meta.entrySet() .stream() .collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, entryValueFunction.andThen(Set::copyOf))); + + var supportedAggregations = indicesList.get(0).supportedAggregations(); + if (indicesList.size() > 1) { + for (int i = 1; i < indicesList.size(); i++) { + supportedAggregations = Sets.intersection(supportedAggregations, indicesList.get(i).supportedAggregations()); + } + } + return new FieldCapabilities( name, type, @@ -626,7 +665,8 @@ FieldCapabilities build(boolean withIndices) { nonAggregatableIndices, nonDimensionIndices, metricConflictsIndices, - immutableMeta + immutableMeta, + supportedAggregations ); } } @@ -636,6 +676,7 @@ private record IndexCaps( boolean isSearchable, boolean isAggregatable, boolean isDimension, - TimeSeriesParams.MetricType metricType + TimeSeriesParams.MetricType metricType, + Set supportedAggregations ) {} } diff --git a/server/src/main/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesFetcher.java b/server/src/main/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesFetcher.java index ec03a4465eeae..4712315902718 100644 --- a/server/src/main/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesFetcher.java +++ b/server/src/main/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesFetcher.java @@ -117,6 +117,8 @@ static Map retrieveFieldCaps( for (String field : fieldNames) { MappedFieldType ft = context.getFieldType(field); if (filter.test(ft)) { + var valuesSourceType = context.getForField(ft, MappedFieldType.FielddataOperation.SEARCH).getValuesSourceType(); + Set supportedAggregations = context.getValuesSourceRegistry().getSupportedAggregations(valuesSourceType); IndexFieldCapabilities fieldCap = new IndexFieldCapabilities( field, ft.familyTypeName(), @@ -125,6 +127,7 @@ static Map retrieveFieldCaps( ft.isAggregatable(), isTimeSeriesIndex ? ft.isDimension() : false, isTimeSeriesIndex ? ft.getMetricType() : null, + supportedAggregations, ft.meta() ); responseMap.put(field, fieldCap); @@ -155,6 +158,7 @@ static Map retrieveFieldCaps( false, false, null, + Set.of(), Collections.emptyMap() ); responseMap.put(parentField, fieldCap); diff --git a/server/src/main/java/org/elasticsearch/action/fieldcaps/IndexFieldCapabilities.java b/server/src/main/java/org/elasticsearch/action/fieldcaps/IndexFieldCapabilities.java index 9b3b7cd08c6cc..ffaefe0cc6851 100644 --- a/server/src/main/java/org/elasticsearch/action/fieldcaps/IndexFieldCapabilities.java +++ b/server/src/main/java/org/elasticsearch/action/fieldcaps/IndexFieldCapabilities.java @@ -18,6 +18,7 @@ import java.io.IOException; import java.util.Map; import java.util.Objects; +import java.util.Set; /** * Describes the capabilities of a field in a single index. @@ -33,14 +34,16 @@ public class IndexFieldCapabilities implements Writeable { private final boolean isAggregatable; private final boolean isDimension; private final TimeSeriesParams.MetricType metricType; + private final Set supportedAggregations; private final Map meta; /** - * @param name The name of the field. - * @param type The type associated with the field. - * @param isSearchable Whether this field is indexed for search. - * @param isAggregatable Whether this field can be aggregated on. - * @param meta Metadata about the field. + * @param name The name of the field. + * @param type The type associated with the field. + * @param isSearchable Whether this field is indexed for search. + * @param isAggregatable Whether this field can be aggregated on. + * @param supportedAggregations + * @param meta Metadata about the field. */ IndexFieldCapabilities( String name, @@ -50,6 +53,7 @@ public class IndexFieldCapabilities implements Writeable { boolean isAggregatable, boolean isDimension, TimeSeriesParams.MetricType metricType, + Set supportedAggregations, Map meta ) { this.name = name; @@ -59,6 +63,7 @@ public class IndexFieldCapabilities implements Writeable { this.isAggregatable = isAggregatable; this.isDimension = isDimension; this.metricType = metricType; + this.supportedAggregations = Objects.requireNonNull(supportedAggregations); this.meta = meta; } @@ -75,6 +80,11 @@ public class IndexFieldCapabilities implements Writeable { this.isDimension = false; this.metricType = null; } + if (in.getTransportVersion().onOrAfter(TransportVersion.V_8_8_0)) { + this.supportedAggregations = in.readSet(StreamInput::readString); + } else { + this.supportedAggregations = Set.of(); + } this.meta = in.readMap(StreamInput::readString, StreamInput::readString); } @@ -89,6 +99,9 @@ public void writeTo(StreamOutput out) throws IOException { out.writeBoolean(isDimension); out.writeOptionalEnum(metricType); } + if (out.getTransportVersion().onOrAfter(TransportVersion.V_8_8_0)) { + out.writeCollection(supportedAggregations, StreamOutput::writeString); + } out.writeMap(meta, StreamOutput::writeString, StreamOutput::writeString); } @@ -124,6 +137,10 @@ public Map meta() { return meta; } + public Set getSupportedAggregations() { + return supportedAggregations; + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -136,11 +153,22 @@ public boolean equals(Object o) { && Objects.equals(metricType, that.metricType) && Objects.equals(name, that.name) && Objects.equals(type, that.type) + && Objects.equals(supportedAggregations, that.supportedAggregations) && Objects.equals(meta, that.meta); } @Override public int hashCode() { - return Objects.hash(name, type, isMetadatafield, isSearchable, isAggregatable, isDimension, metricType, meta); + return Objects.hash( + name, + type, + isMetadatafield, + isSearchable, + isAggregatable, + isDimension, + metricType, + supportedAggregations, + meta + ); } } diff --git a/server/src/main/java/org/elasticsearch/action/fieldcaps/TransportFieldCapabilitiesAction.java b/server/src/main/java/org/elasticsearch/action/fieldcaps/TransportFieldCapabilitiesAction.java index 9ade92242184c..3057d9ba03668 100644 --- a/server/src/main/java/org/elasticsearch/action/fieldcaps/TransportFieldCapabilitiesAction.java +++ b/server/src/main/java/org/elasticsearch/action/fieldcaps/TransportFieldCapabilitiesAction.java @@ -378,7 +378,8 @@ private void innerMerge( fieldCap.isAggregatable(), fieldCap.isDimension(), fieldCap.getMetricType(), - fieldCap.meta() + fieldCap.meta(), + fieldCap.getSupportedAggregations() ); } } diff --git a/server/src/main/java/org/elasticsearch/search/aggregations/support/ValuesSourceRegistry.java b/server/src/main/java/org/elasticsearch/search/aggregations/support/ValuesSourceRegistry.java index 827ed32aff09a..81c5a80625fde 100644 --- a/server/src/main/java/org/elasticsearch/search/aggregations/support/ValuesSourceRegistry.java +++ b/server/src/main/java/org/elasticsearch/search/aggregations/support/ValuesSourceRegistry.java @@ -14,9 +14,11 @@ import java.util.AbstractMap; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Set; /** * {@link ValuesSourceRegistry} holds the mapping from {@link ValuesSourceType}s to functions for building aggregation components. DO NOT @@ -150,7 +152,8 @@ public ValuesSourceRegistry build() { /** Maps Aggregation names to (ValuesSourceType, Supplier) pairs, keyed by ValuesSourceType */ private final AggregationUsageService usageService; - private Map, Map> aggregatorRegistry; + private final Map, Map> aggregatorRegistry; + private final Map> supportedAggsByValueSourceType; public ValuesSourceRegistry( Map, List>> aggregatorRegistry, @@ -158,6 +161,29 @@ public ValuesSourceRegistry( ) { this.aggregatorRegistry = copyMap(aggregatorRegistry); this.usageService = usageService; + + // First find all unique values source types: + Set supportedTypes = new HashSet<>(); + for (var entryList : aggregatorRegistry.values()) { + for (var entry : entryList) { + supportedTypes.add(entry.getKey()); + } + } + // Per value source type create an immutable set of supported aggregations: + Map> supportedAggsByValueSourceType = new HashMap<>(); + for (ValuesSourceType supportedType : supportedTypes) { + Set supportedAggs = new HashSet<>(); + for (var entry : aggregatorRegistry.entrySet()) { + for (var e : entry.getValue()) { + if (supportedType == e.getKey()) { + supportedAggs.add(entry.getKey().getName()); + break; + } + } + } + supportedAggsByValueSourceType.put(supportedType, Set.copyOf(supportedAggs)); + } + this.supportedAggsByValueSourceType = Map.copyOf(supportedAggsByValueSourceType); } public boolean isRegistered(RegistryKey registryKey) { @@ -188,6 +214,10 @@ public T getAggregator(RegistryKey registryKey, ValuesSourceConfig values ); } + public Set getSupportedAggregations(ValuesSourceType valuesSourceType) { + return supportedAggsByValueSourceType.getOrDefault(valuesSourceType, Set.of()); + } + public AggregationUsageService getUsageService() { return usageService; } diff --git a/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesIndexResponseTests.java b/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesIndexResponseTests.java index 0f5ba959c5ed8..bcc26427c44b0 100644 --- a/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesIndexResponseTests.java +++ b/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesIndexResponseTests.java @@ -37,6 +37,7 @@ static Map randomFieldCaps() { randomBoolean(), randomBoolean(), metricType, + randomSet(0, 150, () -> randomAlphaOfLength(8)), meta ); fieldCaps.put(field, fieldCap); diff --git a/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesNodeResponseTests.java b/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesNodeResponseTests.java index d3d7cf43bfde9..0511b86d41f3c 100644 --- a/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesNodeResponseTests.java +++ b/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesNodeResponseTests.java @@ -189,9 +189,9 @@ public void testReadNodeResponseFromPre82() throws Exception { null, Map.of( "red_field", - new IndexFieldCapabilities("red_field", "text", false, true, false, false, null, Map.of()), + new IndexFieldCapabilities("red_field", "text", false, true, false, false, null, Set.of(), Map.of()), "blue_field", - new IndexFieldCapabilities("blue_field", "long", false, true, true, false, null, Map.of()) + new IndexFieldCapabilities("blue_field", "long", false, true, true, false, null, Set.of(), Map.of()) ), true ), @@ -201,9 +201,9 @@ public void testReadNodeResponseFromPre82() throws Exception { null, Map.of( "yellow_field", - new IndexFieldCapabilities("yellow_field", "keyword", false, true, true, false, null, Map.of()), + new IndexFieldCapabilities("yellow_field", "keyword", false, true, true, false, null, Set.of(), Map.of()), "_seq_no", - new IndexFieldCapabilities("_seq_no", "long", true, true, true, false, null, Map.of()) + new IndexFieldCapabilities("_seq_no", "long", true, true, true, false, null, Set.of(), Map.of()) ), true ) diff --git a/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesResponseTests.java b/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesResponseTests.java index 0f30b9f3b43f3..7c7e116146952 100644 --- a/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesResponseTests.java +++ b/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesResponseTests.java @@ -33,6 +33,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; import static org.elasticsearch.action.fieldcaps.FieldCapabilitiesIndexResponseTests.randomIndexResponsesWithMappingHash; @@ -262,9 +263,9 @@ public void testReadCCSResponseFromPre82() throws Exception { null, Map.of( "red_field", - new IndexFieldCapabilities("red_field", "text", false, true, false, false, null, Map.of()), + new IndexFieldCapabilities("red_field", "text", false, true, false, false, null, Set.of(), Map.of()), "blue_field", - new IndexFieldCapabilities("blue_field", "long", false, true, true, false, null, Map.of()) + new IndexFieldCapabilities("blue_field", "long", false, true, true, false, null, Set.of(), Map.of()) ), true ), @@ -274,9 +275,9 @@ public void testReadCCSResponseFromPre82() throws Exception { null, Map.of( "yellow_field", - new IndexFieldCapabilities("yellow_field", "keyword", false, true, true, false, null, Map.of()), + new IndexFieldCapabilities("yellow_field", "keyword", false, true, true, false, null, Set.of(), Map.of()), "_seq_no", - new IndexFieldCapabilities("_seq_no", "long", true, true, true, false, null, Map.of()) + new IndexFieldCapabilities("_seq_no", "long", true, true, true, false, null, Set.of(), Map.of()) ), true ) diff --git a/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesTests.java b/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesTests.java index cdad234c73e97..d98ab67f3c8ba 100644 --- a/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesTests.java +++ b/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesTests.java @@ -49,9 +49,9 @@ protected Writeable.Reader instanceReader() { public void testBuilder() { FieldCapabilities.Builder builder = new FieldCapabilities.Builder("field", "type"); - builder.add(new String[] { "index1" }, false, true, false, false, null, Collections.emptyMap()); - builder.add(new String[] { "index2" }, false, true, false, false, null, Collections.emptyMap()); - builder.add(new String[] { "index3" }, false, true, false, false, null, Collections.emptyMap()); + builder.add(new String[] { "index1" }, false, true, false, false, null, Map.of(), Set.of()); + builder.add(new String[] { "index2" }, false, true, false, false, null, Map.of(), Set.of()); + builder.add(new String[] { "index3" }, false, true, false, false, null, Map.of(), Set.of()); { FieldCapabilities cap1 = builder.build(false); @@ -79,9 +79,9 @@ public void testBuilder() { } builder = new FieldCapabilities.Builder("field", "type"); - builder.add(new String[] { "index1" }, false, false, true, true, null, Collections.emptyMap()); - builder.add(new String[] { "index2" }, false, true, false, false, TimeSeriesParams.MetricType.COUNTER, Collections.emptyMap()); - builder.add(new String[] { "index3" }, false, false, false, false, null, Collections.emptyMap()); + builder.add(new String[] { "index1" }, false, false, true, true, null, Map.of(), Set.of()); + builder.add(new String[] { "index2" }, false, true, false, false, TimeSeriesParams.MetricType.COUNTER, Map.of(), Set.of()); + builder.add(new String[] { "index3" }, false, false, false, false, null, Map.of(), Set.of()); { FieldCapabilities cap1 = builder.build(false); assertThat(cap1.isSearchable(), equalTo(false)); @@ -108,9 +108,27 @@ public void testBuilder() { } builder = new FieldCapabilities.Builder("field", "type"); - builder.add(new String[] { "index1" }, false, true, true, true, TimeSeriesParams.MetricType.COUNTER, Collections.emptyMap()); - builder.add(new String[] { "index2" }, false, true, true, true, TimeSeriesParams.MetricType.COUNTER, Map.of("foo", "bar")); - builder.add(new String[] { "index3" }, false, true, true, true, TimeSeriesParams.MetricType.COUNTER, Map.of("foo", "quux")); + builder.add(new String[] { "index1" }, false, true, true, true, TimeSeriesParams.MetricType.COUNTER, Map.of(), Set.of()); + builder.add( + new String[] { "index2" }, + false, + true, + true, + true, + TimeSeriesParams.MetricType.COUNTER, + Map.of("foo", "bar"), + Set.of() + ); + builder.add( + new String[] { "index3" }, + false, + true, + true, + true, + TimeSeriesParams.MetricType.COUNTER, + Map.of("foo", "quux"), + Set.of() + ); { FieldCapabilities cap1 = builder.build(false); assertThat(cap1.isSearchable(), equalTo(true)); @@ -137,9 +155,18 @@ public void testBuilder() { } builder = new FieldCapabilities.Builder("field", "type"); - builder.add(new String[] { "index1" }, false, true, true, true, TimeSeriesParams.MetricType.COUNTER, Collections.emptyMap()); - builder.add(new String[] { "index2" }, false, true, true, true, TimeSeriesParams.MetricType.GAUGE, Map.of("foo", "bar")); - builder.add(new String[] { "index3" }, false, true, true, true, TimeSeriesParams.MetricType.COUNTER, Map.of("foo", "quux")); + builder.add(new String[] { "index1" }, false, true, true, true, TimeSeriesParams.MetricType.COUNTER, Map.of(), Set.of()); + builder.add(new String[] { "index2" }, false, true, true, true, TimeSeriesParams.MetricType.GAUGE, Map.of("foo", "bar"), Set.of()); + builder.add( + new String[] { "index3" }, + false, + true, + true, + true, + TimeSeriesParams.MetricType.COUNTER, + Map.of("foo", "quux"), + Set.of() + ); { FieldCapabilities cap1 = builder.build(false); assertThat(cap1.isSearchable(), equalTo(true)); @@ -189,7 +216,7 @@ public void testRandomBuilder() { if (isDimension == false) { nonDimensionIndices.addAll(Arrays.asList(groupIndices)); } - builder.add(groupIndices, false, searchable, aggregatable, isDimension, null, Map.of()); + builder.add(groupIndices, false, searchable, aggregatable, isDimension, null, Map.of(), Set.of()); i += bulkSize; } boolean withIndices = randomBoolean(); @@ -240,7 +267,16 @@ public void testBuilderSingleMetricType() { TimeSeriesParams.MetricType metric = randomBoolean() ? null : randomFrom(TimeSeriesParams.MetricType.values()); FieldCapabilities.Builder builder = new FieldCapabilities.Builder("field", "type"); for (String index : indices) { - builder.add(new String[] { index }, randomBoolean(), randomBoolean(), randomBoolean(), randomBoolean(), metric, Map.of()); + builder.add( + new String[] { index }, + randomBoolean(), + randomBoolean(), + randomBoolean(), + randomBoolean(), + metric, + Map.of(), + Set.of() + ); } FieldCapabilities fieldCaps = builder.build(randomBoolean()); assertThat(fieldCaps.getMetricType(), equalTo(metric)); @@ -264,7 +300,8 @@ public void testBuilderMixedMetricType() { randomBoolean(), randomBoolean(), metricTypes.get(index), - Map.of() + Map.of(), + Set.of() ); } FieldCapabilities fieldCaps = builder.build(randomBoolean()); @@ -291,7 +328,8 @@ public void testOutOfOrderIndices() { randomBoolean(), randomBoolean(), randomFrom(TimeSeriesParams.MetricType.values()), - Map.of() + Map.of(), + Set.of() ); } final String outOfOrderIndex = randomBoolean() ? "abc" : "index-" + randomIntBetween(1, numIndex); @@ -303,7 +341,8 @@ public void testOutOfOrderIndices() { randomBoolean(), randomBoolean(), randomFrom(TimeSeriesParams.MetricType.values()), - Map.of() + Map.of(), + Set.of() ); }); assertThat(error.getMessage(), containsString("indices aren't sorted")); @@ -367,7 +406,8 @@ static FieldCapabilities randomFieldCaps(String fieldName) { nonAggregatableIndices, nonDimensionIndices, metricConflictsIndices, - meta + meta, + Set.of() ); } @@ -514,7 +554,8 @@ protected FieldCapabilities mutateInstance(FieldCapabilities instance) { nonAggregatableIndices, nonDimensionIndices, metricConflictsIndices, - meta + meta, + Set.of() ); } } diff --git a/server/src/test/java/org/elasticsearch/action/fieldcaps/MergedFieldCapabilitiesResponseTests.java b/server/src/test/java/org/elasticsearch/action/fieldcaps/MergedFieldCapabilitiesResponseTests.java index 36c8a05b02268..bf5bc40b5c2b1 100644 --- a/server/src/test/java/org/elasticsearch/action/fieldcaps/MergedFieldCapabilitiesResponseTests.java +++ b/server/src/test/java/org/elasticsearch/action/fieldcaps/MergedFieldCapabilitiesResponseTests.java @@ -19,6 +19,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.function.Predicate; public class MergedFieldCapabilitiesResponseTests extends AbstractChunkedSerializingTestCase { @@ -153,7 +154,22 @@ private static FieldCapabilitiesResponse createSimpleResponse() { Map titleCapabilities = new HashMap<>(); titleCapabilities.put( "text", - new FieldCapabilities("title", "text", false, true, false, false, null, null, null, null, null, null, Collections.emptyMap()) + new FieldCapabilities( + "title", + "text", + false, + true, + false, + false, + null, + null, + null, + null, + null, + null, + Collections.emptyMap(), + Set.of() + ) ); Map ratingCapabilities = new HashMap<>(); @@ -172,7 +188,8 @@ private static FieldCapabilitiesResponse createSimpleResponse() { new String[] { "index1" }, new String[] { "index4" }, null, - Collections.emptyMap() + Collections.emptyMap(), + Set.of() ) ); ratingCapabilities.put( @@ -190,7 +207,8 @@ private static FieldCapabilitiesResponse createSimpleResponse() { null, null, null, - Collections.emptyMap() + Collections.emptyMap(), + Set.of() ) ); diff --git a/server/src/test/java/org/elasticsearch/action/fieldcaps/ResponseRewriterTests.java b/server/src/test/java/org/elasticsearch/action/fieldcaps/ResponseRewriterTests.java index 9264db0c5aefc..641f90abbca73 100644 --- a/server/src/test/java/org/elasticsearch/action/fieldcaps/ResponseRewriterTests.java +++ b/server/src/test/java/org/elasticsearch/action/fieldcaps/ResponseRewriterTests.java @@ -14,6 +14,7 @@ import java.util.Collections; import java.util.Map; +import java.util.Set; public class ResponseRewriterTests extends ESTestCase { @@ -146,7 +147,7 @@ public void testAllowedTypes() { } private static IndexFieldCapabilities fieldCaps(String name, String type, boolean isMetadata) { - return new IndexFieldCapabilities(name, type, isMetadata, true, true, false, null, Collections.emptyMap()); + return new IndexFieldCapabilities(name, type, isMetadata, true, true, false, null, Set.of(), Collections.emptyMap()); } } From 24c51300b221e4adb579e5303537278908713351 Mon Sep 17 00:00:00 2001 From: Martijn van Groningen Date: Fri, 17 Feb 2023 16:55:25 +0100 Subject: [PATCH 2/5] iter --- .../fieldcaps/FieldCapabilitiesFetcher.java | 9 +++- .../support/ValuesSourceRegistry.java | 51 ++++++++++--------- 2 files changed, 35 insertions(+), 25 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesFetcher.java b/server/src/main/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesFetcher.java index 4712315902718..c7e960d4b8d3d 100644 --- a/server/src/main/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesFetcher.java +++ b/server/src/main/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesFetcher.java @@ -117,8 +117,13 @@ static Map retrieveFieldCaps( for (String field : fieldNames) { MappedFieldType ft = context.getFieldType(field); if (filter.test(ft)) { - var valuesSourceType = context.getForField(ft, MappedFieldType.FielddataOperation.SEARCH).getValuesSourceType(); - Set supportedAggregations = context.getValuesSourceRegistry().getSupportedAggregations(valuesSourceType); + Set supportedAggregations; + if (ft.isAggregatable()) { + var valuesSourceType = context.getForField(ft, MappedFieldType.FielddataOperation.SEARCH).getValuesSourceType(); + supportedAggregations = context.getValuesSourceRegistry().getSupportedAggregations(valuesSourceType); + } else { + supportedAggregations = Set.of(); + } IndexFieldCapabilities fieldCap = new IndexFieldCapabilities( field, ft.familyTypeName(), diff --git a/server/src/main/java/org/elasticsearch/search/aggregations/support/ValuesSourceRegistry.java b/server/src/main/java/org/elasticsearch/search/aggregations/support/ValuesSourceRegistry.java index 81c5a80625fde..7113ac7eef17b 100644 --- a/server/src/main/java/org/elasticsearch/search/aggregations/support/ValuesSourceRegistry.java +++ b/server/src/main/java/org/elasticsearch/search/aggregations/support/ValuesSourceRegistry.java @@ -161,29 +161,7 @@ public ValuesSourceRegistry( ) { this.aggregatorRegistry = copyMap(aggregatorRegistry); this.usageService = usageService; - - // First find all unique values source types: - Set supportedTypes = new HashSet<>(); - for (var entryList : aggregatorRegistry.values()) { - for (var entry : entryList) { - supportedTypes.add(entry.getKey()); - } - } - // Per value source type create an immutable set of supported aggregations: - Map> supportedAggsByValueSourceType = new HashMap<>(); - for (ValuesSourceType supportedType : supportedTypes) { - Set supportedAggs = new HashSet<>(); - for (var entry : aggregatorRegistry.entrySet()) { - for (var e : entry.getValue()) { - if (supportedType == e.getKey()) { - supportedAggs.add(entry.getKey().getName()); - break; - } - } - } - supportedAggsByValueSourceType.put(supportedType, Set.copyOf(supportedAggs)); - } - this.supportedAggsByValueSourceType = Map.copyOf(supportedAggsByValueSourceType); + this.supportedAggsByValueSourceType = buildSupportedAggregations(aggregatorRegistry); } public boolean isRegistered(RegistryKey registryKey) { @@ -221,4 +199,31 @@ public Set getSupportedAggregations(ValuesSourceType valuesSourceType) { public AggregationUsageService getUsageService() { return usageService; } + + private static Map> buildSupportedAggregations( + Map, List>> aggregatorRegistry + ) { + // First find all unique values source types: + Set supportedTypes = new HashSet<>(); + for (var entryList : aggregatorRegistry.values()) { + for (var entry : entryList) { + supportedTypes.add(entry.getKey()); + } + } + // Per value source type create an immutable set of supported aggregations: + Map> supportedAggsByValueSourceType = new HashMap<>(); + for (var supportedType : supportedTypes) { + Set supportedAggs = new HashSet<>(); + for (var entry : aggregatorRegistry.entrySet()) { + for (var e : entry.getValue()) { + if (supportedType == e.getKey()) { + supportedAggs.add(entry.getKey().getName()); + break; + } + } + } + supportedAggsByValueSourceType.put(supportedType, Set.copyOf(supportedAggs)); + } + return Map.copyOf(supportedAggsByValueSourceType); + } } From 8bf158e15a89ea03786d5a0ad88df5a86e583a42 Mon Sep 17 00:00:00 2001 From: Martijn van Groningen Date: Sat, 18 Feb 2023 15:13:09 +0100 Subject: [PATCH 3/5] Data tiers don't support aggregating and this failed listing supported aggregations --- .../org/elasticsearch/index/mapper/ConstantFieldType.java | 5 ----- .../routing/allocation/mapper/DataTierFieldMapper.java | 6 ++++++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/index/mapper/ConstantFieldType.java b/server/src/main/java/org/elasticsearch/index/mapper/ConstantFieldType.java index 1f8e7fc77b072..72eefc1ec0b33 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/ConstantFieldType.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/ConstantFieldType.java @@ -35,11 +35,6 @@ public ConstantFieldType(String name, Map meta) { assert isSearchable(); } - @Override - public final boolean isAggregatable() { - return true; - } - /** * Return whether the constant value of this field matches the provided {@code pattern} * as documented in {@link Regex#simpleMatch}. diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/cluster/routing/allocation/mapper/DataTierFieldMapper.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/cluster/routing/allocation/mapper/DataTierFieldMapper.java index 9cfa9be606239..4d47f558e985f 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/cluster/routing/allocation/mapper/DataTierFieldMapper.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/cluster/routing/allocation/mapper/DataTierFieldMapper.java @@ -50,6 +50,12 @@ public String familyTypeName() { return KeywordFieldMapper.CONTENT_TYPE; } + @Override + public boolean isAggregatable() { + // Doesn't support field data (yet) and therefor attempting to aggregate on field of this field type fail + return false; + } + @Override protected boolean matches(String pattern, boolean caseInsensitive, SearchExecutionContext context) { if (caseInsensitive) { From 091dcb88023ba77e94d42d0ccd26552a4db0480e Mon Sep 17 00:00:00 2001 From: Martijn van Groningen Date: Sun, 19 Feb 2023 21:33:22 +0100 Subject: [PATCH 4/5] iter --- .../action/fieldcaps/FieldCapabilities.java | 17 ++++++++++++----- .../fieldcaps/FieldCapabilitiesFilterTests.java | 11 +++++++++++ .../FieldCapabilitiesNodeResponseTests.java | 2 +- .../FieldCapabilitiesResponseTests.java | 8 ++++++-- .../fieldcaps/FieldCapabilitiesTests.java | 4 ++-- .../MergedFieldCapabilitiesResponseTests.java | 9 ++++++--- .../index/mapper/MapperServiceTestCase.java | 3 ++- 7 files changed, 40 insertions(+), 14 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/action/fieldcaps/FieldCapabilities.java b/server/src/main/java/org/elasticsearch/action/fieldcaps/FieldCapabilities.java index 38bbfa8bd4965..3a2e4d71ee246 100644 --- a/server/src/main/java/org/elasticsearch/action/fieldcaps/FieldCapabilities.java +++ b/server/src/main/java/org/elasticsearch/action/fieldcaps/FieldCapabilities.java @@ -58,7 +58,6 @@ public class FieldCapabilities implements Writeable, ToXContentObject { private static final ParseField NON_DIMENSION_INDICES_FIELD = new ParseField("non_dimension_indices"); private static final ParseField METRIC_CONFLICTS_INDICES_FIELD = new ParseField("metric_conflicts_indices"); private static final ParseField META_FIELD = new ParseField("meta"); - private static final ParseField SUPPORTED_AGGREGATIONS = new ParseField("supported_aggregations"); private final String name; @@ -211,7 +210,8 @@ public FieldCapabilities( List nonAggregatableIndices, List nonDimensionIndices, List metricConflictsIndices, - Map> meta + Map> meta, + List supportedAggregations ) { this( name, @@ -227,7 +227,7 @@ public FieldCapabilities( nonDimensionIndices != null ? nonDimensionIndices.toArray(new String[0]) : null, metricConflictsIndices != null ? metricConflictsIndices.toArray(new String[0]) : null, meta != null ? meta : Collections.emptyMap(), - Set.of() + supportedAggregations != null ? new HashSet<>(supportedAggregations) : Set.of() ); } @@ -323,9 +323,11 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws } builder.endObject(); } - if (isAggregatable) { - builder.array(SUPPORTED_AGGREGATIONS.getPreferredName(), supportedAggregations); + builder.startArray(SUPPORTED_AGGREGATIONS.getPreferredName()); + for (String supportedAggregation : supportedAggregations) { + builder.value(supportedAggregation); } + builder.endArray(); builder.endObject(); return builder; } @@ -359,6 +361,7 @@ public static FieldCapabilities fromXContent(String name, XContentParser parser) (p, context) -> p.map(HashMap::new, v -> Set.copyOf(v.list())), META_FIELD ); + parser.declareStringArray(ConstructingObjectParser.optionalConstructorArg(), SUPPORTED_AGGREGATIONS); PARSER = parser.build(); } @@ -456,6 +459,10 @@ public Map> meta() { return meta; } + public Set getSupportedAggregations() { + return supportedAggregations; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesFilterTests.java b/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesFilterTests.java index d0ca8a7bf5d33..dbf2da0b3506b 100644 --- a/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesFilterTests.java +++ b/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesFilterTests.java @@ -19,6 +19,12 @@ public class FieldCapabilitiesFilterTests extends MapperServiceTestCase { + // Note: side effect of loading field data: + static final String EXPECTED_WARNING_ID_FIELD = + "Loading the fielddata on the _id field is deprecated and will be removed in future versions. " + + "If you require sorting or aggregating on this field you should also include the id in the " + + "body of your documents, and map this field as a keyword field that has [doc_values] enabled"; + public void testExcludeNestedFields() throws IOException { MapperService mapperService = createMapperService(""" { "_doc" : { @@ -48,6 +54,7 @@ public void testExcludeNestedFields() throws IOException { assertNotNull(response.get("field4")); assertNull(response.get("field2")); assertNull(response.get("field2.field3")); + assertWarnings(EXPECTED_WARNING_ID_FIELD); } public void testMetadataFilters() throws IOException { @@ -83,6 +90,7 @@ public void testMetadataFilters() throws IOException { assertNull(response.get("_index")); assertNotNull(response.get("field1")); } + assertWarnings(EXPECTED_WARNING_ID_FIELD); } public void testExcludeMultifields() throws IOException { @@ -116,6 +124,7 @@ public void testExcludeMultifields() throws IOException { assertNotNull(response.get("field2")); assertNotNull(response.get("field2.keyword")); assertNotNull(response.get("_index")); + assertWarnings(EXPECTED_WARNING_ID_FIELD); } public void testDontIncludeParentInfo() throws IOException { @@ -143,6 +152,7 @@ public void testDontIncludeParentInfo() throws IOException { assertNotNull(response.get("parent.field1")); assertNotNull(response.get("parent.field2")); assertNull(response.get("parent")); + assertWarnings(EXPECTED_WARNING_ID_FIELD); } public void testSecurityFilter() throws IOException { @@ -185,6 +195,7 @@ public void testSecurityFilter() throws IOException { assertNull(response.get("forbidden")); assertNull(response.get("_index")); // -metadata filter applies on top } + assertWarnings(EXPECTED_WARNING_ID_FIELD); } public void testFieldTypeFiltering() throws IOException { diff --git a/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesNodeResponseTests.java b/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesNodeResponseTests.java index 0511b86d41f3c..d1bf2250fe14e 100644 --- a/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesNodeResponseTests.java +++ b/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesNodeResponseTests.java @@ -99,7 +99,7 @@ public void testSerializeNodeResponseBetweenNewNodes() throws Exception { FieldCapabilitiesNodeResponse inNode = randomNodeResponse(indexResponses); final TransportVersion version = TransportVersionUtils.randomVersionBetween( random(), - TransportVersion.V_8_2_0, + TransportVersion.V_8_8_0, TransportVersion.CURRENT ); final FieldCapabilitiesNodeResponse outNode = copyInstance(inNode, version); diff --git a/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesResponseTests.java b/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesResponseTests.java index 7c7e116146952..6158b46edee40 100644 --- a/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesResponseTests.java +++ b/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesResponseTests.java @@ -170,7 +170,7 @@ public void testSerializeCCSResponseBetweenNewClusters() throws Exception { FieldCapabilitiesResponse inResponse = randomCCSResponse(indexResponses); final TransportVersion version = TransportVersionUtils.randomVersionBetween( random(), - TransportVersion.V_8_2_0, + TransportVersion.V_8_8_0, TransportVersion.CURRENT ); final FieldCapabilitiesResponse outResponse = copyInstance(inResponse, version); @@ -229,7 +229,7 @@ public void testSerializeCCSResponseBetweenOldClusters() throws IOException { assertThat(outList.get(i).canMatch(), equalTo(inList.get(i).canMatch())); Map outCap = outList.get(i).get(); Map inCap = inList.get(i).get(); - if (version.onOrAfter(TransportVersion.V_8_0_0)) { + if (version.onOrAfter(TransportVersion.V_8_8_0)) { assertThat(outCap, equalTo(inCap)); } else { // Exclude metric types which was introduced in 8.0 @@ -240,6 +240,10 @@ public void testSerializeCCSResponseBetweenOldClusters() throws IOException { assertThat(outCap.get(field).isSearchable(), equalTo(inCap.get(field).isSearchable())); assertThat(outCap.get(field).isAggregatable(), equalTo(inCap.get(field).isAggregatable())); assertThat(outCap.get(field).meta(), equalTo(inCap.get(field).meta())); + if (version.onOrAfter(TransportVersion.V_8_0_0)) { + assertThat(outCap.get(field).isDimension(), equalTo(inCap.get(field).isDimension())); + assertThat(outCap.get(field).getMetricType(), equalTo(inCap.get(field).getMetricType())); + } } } } diff --git a/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesTests.java b/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesTests.java index d98ab67f3c8ba..b2a69f094ebb5 100644 --- a/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesTests.java +++ b/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesTests.java @@ -407,7 +407,7 @@ static FieldCapabilities randomFieldCaps(String fieldName) { nonDimensionIndices, metricConflictsIndices, meta, - Set.of() + randomSet(0, 5, () -> randomAlphaOfLength(8)) ); } @@ -555,7 +555,7 @@ protected FieldCapabilities mutateInstance(FieldCapabilities instance) { nonDimensionIndices, metricConflictsIndices, meta, - Set.of() + instance.getSupportedAggregations() ); } } diff --git a/server/src/test/java/org/elasticsearch/action/fieldcaps/MergedFieldCapabilitiesResponseTests.java b/server/src/test/java/org/elasticsearch/action/fieldcaps/MergedFieldCapabilitiesResponseTests.java index bf5bc40b5c2b1..b66327a1216fe 100644 --- a/server/src/test/java/org/elasticsearch/action/fieldcaps/MergedFieldCapabilitiesResponseTests.java +++ b/server/src/test/java/org/elasticsearch/action/fieldcaps/MergedFieldCapabilitiesResponseTests.java @@ -112,7 +112,8 @@ public void testToXContent() throws IOException { "aggregatable": true, "time_series_dimension": true, "indices": [ "index3", "index4" ], - "non_searchable_indices": [ "index4" ] + "non_searchable_indices": [ "index4" ], + "supported_aggregations": [] }, "long": { "type": "long", @@ -122,7 +123,8 @@ public void testToXContent() throws IOException { "time_series_metric": "counter", "indices": [ "index1", "index2" ], "non_aggregatable_indices": [ "index1" ], - "non_dimension_indices": [ "index4" ] + "non_dimension_indices": [ "index4" ], + "supported_aggregations": [] } }, "title": { @@ -130,7 +132,8 @@ public void testToXContent() throws IOException { "type": "text", "metadata_field": false, "searchable": true, - "aggregatable": false + "aggregatable": false, + "supported_aggregations": [] } } }, diff --git a/test/framework/src/main/java/org/elasticsearch/index/mapper/MapperServiceTestCase.java b/test/framework/src/main/java/org/elasticsearch/index/mapper/MapperServiceTestCase.java index 64873bab78024..90e40d3d4ce1f 100644 --- a/test/framework/src/main/java/org/elasticsearch/index/mapper/MapperServiceTestCase.java +++ b/test/framework/src/main/java/org/elasticsearch/index/mapper/MapperServiceTestCase.java @@ -59,6 +59,7 @@ import org.elasticsearch.search.aggregations.Aggregator; import org.elasticsearch.search.aggregations.MultiBucketConsumerService.MultiBucketConsumer; import org.elasticsearch.search.aggregations.support.AggregationContext; +import org.elasticsearch.search.aggregations.support.AggregationUsageService; import org.elasticsearch.search.aggregations.support.ValuesSourceRegistry; import org.elasticsearch.search.internal.SubSearchContext; import org.elasticsearch.search.lookup.SearchLookup; @@ -655,7 +656,7 @@ public void onRemoval(ShardId shardId, Accountable accountable) { null, null, () -> true, - null, + new ValuesSourceRegistry(Map.of(), new AggregationUsageService.Builder().build()), Collections.emptyMap() ); } From 309bafc770155430523f1588ca71264dba2626e5 Mon Sep 17 00:00:00 2001 From: Martijn van Groningen Date: Tue, 21 Feb 2023 09:27:11 +0100 Subject: [PATCH 5/5] adjust test --- .../fieldcaps/FieldCapabilitiesNodeResponseTests.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesNodeResponseTests.java b/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesNodeResponseTests.java index d1bf2250fe14e..a944ea574a707 100644 --- a/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesNodeResponseTests.java +++ b/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesNodeResponseTests.java @@ -154,7 +154,7 @@ public void testSerializeNodeResponseBetweenOldNodes() throws IOException { assertThat(outList.get(i).canMatch(), equalTo(inList.get(i).canMatch())); Map outCap = outList.get(i).get(); Map inCap = inList.get(i).get(); - if (version.onOrAfter(TransportVersion.V_8_0_0)) { + if (version.onOrAfter(TransportVersion.V_8_8_0)) { assertThat(outCap, equalTo(inCap)); } else { // Exclude metric types which was introduced in 8.0 @@ -165,6 +165,10 @@ public void testSerializeNodeResponseBetweenOldNodes() throws IOException { assertThat(outCap.get(field).isSearchable(), equalTo(inCap.get(field).isSearchable())); assertThat(outCap.get(field).isAggregatable(), equalTo(inCap.get(field).isAggregatable())); assertThat(outCap.get(field).meta(), equalTo(inCap.get(field).meta())); + if (version.onOrAfter(TransportVersion.V_8_0_0)) { + assertThat(outCap.get(field).getMetricType(), equalTo(inCap.get(field).getMetricType())); + assertThat(outCap.get(field).isDimension(), equalTo(inCap.get(field).isDimension())); + } } } }