Check bucket metric ages point to a multi bucket agg (#26215)

* Check bucket metric ages point to a multi bucket agg

This adds a validation step to the BucketMetricsPipelineAggregationBuilder which ensure that the first aggregation in the `buckets_path` is a multi-bucket aggregation. It does this using a new `MultiBucketAggregationBuilder` marker interface.

The change also moves the validate of pipeline aggregations to the `AggregatorFactories.build()` method so the validate can inspect sibling `AggregatorBuilder` objects rather than `AggregatorFactory` objects. Further it removes the validate from `AggregatorFactory` since this was never implemented and since aggregators only depend on their own internal state and not on other aggregators they should be validated ideally at setter time but in rare case where this is not possible the validation should be done in the `AggregationBuilder.build()` step.

Closes #25775

Move validate stage to happen during AggregatorFactories.Builder.build

Also removes validate method from normal aggs since it was never used.

* review comment fix
This commit is contained in:
Colin Goodheart-Smithe 2017-08-24 12:05:03 +01:00 committed by GitHub
parent 6b23ee8040
commit c8ca015c0b
32 changed files with 347 additions and 114 deletions

View File

@ -101,7 +101,6 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicLong;
@ -710,7 +709,6 @@ public class SearchService extends AbstractLifecycleComponent implements IndexEv
if (source.aggregations() != null) {
try {
AggregatorFactories factories = source.aggregations().build(context, null);
factories.validate();
context.aggregations(new SearchContextAggregations(factories));
} catch (IOException e) {
throw new AggregationInitializationException("Failed to create aggregators", e);

View File

@ -238,15 +238,6 @@ public class AggregatorFactories {
return pipelineAggregatorFactories.size();
}
public void validate() {
for (AggregatorFactory<?> factory : factories) {
factory.validate();
}
for (PipelineAggregationBuilder factory : pipelineAggregatorFactories) {
factory.validate(parent, factories, pipelineAggregatorFactories);
}
}
public static class Builder implements Writeable, ToXContentObject {
private final Set<String> names = new HashSet<>();
private final List<AggregationBuilder> aggregationBuilders = new ArrayList<>();
@ -330,7 +321,8 @@ public class AggregatorFactories {
if (skipResolveOrder) {
orderedpipelineAggregators = new ArrayList<>(pipelineAggregatorBuilders);
} else {
orderedpipelineAggregators = resolvePipelineAggregatorOrder(this.pipelineAggregatorBuilders, this.aggregationBuilders);
orderedpipelineAggregators = resolvePipelineAggregatorOrder(this.pipelineAggregatorBuilders, this.aggregationBuilders,
parent);
}
AggregatorFactory<?>[] aggFactories = new AggregatorFactory<?>[aggregationBuilders.size()];
for (int i = 0; i < aggregationBuilders.size(); i++) {
@ -340,7 +332,8 @@ public class AggregatorFactories {
}
private List<PipelineAggregationBuilder> resolvePipelineAggregatorOrder(
List<PipelineAggregationBuilder> pipelineAggregatorBuilders, List<AggregationBuilder> aggBuilders) {
List<PipelineAggregationBuilder> pipelineAggregatorBuilders, List<AggregationBuilder> aggBuilders,
AggregatorFactory<?> parent) {
Map<String, PipelineAggregationBuilder> pipelineAggregatorBuildersMap = new HashMap<>();
for (PipelineAggregationBuilder builder : pipelineAggregatorBuilders) {
pipelineAggregatorBuildersMap.put(builder.getName(), builder);
@ -354,6 +347,7 @@ public class AggregatorFactories {
Set<PipelineAggregationBuilder> temporarilyMarked = new HashSet<>();
while (!unmarkedBuilders.isEmpty()) {
PipelineAggregationBuilder builder = unmarkedBuilders.get(0);
builder.validate(parent, aggBuilders, pipelineAggregatorBuilders);
resolvePipelineAggregatorOrder(aggBuildersMap, pipelineAggregatorBuildersMap, orderedPipelineAggregatorrs, unmarkedBuilders,
temporarilyMarked, builder);
}

View File

@ -188,15 +188,6 @@ public abstract class AggregatorFactory<AF extends AggregatorFactory<AF>> {
return name;
}
/**
* Validates the state of this factory (makes sure the factory is properly
* configured)
*/
public final void validate() {
doValidate();
factories.validate();
}
public void doValidate() {
}

View File

@ -68,7 +68,7 @@ public abstract class PipelineAggregationBuilder implements NamedWriteable, Base
* Internal: Validates the state of this factory (makes sure the factory is properly
* configured)
*/
protected abstract void validate(AggregatorFactory<?> parent, AggregatorFactory<?>[] factories,
protected abstract void validate(AggregatorFactory<?> parent, List<AggregationBuilder> factories,
List<PipelineAggregationBuilder> pipelineAggregatorFactories);
/**

View File

@ -0,0 +1,30 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.search.aggregations.bucket;
import org.elasticsearch.search.aggregations.AggregationBuilder;
/**
* Marker interface to indicate that the {@link AggregationBuilder} is for a
* multi-bucket aggregation.
*/
public interface MultiBucketAggregationBuilder {
}

View File

@ -32,6 +32,7 @@ import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregatorFactories.Builder;
import org.elasticsearch.search.aggregations.AggregatorFactory;
import org.elasticsearch.search.aggregations.bucket.MultiBucketAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.adjacency.AdjacencyMatrixAggregator.KeyedFilter;
import org.elasticsearch.search.internal.SearchContext;
import org.elasticsearch.search.query.QueryPhaseExecutionException;
@ -46,7 +47,8 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
public class AdjacencyMatrixAggregationBuilder extends AbstractAggregationBuilder<AdjacencyMatrixAggregationBuilder> {
public class AdjacencyMatrixAggregationBuilder extends AbstractAggregationBuilder<AdjacencyMatrixAggregationBuilder>
implements MultiBucketAggregationBuilder {
public static final String NAME = "adjacency_matrix";
private static final String DEFAULT_SEPARATOR = "&";

View File

@ -31,8 +31,9 @@ import org.elasticsearch.index.query.Rewriteable;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregatorFactories.Builder;
import org.elasticsearch.search.aggregations.bucket.filter.FiltersAggregator.KeyedFilter;
import org.elasticsearch.search.aggregations.AggregatorFactory;
import org.elasticsearch.search.aggregations.bucket.MultiBucketAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.filter.FiltersAggregator.KeyedFilter;
import org.elasticsearch.search.internal.SearchContext;
import java.io.IOException;
@ -44,7 +45,8 @@ import java.util.Objects;
import static org.elasticsearch.index.query.AbstractQueryBuilder.parseInnerQueryBuilder;
public class FiltersAggregationBuilder extends AbstractAggregationBuilder<FiltersAggregationBuilder> {
public class FiltersAggregationBuilder extends AbstractAggregationBuilder<FiltersAggregationBuilder>
implements MultiBucketAggregationBuilder {
public static final String NAME = "filters";
private static final ParseField FILTERS_FIELD = new ParseField("filters");

View File

@ -38,6 +38,7 @@ import org.elasticsearch.index.fielddata.SortedNumericDoubleValues;
import org.elasticsearch.search.aggregations.AggregatorFactories.Builder;
import org.elasticsearch.search.aggregations.AggregatorFactory;
import org.elasticsearch.search.aggregations.bucket.BucketUtils;
import org.elasticsearch.search.aggregations.bucket.MultiBucketAggregationBuilder;
import org.elasticsearch.search.aggregations.support.ValueType;
import org.elasticsearch.search.aggregations.support.ValuesSource;
import org.elasticsearch.search.aggregations.support.ValuesSourceAggregationBuilder;
@ -50,7 +51,8 @@ import org.elasticsearch.search.internal.SearchContext;
import java.io.IOException;
import java.util.Objects;
public class GeoGridAggregationBuilder extends ValuesSourceAggregationBuilder<ValuesSource.GeoPoint, GeoGridAggregationBuilder> {
public class GeoGridAggregationBuilder extends ValuesSourceAggregationBuilder<ValuesSource.GeoPoint, GeoGridAggregationBuilder>
implements MultiBucketAggregationBuilder {
public static final String NAME = "geohash_grid";
public static final int DEFAULT_PRECISION = 5;
public static final int DEFAULT_MAX_NUM_CELLS = 10000;

View File

@ -32,6 +32,7 @@ import org.elasticsearch.search.aggregations.AggregatorFactory;
import org.elasticsearch.search.aggregations.BucketOrder;
import org.elasticsearch.search.aggregations.InternalOrder;
import org.elasticsearch.search.aggregations.InternalOrder.CompoundOrder;
import org.elasticsearch.search.aggregations.bucket.MultiBucketAggregationBuilder;
import org.elasticsearch.search.aggregations.support.ValueType;
import org.elasticsearch.search.aggregations.support.ValuesSource;
import org.elasticsearch.search.aggregations.support.ValuesSource.Numeric;
@ -53,8 +54,8 @@ import static java.util.Collections.unmodifiableMap;
/**
* A builder for histograms on date fields.
*/
public class DateHistogramAggregationBuilder
extends ValuesSourceAggregationBuilder<ValuesSource.Numeric, DateHistogramAggregationBuilder> {
public class DateHistogramAggregationBuilder extends ValuesSourceAggregationBuilder<ValuesSource.Numeric, DateHistogramAggregationBuilder>
implements MultiBucketAggregationBuilder {
public static final String NAME = "date_histogram";
public static final Map<String, DateTimeUnit> DATE_FIELD_UNITS;

View File

@ -30,6 +30,7 @@ import org.elasticsearch.search.aggregations.AggregatorFactory;
import org.elasticsearch.search.aggregations.BucketOrder;
import org.elasticsearch.search.aggregations.InternalOrder;
import org.elasticsearch.search.aggregations.InternalOrder.CompoundOrder;
import org.elasticsearch.search.aggregations.bucket.MultiBucketAggregationBuilder;
import org.elasticsearch.search.aggregations.support.ValueType;
import org.elasticsearch.search.aggregations.support.ValuesSource;
import org.elasticsearch.search.aggregations.support.ValuesSource.Numeric;
@ -47,8 +48,8 @@ import java.util.Objects;
/**
* A builder for histograms on numeric fields.
*/
public class HistogramAggregationBuilder
extends ValuesSourceAggregationBuilder<ValuesSource.Numeric, HistogramAggregationBuilder> {
public class HistogramAggregationBuilder extends ValuesSourceAggregationBuilder<ValuesSource.Numeric, HistogramAggregationBuilder>
implements MultiBucketAggregationBuilder {
public static final String NAME = "histogram";
private static final ObjectParser<double[], Void> EXTENDED_BOUNDS_PARSER = new ObjectParser<>(

View File

@ -24,6 +24,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.xcontent.XContentBuilder;
import org.elasticsearch.search.aggregations.bucket.MultiBucketAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.range.RangeAggregator.Range;
import org.elasticsearch.search.aggregations.support.ValuesSource;
import org.elasticsearch.search.aggregations.support.ValuesSourceAggregationBuilder;
@ -35,7 +36,7 @@ import java.util.Objects;
import java.util.function.Function;
public abstract class AbstractRangeBuilder<AB extends AbstractRangeBuilder<AB, R>, R extends Range>
extends ValuesSourceAggregationBuilder<ValuesSource.Numeric, AB> {
extends ValuesSourceAggregationBuilder<ValuesSource.Numeric, AB> implements MultiBucketAggregationBuilder {
protected final InternalRange.Factory<?, ?> rangeFactory;
protected List<R> ranges = new ArrayList<>();

View File

@ -30,6 +30,7 @@ import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.Aggregator;
import org.elasticsearch.search.aggregations.AggregatorFactories.Builder;
import org.elasticsearch.search.aggregations.AggregatorFactory;
import org.elasticsearch.search.aggregations.bucket.MultiBucketAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.significant.heuristics.JLHScore;
import org.elasticsearch.search.aggregations.bucket.significant.heuristics.SignificanceHeuristic;
import org.elasticsearch.search.aggregations.bucket.significant.heuristics.SignificanceHeuristicParser;
@ -51,7 +52,8 @@ import java.util.Objects;
import static org.elasticsearch.index.query.AbstractQueryBuilder.parseInnerQueryBuilder;
public class SignificantTermsAggregationBuilder extends ValuesSourceAggregationBuilder<ValuesSource, SignificantTermsAggregationBuilder> {
public class SignificantTermsAggregationBuilder extends ValuesSourceAggregationBuilder<ValuesSource, SignificantTermsAggregationBuilder>
implements MultiBucketAggregationBuilder {
public static final String NAME = "significant_terms";
static final ParseField BACKGROUND_FILTER = new ParseField("background_filter");

View File

@ -31,6 +31,7 @@ import org.elasticsearch.search.aggregations.AggregatorFactory;
import org.elasticsearch.search.aggregations.BucketOrder;
import org.elasticsearch.search.aggregations.InternalOrder;
import org.elasticsearch.search.aggregations.InternalOrder.CompoundOrder;
import org.elasticsearch.search.aggregations.bucket.MultiBucketAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregator.BucketCountThresholds;
import org.elasticsearch.search.aggregations.support.ValueType;
import org.elasticsearch.search.aggregations.support.ValuesSource;
@ -45,7 +46,8 @@ import java.io.IOException;
import java.util.List;
import java.util.Objects;
public class TermsAggregationBuilder extends ValuesSourceAggregationBuilder<ValuesSource, TermsAggregationBuilder> {
public class TermsAggregationBuilder extends ValuesSourceAggregationBuilder<ValuesSource, TermsAggregationBuilder>
implements MultiBucketAggregationBuilder {
public static final String NAME = "terms";
public static final ParseField EXECUTION_HINT_FIELD_NAME = new ParseField("execution_hint");

View File

@ -22,6 +22,7 @@ import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregatorFactory;
import org.elasticsearch.search.aggregations.PipelineAggregationBuilder;
@ -80,7 +81,7 @@ public abstract class AbstractPipelineAggregationBuilder<PAB extends AbstractPip
* configured)
*/
@Override
public final void validate(AggregatorFactory<?> parent, AggregatorFactory<?>[] factories,
public final void validate(AggregatorFactory<?> parent, List<AggregationBuilder> factories,
List<PipelineAggregationBuilder> pipelineAggregatorFactories) {
doValidate(parent, factories, pipelineAggregatorFactories);
}
@ -98,7 +99,7 @@ public abstract class AbstractPipelineAggregationBuilder<PAB extends AbstractPip
return aggregator;
}
public void doValidate(AggregatorFactory<?> parent, AggregatorFactory<?>[] factories,
public void doValidate(AggregatorFactory<?> parent, List<AggregationBuilder> factories,
List<PipelineAggregationBuilder> pipelineAggregatorFactories) {
}

View File

@ -23,16 +23,19 @@ import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.search.DocValueFormat;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregatorFactory;
import org.elasticsearch.search.aggregations.PipelineAggregationBuilder;
import org.elasticsearch.search.aggregations.pipeline.BucketHelpers.GapPolicy;
import org.elasticsearch.search.aggregations.bucket.MultiBucketAggregationBuilder;
import org.elasticsearch.search.aggregations.pipeline.AbstractPipelineAggregationBuilder;
import org.elasticsearch.search.aggregations.pipeline.BucketHelpers.GapPolicy;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
public abstract class BucketMetricsPipelineAggregationBuilder<AF extends BucketMetricsPipelineAggregationBuilder<AF>>
extends AbstractPipelineAggregationBuilder<AF> {
@ -106,12 +109,29 @@ public abstract class BucketMetricsPipelineAggregationBuilder<AF extends BucketM
protected abstract PipelineAggregator createInternal(Map<String, Object> metaData) throws IOException;
@Override
public void doValidate(AggregatorFactory<?> parent, AggregatorFactory<?>[] aggFactories,
public void doValidate(AggregatorFactory<?> parent, List<AggregationBuilder> aggBuilders,
List<PipelineAggregationBuilder> pipelineAggregatorFactories) {
if (bucketsPaths.length != 1) {
throw new IllegalStateException(PipelineAggregator.Parser.BUCKETS_PATH.getPreferredName()
+ " must contain a single entry for aggregation [" + name + "]");
}
// Need to find the first agg name in the buckets path to check its a
// multi bucket agg: aggs are split with '>' and can optionally have a
// metric name after them by using '.' so need to split on both to get
// just the agg name
final String firstAgg = bucketsPaths[0].split("[>\\.]")[0];
Optional<AggregationBuilder> aggBuilder = aggBuilders.stream().filter((builder) -> builder.getName().equals(firstAgg))
.findAny();
if (aggBuilder.isPresent()) {
if ((aggBuilder.get() instanceof MultiBucketAggregationBuilder) == false) {
throw new IllegalArgumentException("The first aggregation in " + PipelineAggregator.Parser.BUCKETS_PATH.getPreferredName()
+ " must be a multi-bucket aggregation for aggregation [" + name + "] found :"
+ aggBuilder.get().getClass().getName() + " for buckets path: " + bucketsPaths[0]);
}
} else {
throw new IllegalArgumentException(PipelineAggregator.Parser.BUCKETS_PATH.getPreferredName()
+ " aggregation does not exist for aggregation [" + name + "]: " + bucketsPaths[0]);
}
}
@Override

View File

@ -22,14 +22,11 @@ package org.elasticsearch.search.aggregations.pipeline.bucketmetrics.avg;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.search.aggregations.AggregatorFactory;
import org.elasticsearch.search.aggregations.PipelineAggregationBuilder;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
import org.elasticsearch.search.aggregations.pipeline.bucketmetrics.BucketMetricsParser;
import org.elasticsearch.search.aggregations.pipeline.bucketmetrics.BucketMetricsPipelineAggregationBuilder;
import java.io.IOException;
import java.util.List;
import java.util.Map;
public class AvgBucketPipelineAggregationBuilder extends BucketMetricsPipelineAggregationBuilder<AvgBucketPipelineAggregationBuilder> {
@ -56,15 +53,6 @@ public class AvgBucketPipelineAggregationBuilder extends BucketMetricsPipelineAg
return new AvgBucketPipelineAggregator(name, bucketsPaths, gapPolicy(), formatter(), metaData);
}
@Override
public void doValidate(AggregatorFactory<?> parent, AggregatorFactory<?>[] aggFactories,
List<PipelineAggregationBuilder> pipelineAggregatorFactories) {
if (bucketsPaths.length != 1) {
throw new IllegalStateException(PipelineAggregator.Parser.BUCKETS_PATH.getPreferredName()
+ " must contain a single entry for aggregation [" + name + "]");
}
}
@Override
protected XContentBuilder doXContentBody(XContentBuilder builder, Params params) throws IOException {
return builder;

View File

@ -22,14 +22,11 @@ package org.elasticsearch.search.aggregations.pipeline.bucketmetrics.max;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.search.aggregations.AggregatorFactory;
import org.elasticsearch.search.aggregations.PipelineAggregationBuilder;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
import org.elasticsearch.search.aggregations.pipeline.bucketmetrics.BucketMetricsParser;
import org.elasticsearch.search.aggregations.pipeline.bucketmetrics.BucketMetricsPipelineAggregationBuilder;
import java.io.IOException;
import java.util.List;
import java.util.Map;
public class MaxBucketPipelineAggregationBuilder extends BucketMetricsPipelineAggregationBuilder<MaxBucketPipelineAggregationBuilder> {
@ -56,15 +53,6 @@ public class MaxBucketPipelineAggregationBuilder extends BucketMetricsPipelineAg
return new MaxBucketPipelineAggregator(name, bucketsPaths, gapPolicy(), formatter(), metaData);
}
@Override
public void doValidate(AggregatorFactory<?> parent, AggregatorFactory<?>[] aggFactories,
List<PipelineAggregationBuilder> pipelineAggregatorFactories) {
if (bucketsPaths.length != 1) {
throw new IllegalStateException(PipelineAggregator.Parser.BUCKETS_PATH.getPreferredName()
+ " must contain a single entry for aggregation [" + name + "]");
}
}
@Override
protected XContentBuilder doXContentBody(XContentBuilder builder, Params params) throws IOException {
return builder;

View File

@ -22,14 +22,11 @@ package org.elasticsearch.search.aggregations.pipeline.bucketmetrics.min;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.search.aggregations.AggregatorFactory;
import org.elasticsearch.search.aggregations.PipelineAggregationBuilder;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
import org.elasticsearch.search.aggregations.pipeline.bucketmetrics.BucketMetricsParser;
import org.elasticsearch.search.aggregations.pipeline.bucketmetrics.BucketMetricsPipelineAggregationBuilder;
import java.io.IOException;
import java.util.List;
import java.util.Map;
public class MinBucketPipelineAggregationBuilder extends BucketMetricsPipelineAggregationBuilder<MinBucketPipelineAggregationBuilder> {
@ -56,15 +53,6 @@ public class MinBucketPipelineAggregationBuilder extends BucketMetricsPipelineAg
return new MinBucketPipelineAggregator(name, bucketsPaths, gapPolicy(), formatter(), metaData);
}
@Override
public void doValidate(AggregatorFactory<?> parent, AggregatorFactory<?>[] aggFactories,
List<PipelineAggregationBuilder> pipelineAggregatorFactories) {
if (bucketsPaths.length != 1) {
throw new IllegalStateException(PipelineAggregator.Parser.BUCKETS_PATH.getPreferredName()
+ " must contain a single entry for aggregation [" + name + "]");
}
}
@Override
protected XContentBuilder doXContentBody(XContentBuilder builder, Params params) throws IOException {
return builder;

View File

@ -26,6 +26,7 @@ import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregatorFactory;
import org.elasticsearch.search.aggregations.PipelineAggregationBuilder;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
@ -42,7 +43,7 @@ public class PercentilesBucketPipelineAggregationBuilder
extends BucketMetricsPipelineAggregationBuilder<PercentilesBucketPipelineAggregationBuilder> {
public static final String NAME = "percentiles_bucket";
private static final ParseField PERCENTS_FIELD = new ParseField("percents");
public static final ParseField PERCENTS_FIELD = new ParseField("percents");
private double[] percents = new double[] { 1.0, 5.0, 25.0, 50.0, 75.0, 95.0, 99.0 };
@ -94,12 +95,9 @@ public class PercentilesBucketPipelineAggregationBuilder
}
@Override
public void doValidate(AggregatorFactory<?> parent, AggregatorFactory<?>[] aggFactories,
public void doValidate(AggregatorFactory<?> parent, List<AggregationBuilder> aggFactories,
List<PipelineAggregationBuilder> pipelineAggregatorFactories) {
if (bucketsPaths.length != 1) {
throw new IllegalStateException(PipelineAggregator.Parser.BUCKETS_PATH.getPreferredName()
+ " must contain a single entry for aggregation [" + name + "]");
}
super.doValidate(parent, aggFactories, pipelineAggregatorFactories);
for (Double p : percents) {
if (p == null || p < 0.0 || p > 100.0) {

View File

@ -22,15 +22,11 @@ package org.elasticsearch.search.aggregations.pipeline.bucketmetrics.stats;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.search.aggregations.AggregatorFactory;
import org.elasticsearch.search.aggregations.PipelineAggregationBuilder;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator.Parser;
import org.elasticsearch.search.aggregations.pipeline.bucketmetrics.BucketMetricsParser;
import org.elasticsearch.search.aggregations.pipeline.bucketmetrics.BucketMetricsPipelineAggregationBuilder;
import java.io.IOException;
import java.util.List;
import java.util.Map;
public class StatsBucketPipelineAggregationBuilder extends BucketMetricsPipelineAggregationBuilder<StatsBucketPipelineAggregationBuilder> {
@ -58,15 +54,6 @@ public class StatsBucketPipelineAggregationBuilder extends BucketMetricsPipeline
return new StatsBucketPipelineAggregator(name, bucketsPaths, gapPolicy(), formatter(), metaData);
}
@Override
public void doValidate(AggregatorFactory<?> parent, AggregatorFactory<?>[] aggFactories,
List<PipelineAggregationBuilder> pipelineAggregatorFactories) {
if (bucketsPaths.length != 1) {
throw new IllegalStateException(Parser.BUCKETS_PATH.getPreferredName()
+ " must contain a single entry for aggregation [" + name + "]");
}
}
@Override
protected XContentBuilder doXContentBody(XContentBuilder builder, Params params) throws IOException {
return builder;

View File

@ -22,10 +22,10 @@ package org.elasticsearch.search.aggregations.pipeline.bucketmetrics.stats.exten
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregatorFactory;
import org.elasticsearch.search.aggregations.PipelineAggregationBuilder;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator.Parser;
import org.elasticsearch.search.aggregations.pipeline.bucketmetrics.BucketMetricsPipelineAggregationBuilder;
import java.io.IOException;
@ -82,12 +82,9 @@ public class ExtendedStatsBucketPipelineAggregationBuilder
}
@Override
public void doValidate(AggregatorFactory<?> parent, AggregatorFactory<?>[] aggFactories,
public void doValidate(AggregatorFactory<?> parent, List<AggregationBuilder> aggBuilders,
List<PipelineAggregationBuilder> pipelineAggregatorFactories) {
if (bucketsPaths.length != 1) {
throw new IllegalStateException(Parser.BUCKETS_PATH.getPreferredName()
+ " must contain a single entry for aggregation [" + name + "]");
}
super.doValidate(parent, aggBuilders, pipelineAggregatorFactories);
if (sigma < 0.0 ) {
throw new IllegalStateException(ExtendedStatsBucketParser.SIGMA.getPreferredName()

View File

@ -22,14 +22,11 @@ package org.elasticsearch.search.aggregations.pipeline.bucketmetrics.sum;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.search.aggregations.AggregatorFactory;
import org.elasticsearch.search.aggregations.PipelineAggregationBuilder;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
import org.elasticsearch.search.aggregations.pipeline.bucketmetrics.BucketMetricsParser;
import org.elasticsearch.search.aggregations.pipeline.bucketmetrics.BucketMetricsPipelineAggregationBuilder;
import java.io.IOException;
import java.util.List;
import java.util.Map;
public class SumBucketPipelineAggregationBuilder extends BucketMetricsPipelineAggregationBuilder<SumBucketPipelineAggregationBuilder> {
@ -56,15 +53,6 @@ public class SumBucketPipelineAggregationBuilder extends BucketMetricsPipelineAg
return new SumBucketPipelineAggregator(name, bucketsPaths, gapPolicy(), formatter(), metaData);
}
@Override
public void doValidate(AggregatorFactory<?> parent, AggregatorFactory<?>[] aggFactories,
List<PipelineAggregationBuilder> pipelineAggregatorFactories) {
if (bucketsPaths.length != 1) {
throw new IllegalStateException(PipelineAggregator.Parser.BUCKETS_PATH.getPreferredName()
+ " must contain a single entry for aggregation [" + name + "]");
}
}
@Override
protected XContentBuilder doXContentBody(XContentBuilder builder, Params params) throws IOException {
return builder;

View File

@ -25,6 +25,7 @@ import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.search.DocValueFormat;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregatorFactory;
import org.elasticsearch.search.aggregations.PipelineAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramAggregatorFactory;
@ -96,7 +97,7 @@ public class CumulativeSumPipelineAggregationBuilder extends AbstractPipelineAgg
}
@Override
public void doValidate(AggregatorFactory<?> parent, AggregatorFactory<?>[] aggFactories,
public void doValidate(AggregatorFactory<?> parent, List<AggregationBuilder> aggFactories,
List<PipelineAggregationBuilder> pipelineAggregatorFactories) {
if (bucketsPaths.length != 1) {
throw new IllegalStateException(BUCKETS_PATH.getPreferredName()

View File

@ -28,6 +28,7 @@ import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.search.DocValueFormat;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregatorFactory;
import org.elasticsearch.search.aggregations.PipelineAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramAggregationBuilder;
@ -155,7 +156,7 @@ public class DerivativePipelineAggregationBuilder extends AbstractPipelineAggreg
}
@Override
public void doValidate(AggregatorFactory<?> parent, AggregatorFactory<?>[] aggFactories,
public void doValidate(AggregatorFactory<?> parent, List<AggregationBuilder> aggFactories,
List<PipelineAggregationBuilder> pipelineAggregatoractories) {
if (bucketsPaths.length != 1) {
throw new IllegalStateException(PipelineAggregator.Parser.BUCKETS_PATH.getPreferredName()

View File

@ -27,6 +27,7 @@ import org.elasticsearch.common.xcontent.ParseFieldRegistry;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.search.DocValueFormat;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregatorFactory;
import org.elasticsearch.search.aggregations.PipelineAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramAggregatorFactory;
@ -255,7 +256,7 @@ public class MovAvgPipelineAggregationBuilder extends AbstractPipelineAggregatio
}
@Override
public void doValidate(AggregatorFactory<?> parent, AggregatorFactory<?>[] aggFactories,
public void doValidate(AggregatorFactory<?> parent, List<AggregationBuilder> aggFactories,
List<PipelineAggregationBuilder> pipelineAggregatoractories) {
if (minimize != null && minimize && !model.canBeMinimized()) {
// If the user asks to minimize, but this model doesn't support

View File

@ -19,7 +19,16 @@
package org.elasticsearch.search.aggregations.pipeline.bucketmetrics;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.global.GlobalAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
import org.elasticsearch.search.aggregations.pipeline.bucketmetrics.avg.AvgBucketPipelineAggregationBuilder;
import org.elasticsearch.search.aggregations.support.ValueType;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class AvgBucketTests extends AbstractBucketMetricsTestCase<AvgBucketPipelineAggregationBuilder> {
@ -28,5 +37,31 @@ public class AvgBucketTests extends AbstractBucketMetricsTestCase<AvgBucketPipel
return new AvgBucketPipelineAggregationBuilder(name, bucketsPath);
}
public void testValidate() {
AggregationBuilder singleBucketAgg = new GlobalAggregationBuilder("global");
AggregationBuilder multiBucketAgg = new TermsAggregationBuilder("terms", ValueType.STRING);
final List<AggregationBuilder> aggBuilders = new ArrayList<>();
aggBuilders.add(singleBucketAgg);
aggBuilders.add(multiBucketAgg);
// First try to point to a non-existent agg
final AvgBucketPipelineAggregationBuilder builder = new AvgBucketPipelineAggregationBuilder("name", "invalid_agg>metric");
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class,
() -> builder.validate(null, aggBuilders, Collections.emptyList()));
assertEquals(PipelineAggregator.Parser.BUCKETS_PATH.getPreferredName()
+ " aggregation does not exist for aggregation [name]: invalid_agg>metric", ex.getMessage());
// Now try to point to a single bucket agg
AvgBucketPipelineAggregationBuilder builder2 = new AvgBucketPipelineAggregationBuilder("name", "global>metric");
ex = expectThrows(IllegalArgumentException.class, () -> builder2.validate(null, aggBuilders, Collections.emptyList()));
assertEquals("The first aggregation in " + PipelineAggregator.Parser.BUCKETS_PATH.getPreferredName()
+ " must be a multi-bucket aggregation for aggregation [name] found :" + GlobalAggregationBuilder.class.getName()
+ " for buckets path: global>metric", ex.getMessage());
// Now try to point to a valid multi-bucket agg (no exception should be thrown)
AvgBucketPipelineAggregationBuilder builder3 = new AvgBucketPipelineAggregationBuilder("name", "terms>metric");
builder3.validate(null, aggBuilders, Collections.emptyList());
}
}

View File

@ -21,7 +21,16 @@ package org.elasticsearch.search.aggregations.pipeline.bucketmetrics;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.global.GlobalAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
import org.elasticsearch.search.aggregations.pipeline.bucketmetrics.stats.extended.ExtendedStatsBucketPipelineAggregationBuilder;
import org.elasticsearch.search.aggregations.support.ValueType;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.hamcrest.Matchers.equalTo;
@ -52,4 +61,32 @@ public class ExtendedStatsBucketTests extends AbstractBucketMetricsTestCase<Exte
assertThat(builder.sigma(), equalTo(5.0));
}
public void testValidate() {
AggregationBuilder singleBucketAgg = new GlobalAggregationBuilder("global");
AggregationBuilder multiBucketAgg = new TermsAggregationBuilder("terms", ValueType.STRING);
final List<AggregationBuilder> aggBuilders = new ArrayList<>();
aggBuilders.add(singleBucketAgg);
aggBuilders.add(multiBucketAgg);
// First try to point to a non-existent agg
final ExtendedStatsBucketPipelineAggregationBuilder builder = new ExtendedStatsBucketPipelineAggregationBuilder("name",
"invalid_agg>metric");
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class,
() -> builder.validate(null, aggBuilders, Collections.emptyList()));
assertEquals(PipelineAggregator.Parser.BUCKETS_PATH.getPreferredName()
+ " aggregation does not exist for aggregation [name]: invalid_agg>metric", ex.getMessage());
// Now try to point to a single bucket agg
ExtendedStatsBucketPipelineAggregationBuilder builder2 = new ExtendedStatsBucketPipelineAggregationBuilder("name", "global>metric");
ex = expectThrows(IllegalArgumentException.class, () -> builder2.validate(null, aggBuilders, Collections.emptyList()));
assertEquals("The first aggregation in " + PipelineAggregator.Parser.BUCKETS_PATH.getPreferredName()
+ " must be a multi-bucket aggregation for aggregation [name] found :" + GlobalAggregationBuilder.class.getName()
+ " for buckets path: global>metric", ex.getMessage());
// Now try to point to a valid multi-bucket agg (no exception should be
// thrown)
ExtendedStatsBucketPipelineAggregationBuilder builder3 = new ExtendedStatsBucketPipelineAggregationBuilder("name", "terms>metric");
builder3.validate(null, aggBuilders, Collections.emptyList());
}
}

View File

@ -19,7 +19,16 @@
package org.elasticsearch.search.aggregations.pipeline.bucketmetrics;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.global.GlobalAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
import org.elasticsearch.search.aggregations.pipeline.bucketmetrics.max.MaxBucketPipelineAggregationBuilder;
import org.elasticsearch.search.aggregations.support.ValueType;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MaxBucketTests extends AbstractBucketMetricsTestCase<MaxBucketPipelineAggregationBuilder> {
@ -28,5 +37,31 @@ public class MaxBucketTests extends AbstractBucketMetricsTestCase<MaxBucketPipel
return new MaxBucketPipelineAggregationBuilder(name, bucketsPath);
}
public void testValidate() {
AggregationBuilder singleBucketAgg = new GlobalAggregationBuilder("global");
AggregationBuilder multiBucketAgg = new TermsAggregationBuilder("terms", ValueType.STRING);
final List<AggregationBuilder> aggBuilders = new ArrayList<>();
aggBuilders.add(singleBucketAgg);
aggBuilders.add(multiBucketAgg);
// First try to point to a non-existent agg
final MaxBucketPipelineAggregationBuilder builder = new MaxBucketPipelineAggregationBuilder("name", "invalid_agg>metric");
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class,
() -> builder.validate(null, aggBuilders, Collections.emptyList()));
assertEquals(PipelineAggregator.Parser.BUCKETS_PATH.getPreferredName()
+ " aggregation does not exist for aggregation [name]: invalid_agg>metric", ex.getMessage());
// Now try to point to a single bucket agg
MaxBucketPipelineAggregationBuilder builder2 = new MaxBucketPipelineAggregationBuilder("name", "global>metric");
ex = expectThrows(IllegalArgumentException.class, () -> builder2.validate(null, aggBuilders, Collections.emptyList()));
assertEquals("The first aggregation in " + PipelineAggregator.Parser.BUCKETS_PATH.getPreferredName()
+ " must be a multi-bucket aggregation for aggregation [name] found :" + GlobalAggregationBuilder.class.getName()
+ " for buckets path: global>metric", ex.getMessage());
// Now try to point to a valid multi-bucket agg (no exception should be
// thrown)
MaxBucketPipelineAggregationBuilder builder3 = new MaxBucketPipelineAggregationBuilder("name", "terms>metric");
builder3.validate(null, aggBuilders, Collections.emptyList());
}
}

View File

@ -19,7 +19,16 @@
package org.elasticsearch.search.aggregations.pipeline.bucketmetrics;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.global.GlobalAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
import org.elasticsearch.search.aggregations.pipeline.bucketmetrics.min.MinBucketPipelineAggregationBuilder;
import org.elasticsearch.search.aggregations.support.ValueType;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MinBucketTests extends AbstractBucketMetricsTestCase<MinBucketPipelineAggregationBuilder> {
@ -28,5 +37,31 @@ public class MinBucketTests extends AbstractBucketMetricsTestCase<MinBucketPipel
return new MinBucketPipelineAggregationBuilder(name, bucketsPath);
}
public void testValidate() {
AggregationBuilder singleBucketAgg = new GlobalAggregationBuilder("global");
AggregationBuilder multiBucketAgg = new TermsAggregationBuilder("terms", ValueType.STRING);
final List<AggregationBuilder> aggBuilders = new ArrayList<>();
aggBuilders.add(singleBucketAgg);
aggBuilders.add(multiBucketAgg);
// First try to point to a non-existent agg
final MinBucketPipelineAggregationBuilder builder = new MinBucketPipelineAggregationBuilder("name", "invalid_agg>metric");
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class,
() -> builder.validate(null, aggBuilders, Collections.emptyList()));
assertEquals(PipelineAggregator.Parser.BUCKETS_PATH.getPreferredName()
+ " aggregation does not exist for aggregation [name]: invalid_agg>metric", ex.getMessage());
// Now try to point to a single bucket agg
MinBucketPipelineAggregationBuilder builder2 = new MinBucketPipelineAggregationBuilder("name", "global>metric");
ex = expectThrows(IllegalArgumentException.class, () -> builder2.validate(null, aggBuilders, Collections.emptyList()));
assertEquals("The first aggregation in " + PipelineAggregator.Parser.BUCKETS_PATH.getPreferredName()
+ " must be a multi-bucket aggregation for aggregation [name] found :" + GlobalAggregationBuilder.class.getName()
+ " for buckets path: global>metric", ex.getMessage());
// Now try to point to a valid multi-bucket agg (no exception should be
// thrown)
MinBucketPipelineAggregationBuilder builder3 = new MinBucketPipelineAggregationBuilder("name", "terms>metric");
builder3.validate(null, aggBuilders, Collections.emptyList());
}
}

View File

@ -21,7 +21,16 @@ package org.elasticsearch.search.aggregations.pipeline.bucketmetrics;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.global.GlobalAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
import org.elasticsearch.search.aggregations.pipeline.bucketmetrics.percentile.PercentilesBucketPipelineAggregationBuilder;
import org.elasticsearch.search.aggregations.support.ValueType;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.hamcrest.Matchers.equalTo;
@ -56,4 +65,32 @@ public class PercentilesBucketTests extends AbstractBucketMetricsTestCase<Percen
assertThat(builder.percents(), equalTo(new double[]{0.0, 20.0, 50.0, 75.99}));
}
public void testValidate() {
AggregationBuilder singleBucketAgg = new GlobalAggregationBuilder("global");
AggregationBuilder multiBucketAgg = new TermsAggregationBuilder("terms", ValueType.STRING);
final List<AggregationBuilder> aggBuilders = new ArrayList<>();
aggBuilders.add(singleBucketAgg);
aggBuilders.add(multiBucketAgg);
// First try to point to a non-existent agg
final PercentilesBucketPipelineAggregationBuilder builder = new PercentilesBucketPipelineAggregationBuilder("name",
"invalid_agg>metric");
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class,
() -> builder.validate(null, aggBuilders, Collections.emptyList()));
assertEquals(PipelineAggregator.Parser.BUCKETS_PATH.getPreferredName()
+ " aggregation does not exist for aggregation [name]: invalid_agg>metric", ex.getMessage());
// Now try to point to a single bucket agg
PercentilesBucketPipelineAggregationBuilder builder2 = new PercentilesBucketPipelineAggregationBuilder("name", "global>metric");
ex = expectThrows(IllegalArgumentException.class, () -> builder2.validate(null, aggBuilders, Collections.emptyList()));
assertEquals("The first aggregation in " + PipelineAggregator.Parser.BUCKETS_PATH.getPreferredName()
+ " must be a multi-bucket aggregation for aggregation [name] found :" + GlobalAggregationBuilder.class.getName()
+ " for buckets path: global>metric", ex.getMessage());
// Now try to point to a valid multi-bucket agg (no exception should be
// thrown)
PercentilesBucketPipelineAggregationBuilder builder3 = new PercentilesBucketPipelineAggregationBuilder("name", "terms>metric");
builder3.validate(null, aggBuilders, Collections.emptyList());
}
}

View File

@ -19,7 +19,16 @@
package org.elasticsearch.search.aggregations.pipeline.bucketmetrics;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.global.GlobalAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
import org.elasticsearch.search.aggregations.pipeline.bucketmetrics.stats.StatsBucketPipelineAggregationBuilder;
import org.elasticsearch.search.aggregations.support.ValueType;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class StatsBucketTests extends AbstractBucketMetricsTestCase<StatsBucketPipelineAggregationBuilder> {
@ -29,5 +38,31 @@ public class StatsBucketTests extends AbstractBucketMetricsTestCase<StatsBucketP
return new StatsBucketPipelineAggregationBuilder(name, bucketsPath);
}
public void testValidate() {
AggregationBuilder singleBucketAgg = new GlobalAggregationBuilder("global");
AggregationBuilder multiBucketAgg = new TermsAggregationBuilder("terms", ValueType.STRING);
final List<AggregationBuilder> aggBuilders = new ArrayList<>();
aggBuilders.add(singleBucketAgg);
aggBuilders.add(multiBucketAgg);
// First try to point to a non-existent agg
final StatsBucketPipelineAggregationBuilder builder = new StatsBucketPipelineAggregationBuilder("name", "invalid_agg>metric");
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class,
() -> builder.validate(null, aggBuilders, Collections.emptyList()));
assertEquals(PipelineAggregator.Parser.BUCKETS_PATH.getPreferredName()
+ " aggregation does not exist for aggregation [name]: invalid_agg>metric", ex.getMessage());
// Now try to point to a single bucket agg
StatsBucketPipelineAggregationBuilder builder2 = new StatsBucketPipelineAggregationBuilder("name", "global>metric");
ex = expectThrows(IllegalArgumentException.class, () -> builder2.validate(null, aggBuilders, Collections.emptyList()));
assertEquals("The first aggregation in " + PipelineAggregator.Parser.BUCKETS_PATH.getPreferredName()
+ " must be a multi-bucket aggregation for aggregation [name] found :" + GlobalAggregationBuilder.class.getName()
+ " for buckets path: global>metric", ex.getMessage());
// Now try to point to a valid multi-bucket agg (no exception should be
// thrown)
StatsBucketPipelineAggregationBuilder builder3 = new StatsBucketPipelineAggregationBuilder("name", "terms>metric");
builder3.validate(null, aggBuilders, Collections.emptyList());
}
}

View File

@ -19,7 +19,16 @@
package org.elasticsearch.search.aggregations.pipeline.bucketmetrics;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.global.GlobalAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
import org.elasticsearch.search.aggregations.pipeline.bucketmetrics.sum.SumBucketPipelineAggregationBuilder;
import org.elasticsearch.search.aggregations.support.ValueType;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class SumBucketTests extends AbstractBucketMetricsTestCase<SumBucketPipelineAggregationBuilder> {
@ -28,5 +37,31 @@ public class SumBucketTests extends AbstractBucketMetricsTestCase<SumBucketPipel
return new SumBucketPipelineAggregationBuilder(name, bucketsPath);
}
public void testValidate() {
AggregationBuilder singleBucketAgg = new GlobalAggregationBuilder("global");
AggregationBuilder multiBucketAgg = new TermsAggregationBuilder("terms", ValueType.STRING);
final List<AggregationBuilder> aggBuilders = new ArrayList<>();
aggBuilders.add(singleBucketAgg);
aggBuilders.add(multiBucketAgg);
// First try to point to a non-existent agg
final SumBucketPipelineAggregationBuilder builder = new SumBucketPipelineAggregationBuilder("name", "invalid_agg>metric");
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class,
() -> builder.validate(null, aggBuilders, Collections.emptyList()));
assertEquals(PipelineAggregator.Parser.BUCKETS_PATH.getPreferredName()
+ " aggregation does not exist for aggregation [name]: invalid_agg>metric", ex.getMessage());
// Now try to point to a single bucket agg
SumBucketPipelineAggregationBuilder builder2 = new SumBucketPipelineAggregationBuilder("name", "global>metric");
ex = expectThrows(IllegalArgumentException.class, () -> builder2.validate(null, aggBuilders, Collections.emptyList()));
assertEquals("The first aggregation in " + PipelineAggregator.Parser.BUCKETS_PATH.getPreferredName()
+ " must be a multi-bucket aggregation for aggregation [name] found :" + GlobalAggregationBuilder.class.getName()
+ " for buckets path: global>metric", ex.getMessage());
// Now try to point to a valid multi-bucket agg (no exception should be
// thrown)
SumBucketPipelineAggregationBuilder builder3 = new SumBucketPipelineAggregationBuilder("name", "terms>metric");
builder3.validate(null, aggBuilders, Collections.emptyList());
}
}