added validation of reducers

This commit is contained in:
Colin Goodheart-Smithe 2015-03-23 08:58:44 +00:00
parent cb4ab06021
commit b751f0e11b
7 changed files with 57 additions and 18 deletions

View File

@ -40,6 +40,7 @@ public class AggregatorFactories {
public static final AggregatorFactories EMPTY = new Empty(); public static final AggregatorFactories EMPTY = new Empty();
private AggregatorFactory parent;
private AggregatorFactory[] factories; private AggregatorFactory[] factories;
private List<ReducerFactory> reducerFactories; private List<ReducerFactory> reducerFactories;
@ -101,6 +102,7 @@ public class AggregatorFactories {
} }
void setParent(AggregatorFactory parent) { void setParent(AggregatorFactory parent) {
this.parent = parent;
for (AggregatorFactory factory : factories) { for (AggregatorFactory factory : factories) {
factory.parent = parent; factory.parent = parent;
} }
@ -111,7 +113,7 @@ public class AggregatorFactories {
factory.validate(); factory.validate();
} }
for (ReducerFactory factory : reducerFactories) { for (ReducerFactory factory : reducerFactories) {
factory.validate(); factory.validate(parent, factories, reducerFactories);
} }
} }

View File

@ -66,6 +66,10 @@ public abstract class AggregatorFactory {
return this; return this;
} }
public String name() {
return name;
}
/** /**
* 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)
*/ */

View File

@ -169,6 +169,10 @@ public class HistogramAggregator extends BucketsAggregator {
this.histogramFactory = histogramFactory; this.histogramFactory = histogramFactory;
} }
public long minDocCount() {
return minDocCount;
}
@Override @Override
protected Aggregator createUnmapped(AggregationContext aggregationContext, Aggregator parent, List<Reducer> reducers, protected Aggregator createUnmapped(AggregationContext aggregationContext, Aggregator parent, List<Reducer> reducers,
Map<String, Object> metaData) throws IOException { Map<String, Object> metaData) throws IOException {

View File

@ -19,9 +19,11 @@
package org.elasticsearch.search.aggregations.reducers; package org.elasticsearch.search.aggregations.reducers;
import org.elasticsearch.search.aggregations.Aggregator; import org.elasticsearch.search.aggregations.Aggregator;
import org.elasticsearch.search.aggregations.AggregatorFactory;
import org.elasticsearch.search.aggregations.support.AggregationContext; import org.elasticsearch.search.aggregations.support.AggregationContext;
import java.io.IOException; import java.io.IOException;
import java.util.List;
import java.util.Map; 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() { public final void validate(AggregatorFactory parent, AggregatorFactory[] factories, List<ReducerFactory> reducerFactories) {
doValidate(); doValidate(parent, factories, reducerFactories);
} }
protected abstract Reducer createInternal(AggregationContext context, Aggregator parent, boolean collectsFromSingleBucket, protected abstract Reducer createInternal(AggregationContext context, Aggregator parent, boolean collectsFromSingleBucket,
@ -79,7 +86,7 @@ public abstract class ReducerFactory {
return aggregator; return aggregator;
} }
public void doValidate() { public void doValidate(AggregatorFactory parent, AggregatorFactory[] factories, List<ReducerFactory> reducerFactories) {
} }
public void setMetaData(Map<String, Object> metaData) { public void setMetaData(Map<String, Object> metaData) {

View File

@ -22,18 +22,24 @@ package org.elasticsearch.search.aggregations.reducers.derivative;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import org.elasticsearch.ElasticsearchIllegalStateException;
import org.elasticsearch.common.Nullable; import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.search.aggregations.Aggregation; import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.Aggregator; import org.elasticsearch.search.aggregations.Aggregator;
import org.elasticsearch.search.aggregations.AggregatorFactory;
import org.elasticsearch.search.aggregations.InternalAggregation; import org.elasticsearch.search.aggregations.InternalAggregation;
import org.elasticsearch.search.aggregations.InternalAggregation.ReduceContext; import org.elasticsearch.search.aggregations.InternalAggregation.ReduceContext;
import org.elasticsearch.search.aggregations.InternalAggregation.Type; import org.elasticsearch.search.aggregations.InternalAggregation.Type;
import org.elasticsearch.search.aggregations.InternalAggregations; 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.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.AggregationContext;
import org.elasticsearch.search.aggregations.support.format.ValueFormatter; import org.elasticsearch.search.aggregations.support.format.ValueFormatter;
import org.elasticsearch.search.aggregations.support.format.ValueFormatterStreams; import org.elasticsearch.search.aggregations.support.format.ValueFormatterStreams;
@ -43,7 +49,6 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static org.elasticsearch.search.aggregations.reducers.BucketHelpers.GapPolicy;
import static org.elasticsearch.search.aggregations.reducers.BucketHelpers.resolveBucketValue; import static org.elasticsearch.search.aggregations.reducers.BucketHelpers.resolveBucketValue;
public class DerivativeReducer extends Reducer { public class DerivativeReducer extends Reducer {
@ -143,5 +148,23 @@ public class DerivativeReducer extends Reducer {
return new DerivativeReducer(name, bucketsPaths, formatter, gapPolicy, metaData); return new DerivativeReducer(name, bucketsPaths, formatter, gapPolicy, metaData);
} }
@Override
public void doValidate(AggregatorFactory parent, AggregatorFactory[] aggFactories, List<ReducerFactory> 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");
}
}
}
} }
} }

