diff --git a/src/main/java/org/elasticsearch/search/aggregations/AggregatorFactories.java b/src/main/java/org/elasticsearch/search/aggregations/AggregatorFactories.java index 552ff49fe1d..1a4c157da8e 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/AggregatorFactories.java +++ b/src/main/java/org/elasticsearch/search/aggregations/AggregatorFactories.java @@ -40,6 +40,7 @@ public class AggregatorFactories { public static final AggregatorFactories EMPTY = new Empty(); + private AggregatorFactory parent; private AggregatorFactory[] factories; private List reducerFactories; @@ -101,6 +102,7 @@ public class AggregatorFactories { } void setParent(AggregatorFactory parent) { + this.parent = parent; for (AggregatorFactory factory : factories) { factory.parent = parent; } @@ -111,7 +113,7 @@ public class AggregatorFactories { factory.validate(); } for (ReducerFactory factory : reducerFactories) { - factory.validate(); + factory.validate(parent, factories, reducerFactories); } } diff --git a/src/main/java/org/elasticsearch/search/aggregations/AggregatorFactory.java b/src/main/java/org/elasticsearch/search/aggregations/AggregatorFactory.java index 41aee8f931f..f69e54ee710 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/AggregatorFactory.java +++ b/src/main/java/org/elasticsearch/search/aggregations/AggregatorFactory.java @@ -66,6 +66,10 @@ public abstract class AggregatorFactory { return this; } + public String name() { + return name; + } + /** * Validates the state of this factory (makes sure the factory is properly configured) */ diff --git a/src/main/java/org/elasticsearch/search/aggregations/bucket/histogram/HistogramAggregator.java b/src/main/java/org/elasticsearch/search/aggregations/bucket/histogram/HistogramAggregator.java index 0a6a8bce732..63325c12aad 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/bucket/histogram/HistogramAggregator.java +++ b/src/main/java/org/elasticsearch/search/aggregations/bucket/histogram/HistogramAggregator.java @@ -169,6 +169,10 @@ public class HistogramAggregator extends BucketsAggregator { this.histogramFactory = histogramFactory; } + public long minDocCount() { + return minDocCount; + } + @Override protected Aggregator createUnmapped(AggregationContext aggregationContext, Aggregator parent, List reducers, Map metaData) throws IOException { diff --git a/src/main/java/org/elasticsearch/search/aggregations/reducers/ReducerFactory.java b/src/main/java/org/elasticsearch/search/aggregations/reducers/ReducerFactory.java index 05cb6fbed48..ccdd2ac0328 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/reducers/ReducerFactory.java +++ b/src/main/java/org/elasticsearch/search/aggregations/reducers/ReducerFactory.java @@ -19,9 +19,11 @@ package org.elasticsearch.search.aggregations.reducers; import org.elasticsearch.search.aggregations.Aggregator; +import org.elasticsearch.search.aggregations.AggregatorFactory; import org.elasticsearch.search.aggregations.support.AggregationContext; import java.io.IOException; +import java.util.List; import java.util.Map; /** @@ -49,10 +51,15 @@ public abstract class ReducerFactory { } /** - * Validates the state of this factory (makes sure the factory is properly configured) + * Validates the state of this factory (makes sure the factory is properly + * configured) + * + * @param reducerFactories + * @param factories + * @param parent */ - public final void validate() { - doValidate(); + public final void validate(AggregatorFactory parent, AggregatorFactory[] factories, List reducerFactories) { + doValidate(parent, factories, reducerFactories); } protected abstract Reducer createInternal(AggregationContext context, Aggregator parent, boolean collectsFromSingleBucket, @@ -79,7 +86,7 @@ public abstract class ReducerFactory { return aggregator; } - public void doValidate() { + public void doValidate(AggregatorFactory parent, AggregatorFactory[] factories, List reducerFactories) { } public void setMetaData(Map metaData) { diff --git a/src/main/java/org/elasticsearch/search/aggregations/reducers/derivative/DerivativeReducer.java b/src/main/java/org/elasticsearch/search/aggregations/reducers/derivative/DerivativeReducer.java index 1130639a1a2..5f40ab2906e 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/reducers/derivative/DerivativeReducer.java +++ b/src/main/java/org/elasticsearch/search/aggregations/reducers/derivative/DerivativeReducer.java @@ -22,18 +22,24 @@ package org.elasticsearch.search.aggregations.reducers.derivative; import com.google.common.base.Function; import com.google.common.collect.Lists; - +import org.elasticsearch.ElasticsearchIllegalStateException; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.search.aggregations.Aggregation; import org.elasticsearch.search.aggregations.Aggregator; +import org.elasticsearch.search.aggregations.AggregatorFactory; import org.elasticsearch.search.aggregations.InternalAggregation; import org.elasticsearch.search.aggregations.InternalAggregation.ReduceContext; import org.elasticsearch.search.aggregations.InternalAggregation.Type; import org.elasticsearch.search.aggregations.InternalAggregations; +import org.elasticsearch.search.aggregations.bucket.histogram.HistogramAggregator; import org.elasticsearch.search.aggregations.bucket.histogram.InternalHistogram; -import org.elasticsearch.search.aggregations.reducers.*; +import org.elasticsearch.search.aggregations.reducers.BucketHelpers.GapPolicy; +import org.elasticsearch.search.aggregations.reducers.InternalSimpleValue; +import org.elasticsearch.search.aggregations.reducers.Reducer; +import org.elasticsearch.search.aggregations.reducers.ReducerFactory; +import org.elasticsearch.search.aggregations.reducers.ReducerStreams; import org.elasticsearch.search.aggregations.support.AggregationContext; import org.elasticsearch.search.aggregations.support.format.ValueFormatter; import org.elasticsearch.search.aggregations.support.format.ValueFormatterStreams; @@ -43,7 +49,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; -import static org.elasticsearch.search.aggregations.reducers.BucketHelpers.GapPolicy; import static org.elasticsearch.search.aggregations.reducers.BucketHelpers.resolveBucketValue; public class DerivativeReducer extends Reducer { @@ -143,5 +148,23 @@ public class DerivativeReducer extends Reducer { return new DerivativeReducer(name, bucketsPaths, formatter, gapPolicy, metaData); } + @Override + public void doValidate(AggregatorFactory parent, AggregatorFactory[] aggFactories, List reducerFactories) { + if (bucketsPaths.length != 1) { + throw new ElasticsearchIllegalStateException(Reducer.Parser.BUCKETS_PATH.getPreferredName() + + " must contain a single entry for reducer [" + name + "]"); + } + if (!(parent instanceof HistogramAggregator.Factory)) { + throw new ElasticsearchIllegalStateException("derivative reducer [" + name + + "] must have a histogram or date_histogram as parent"); + } else { + HistogramAggregator.Factory histoParent = (HistogramAggregator.Factory) parent; + if (histoParent.minDocCount() != 0) { + throw new ElasticsearchIllegalStateException("parent histogram of derivative reducer [" + name + + "] must have min_doc_count of 0"); + } + } + } + } } diff --git a/src/test/java/org/elasticsearch/search/aggregations/reducers/DateDerivativeTests.java b/src/test/java/org/elasticsearch/search/aggregations/reducers/DateDerivativeTests.java index ad1c131c885..ede94abd973 100644 --- a/src/test/java/org/elasticsearch/search/aggregations/reducers/DateDerivativeTests.java +++ b/src/test/java/org/elasticsearch/search/aggregations/reducers/DateDerivativeTests.java @@ -109,7 +109,7 @@ public class DateDerivativeTests extends ElasticsearchIntegrationTest { SearchResponse response = client() .prepareSearch("idx") .addAggregation( - dateHistogram("histo").field("date").interval(DateHistogramInterval.MONTH) + dateHistogram("histo").field("date").interval(DateHistogramInterval.MONTH).minDocCount(0) .subAggregation(derivative("deriv").setBucketsPaths("_count"))).execute().actionGet(); assertSearchResponse(response); @@ -152,7 +152,7 @@ public class DateDerivativeTests extends ElasticsearchIntegrationTest { SearchResponse response = client() .prepareSearch("idx") .addAggregation( - dateHistogram("histo").field("date").interval(DateHistogramInterval.MONTH) + dateHistogram("histo").field("date").interval(DateHistogramInterval.MONTH).minDocCount(0) .subAggregation(derivative("deriv").setBucketsPaths("sum")).subAggregation(sum("sum").field("value"))) .execute().actionGet(); @@ -222,7 +222,7 @@ public class DateDerivativeTests extends ElasticsearchIntegrationTest { SearchResponse response = client() .prepareSearch("idx") .addAggregation( - dateHistogram("histo").field("dates").interval(DateHistogramInterval.MONTH) + dateHistogram("histo").field("dates").interval(DateHistogramInterval.MONTH).minDocCount(0) .subAggregation(derivative("deriv").setBucketsPaths("_count"))).execute().actionGet(); assertSearchResponse(response); @@ -278,7 +278,7 @@ public class DateDerivativeTests extends ElasticsearchIntegrationTest { SearchResponse response = client() .prepareSearch("idx_unmapped") .addAggregation( - dateHistogram("histo").field("date").interval(DateHistogramInterval.MONTH) + dateHistogram("histo").field("date").interval(DateHistogramInterval.MONTH).minDocCount(0) .subAggregation(derivative("deriv").setBucketsPaths("_count"))).execute().actionGet(); assertSearchResponse(response); @@ -294,7 +294,7 @@ public class DateDerivativeTests extends ElasticsearchIntegrationTest { SearchResponse response = client() .prepareSearch("idx", "idx_unmapped") .addAggregation( - dateHistogram("histo").field("date").interval(DateHistogramInterval.MONTH) + dateHistogram("histo").field("date").interval(DateHistogramInterval.MONTH).minDocCount(0) .subAggregation(derivative("deriv").setBucketsPaths("_count"))).execute().actionGet(); assertSearchResponse(response); diff --git a/src/test/java/org/elasticsearch/search/aggregations/reducers/DerivativeTests.java b/src/test/java/org/elasticsearch/search/aggregations/reducers/DerivativeTests.java index a5c9506aeac..6f5641fcffa 100644 --- a/src/test/java/org/elasticsearch/search/aggregations/reducers/DerivativeTests.java +++ b/src/test/java/org/elasticsearch/search/aggregations/reducers/DerivativeTests.java @@ -34,7 +34,6 @@ import org.junit.Test; import java.io.IOException; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; @@ -165,7 +164,7 @@ public class DerivativeTests extends ElasticsearchIntegrationTest { SearchResponse response = client() .prepareSearch("idx") .addAggregation( - histogram("histo").field(SINGLE_VALUED_FIELD_NAME).interval(interval) + histogram("histo").field(SINGLE_VALUED_FIELD_NAME).interval(interval).minDocCount(0) .subAggregation(derivative("deriv").setBucketsPaths("_count")) .subAggregation(derivative("2nd_deriv").setBucketsPaths("deriv"))).execute().actionGet(); @@ -202,7 +201,7 @@ public class DerivativeTests extends ElasticsearchIntegrationTest { SearchResponse response = client() .prepareSearch("idx") .addAggregation( - histogram("histo").field(SINGLE_VALUED_FIELD_NAME).interval(interval) + histogram("histo").field(SINGLE_VALUED_FIELD_NAME).interval(interval).minDocCount(0) .subAggregation(sum("sum").field(SINGLE_VALUED_FIELD_NAME)) .subAggregation(derivative("deriv").setBucketsPaths("sum"))).execute().actionGet(); @@ -248,7 +247,7 @@ public class DerivativeTests extends ElasticsearchIntegrationTest { SearchResponse response = client() .prepareSearch("idx_unmapped") .addAggregation( - histogram("histo").field(SINGLE_VALUED_FIELD_NAME).interval(interval) + histogram("histo").field(SINGLE_VALUED_FIELD_NAME).interval(interval).minDocCount(0) .subAggregation(derivative("deriv").setBucketsPaths("_count"))).execute().actionGet(); assertSearchResponse(response); @@ -264,7 +263,7 @@ public class DerivativeTests extends ElasticsearchIntegrationTest { SearchResponse response = client() .prepareSearch("idx", "idx_unmapped") .addAggregation( - histogram("histo").field(SINGLE_VALUED_FIELD_NAME).interval(interval) + histogram("histo").field(SINGLE_VALUED_FIELD_NAME).interval(interval).minDocCount(0) .subAggregation(derivative("deriv").setBucketsPaths("_count"))).execute().actionGet(); assertSearchResponse(response);