View File

@ -109,7 +109,7 @@ public class DateDerivativeTests extends ElasticsearchIntegrationTest {
SearchResponse response = client() SearchResponse response = client()
.prepareSearch("idx") .prepareSearch("idx")
.addAggregation( .addAggregation(
dateHistogram("histo").field("date").interval(DateHistogramInterval.MONTH) dateHistogram("histo").field("date").interval(DateHistogramInterval.MONTH).minDocCount(0)
.subAggregation(derivative("deriv").setBucketsPaths("_count"))).execute().actionGet(); .subAggregation(derivative("deriv").setBucketsPaths("_count"))).execute().actionGet();
assertSearchResponse(response); assertSearchResponse(response);
@ -152,7 +152,7 @@ public class DateDerivativeTests extends ElasticsearchIntegrationTest {
SearchResponse response = client() SearchResponse response = client()
.prepareSearch("idx") .prepareSearch("idx")
.addAggregation( .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"))) .subAggregation(derivative("deriv").setBucketsPaths("sum")).subAggregation(sum("sum").field("value")))
.execute().actionGet(); .execute().actionGet();
@ -222,7 +222,7 @@ public class DateDerivativeTests extends ElasticsearchIntegrationTest {
SearchResponse response = client() SearchResponse response = client()
.prepareSearch("idx") .prepareSearch("idx")
.addAggregation( .addAggregation(
dateHistogram("histo").field("dates").interval(DateHistogramInterval.MONTH) dateHistogram("histo").field("dates").interval(DateHistogramInterval.MONTH).minDocCount(0)
.subAggregation(derivative("deriv").setBucketsPaths("_count"))).execute().actionGet(); .subAggregation(derivative("deriv").setBucketsPaths("_count"))).execute().actionGet();
assertSearchResponse(response); assertSearchResponse(response);
@ -278,7 +278,7 @@ public class DateDerivativeTests extends ElasticsearchIntegrationTest {
SearchResponse response = client() SearchResponse response = client()
.prepareSearch("idx_unmapped") .prepareSearch("idx_unmapped")
.addAggregation( .addAggregation(
dateHistogram("histo").field("date").interval(DateHistogramInterval.MONTH) dateHistogram("histo").field("date").interval(DateHistogramInterval.MONTH).minDocCount(0)
.subAggregation(derivative("deriv").setBucketsPaths("_count"))).execute().actionGet(); .subAggregation(derivative("deriv").setBucketsPaths("_count"))).execute().actionGet();
assertSearchResponse(response); assertSearchResponse(response);
@ -294,7 +294,7 @@ public class DateDerivativeTests extends ElasticsearchIntegrationTest {
SearchResponse response = client() SearchResponse response = client()
.prepareSearch("idx", "idx_unmapped") .prepareSearch("idx", "idx_unmapped")
.addAggregation( .addAggregation(
dateHistogram("histo").field("date").interval(DateHistogramInterval.MONTH) dateHistogram("histo").field("date").interval(DateHistogramInterval.MONTH).minDocCount(0)
.subAggregation(derivative("deriv").setBucketsPaths("_count"))).execute().actionGet(); .subAggregation(derivative("deriv").setBucketsPaths("_count"))).execute().actionGet();
assertSearchResponse(response); assertSearchResponse(response);

View File

@ -34,7 +34,6 @@ import org.junit.Test;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
@ -165,7 +164,7 @@ public class DerivativeTests extends ElasticsearchIntegrationTest {
SearchResponse response = client() SearchResponse response = client()
.prepareSearch("idx") .prepareSearch("idx")
.addAggregation( .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("deriv").setBucketsPaths("_count"))
.subAggregation(derivative("2nd_deriv").setBucketsPaths("deriv"))).execute().actionGet(); .subAggregation(derivative("2nd_deriv").setBucketsPaths("deriv"))).execute().actionGet();
@ -202,7 +201,7 @@ public class DerivativeTests extends ElasticsearchIntegrationTest {
SearchResponse response = client() SearchResponse response = client()
.prepareSearch("idx") .prepareSearch("idx")
.addAggregation( .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(sum("sum").field(SINGLE_VALUED_FIELD_NAME))
.subAggregation(derivative("deriv").setBucketsPaths("sum"))).execute().actionGet(); .subAggregation(derivative("deriv").setBucketsPaths("sum"))).execute().actionGet();
@ -248,7 +247,7 @@ public class DerivativeTests extends ElasticsearchIntegrationTest {
SearchResponse response = client() SearchResponse response = client()
.prepareSearch("idx_unmapped") .prepareSearch("idx_unmapped")
.addAggregation( .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(); .subAggregation(derivative("deriv").setBucketsPaths("_count"))).execute().actionGet();
assertSearchResponse(response); assertSearchResponse(response);
@ -264,7 +263,7 @@ public class DerivativeTests extends ElasticsearchIntegrationTest {
SearchResponse response = client() SearchResponse response = client()
.prepareSearch("idx", "idx_unmapped") .prepareSearch("idx", "idx_unmapped")
.addAggregation( .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(); .subAggregation(derivative("deriv").setBucketsPaths("_count"))).execute().actionGet();
assertSearchResponse(response); assertSearchResponse(response);