From 9230743e4eba619249e5186948f51d21553bdbac Mon Sep 17 00:00:00 2001 From: Tanguy Leroux Date: Wed, 10 May 2017 15:28:54 +0200 Subject: [PATCH 1/3] Add parsing method to Range aggregations --- .../ParsedMultiBucketAggregation.java | 4 + .../bucket/range/ParsedRange.java | 193 ++++++++++++++++++ .../bucket/range/date/ParsedDateRange.java | 74 +++++++ .../range/geodistance/ParsedGeoDistance.java | 55 +++++ .../aggregations/AggregationsTests.java | 6 + .../bucket/range/InternalRangeTestCase.java | 13 +- .../bucket/range/InternalRangeTests.java | 17 +- .../range/date/InternalDateRangeTests.java | 9 +- .../geodistance/InternalGeoDistanceTests.java | 10 +- .../test/InternalAggregationTestCase.java | 9 + 10 files changed, 380 insertions(+), 10 deletions(-) create mode 100644 core/src/main/java/org/elasticsearch/search/aggregations/bucket/range/ParsedRange.java create mode 100644 core/src/main/java/org/elasticsearch/search/aggregations/bucket/range/date/ParsedDateRange.java create mode 100644 core/src/main/java/org/elasticsearch/search/aggregations/bucket/range/geodistance/ParsedGeoDistance.java diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/ParsedMultiBucketAggregation.java b/core/src/main/java/org/elasticsearch/search/aggregations/ParsedMultiBucketAggregation.java index 52b5fad53798e..df80ada8ddd1a 100644 --- a/core/src/main/java/org/elasticsearch/search/aggregations/ParsedMultiBucketAggregation.java +++ b/core/src/main/java/org/elasticsearch/search/aggregations/ParsedMultiBucketAggregation.java @@ -107,6 +107,10 @@ public void setKeyed(boolean keyed) { this.keyed = keyed; } + protected boolean isKeyed() { + return keyed; + } + protected void setAggregations(Aggregations aggregations) { this.aggregations = aggregations; } diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/range/ParsedRange.java b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/range/ParsedRange.java new file mode 100644 index 0000000000000..be584da1226a8 --- /dev/null +++ b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/range/ParsedRange.java @@ -0,0 +1,193 @@ +/* + * 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.range; + +import org.elasticsearch.common.CheckedFunction; +import org.elasticsearch.common.xcontent.ObjectParser; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.common.xcontent.XContentParserUtils; +import org.elasticsearch.search.aggregations.Aggregation; +import org.elasticsearch.search.aggregations.Aggregations; +import org.elasticsearch.search.aggregations.ParsedMultiBucketAggregation; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken; + +public class ParsedRange extends ParsedMultiBucketAggregation implements Range { + + @Override + public String getType() { + return RangeAggregationBuilder.NAME; + } + + @Override + public List getBuckets() { + return buckets; + } + + protected static void declareParsedRangeFields(final ObjectParser objectParser, + final CheckedFunction bucketParser, + final CheckedFunction keyedBucketParser) { + declareMultiBucketAggregationFields(objectParser, bucketParser::apply, keyedBucketParser::apply); + } + + private static ObjectParser PARSER = + new ObjectParser<>(ParsedRange.class.getSimpleName(), true, ParsedRange::new); + static { + declareParsedRangeFields(PARSER, + parser -> ParsedBucket.fromXContent(parser, false), + parser -> ParsedBucket.fromXContent(parser, true)); + } + + public static ParsedRange fromXContent(XContentParser parser, String name) throws IOException { + ParsedRange aggregation = PARSER.parse(parser, null); + aggregation.setName(name); + return aggregation; + } + + public static class ParsedBucket extends ParsedMultiBucketAggregation.ParsedBucket implements Range.Bucket { + + protected String key; + protected double from; + protected String fromAsString; + protected double to; + protected String toAsString; + + @Override + public String getKey() { + return getKeyAsString(); + } + + @Override + public String getKeyAsString() { + String keyAsString = super.getKeyAsString(); + if (keyAsString != null) { + return keyAsString; + } + return key; + } + + @Override + public Object getFrom() { + return from; + } + + @Override + public String getFromAsString() { + if (fromAsString != null) { + return fromAsString; + } + return doubleAsString(from); + } + + @Override + public Object getTo() { + return to; + } + + @Override + public String getToAsString() { + if (toAsString != null) { + return toAsString; + } + return doubleAsString(to); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + if (isKeyed()) { + builder.startObject(key); + } else { + builder.startObject(); + builder.field(CommonFields.KEY.getPreferredName(), key); + } + if (!Double.isInfinite(from)) { + builder.field(CommonFields.FROM.getPreferredName(), from); + if (fromAsString != null) { + builder.field(CommonFields.FROM_AS_STRING.getPreferredName(), fromAsString); + } + } + if (!Double.isInfinite(to)) { + builder.field(CommonFields.TO.getPreferredName(), to); + if (toAsString != null) { + builder.field(CommonFields.TO_AS_STRING.getPreferredName(), toAsString); + } + } + builder.field(CommonFields.DOC_COUNT.getPreferredName(), getDocCount()); + getAggregations().toXContentInternal(builder, params); + builder.endObject(); + return builder; + } + + private static String doubleAsString(double d) { + return Double.isInfinite(d) ? null : Double.toString(d); + } + + protected static B parseRangeBucketXContent(final XContentParser parser, + final Supplier bucketSupplier, + final boolean keyed) throws IOException { + final B bucket = bucketSupplier.get(); + bucket.setKeyed(keyed); + XContentParser.Token token = parser.currentToken(); + String currentFieldName = parser.currentName(); + if (keyed) { + ensureExpectedToken(XContentParser.Token.FIELD_NAME, token, parser::getTokenLocation); + bucket.key = currentFieldName; + ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser::getTokenLocation); + } + + List aggregations = new ArrayList<>(); + while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { + if (token == XContentParser.Token.FIELD_NAME) { + currentFieldName = parser.currentName(); + } else if (token.isValue()) { + if (CommonFields.KEY_AS_STRING.getPreferredName().equals(currentFieldName)) { + bucket.setKeyAsString(parser.text()); + } else if (CommonFields.KEY.getPreferredName().equals(currentFieldName)) { + bucket.key = parser.text(); + } else if (CommonFields.DOC_COUNT.getPreferredName().equals(currentFieldName)) { + bucket.setDocCount(parser.longValue()); + } else if (CommonFields.FROM.getPreferredName().equals(currentFieldName)) { + bucket.from = parser.doubleValue(); + } else if (CommonFields.FROM_AS_STRING.getPreferredName().equals(currentFieldName)) { + bucket.fromAsString = parser.text(); + } else if (CommonFields.TO.getPreferredName().equals(currentFieldName)) { + bucket.to = parser.doubleValue(); + } else if (CommonFields.TO_AS_STRING.getPreferredName().equals(currentFieldName)) { + bucket.toAsString = parser.text(); + } + } else if (token == XContentParser.Token.START_OBJECT) { + aggregations.add(XContentParserUtils.parseTypedKeysObject(parser, Aggregation.TYPED_KEYS_DELIMITER, Aggregation.class)); + } + } + bucket.setAggregations(new Aggregations(aggregations)); + return bucket; + } + + static ParsedBucket fromXContent(final XContentParser parser, final boolean keyed) throws IOException { + return parseRangeBucketXContent(parser, ParsedBucket::new, keyed); + } + } +} diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/range/date/ParsedDateRange.java b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/range/date/ParsedDateRange.java new file mode 100644 index 0000000000000..b8f2f008cec65 --- /dev/null +++ b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/range/date/ParsedDateRange.java @@ -0,0 +1,74 @@ +/* + * 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.range.date; + +import org.elasticsearch.common.xcontent.ObjectParser; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.search.aggregations.bucket.range.ParsedRange; +import org.joda.time.DateTime; +import org.joda.time.DateTimeZone; + +import java.io.IOException; + +public class ParsedDateRange extends ParsedRange { + + @Override + public String getType() { + return DateRangeAggregationBuilder.NAME; + } + + private static ObjectParser PARSER = + new ObjectParser<>(ParsedDateRange.class.getSimpleName(), true, ParsedDateRange::new); + static { + declareParsedRangeFields(PARSER, + parser -> ParsedBucket.fromXContent(parser, false), + parser -> ParsedBucket.fromXContent(parser, true)); + } + + public static ParsedDateRange fromXContent(XContentParser parser, String name) throws IOException { + ParsedDateRange aggregation = PARSER.parse(parser, null); + aggregation.setName(name); + return aggregation; + } + + public static class ParsedBucket extends ParsedRange.ParsedBucket { + + @Override + public Object getFrom() { + return doubleAsDateTime(from); + } + + @Override + public Object getTo() { + return doubleAsDateTime(to); + } + + private static DateTime doubleAsDateTime(Double d) { + if (d == null || Double.isInfinite(d)) { + return null; + } + return new DateTime(d.longValue(), DateTimeZone.UTC); + } + + static ParsedBucket fromXContent(final XContentParser parser, final boolean keyed) throws IOException { + return parseRangeBucketXContent(parser, ParsedBucket::new, keyed); + } + } +} diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/range/geodistance/ParsedGeoDistance.java b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/range/geodistance/ParsedGeoDistance.java new file mode 100644 index 0000000000000..a926499e9249a --- /dev/null +++ b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/range/geodistance/ParsedGeoDistance.java @@ -0,0 +1,55 @@ +/* + * 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.range.geodistance; + +import org.elasticsearch.common.xcontent.ObjectParser; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.search.aggregations.bucket.range.ParsedRange; + +import java.io.IOException; + +public class ParsedGeoDistance extends ParsedRange { + + @Override + public String getType() { + return GeoDistanceAggregationBuilder.NAME; + } + + private static ObjectParser PARSER = + new ObjectParser<>(ParsedGeoDistance.class.getSimpleName(), true, ParsedGeoDistance::new); + static { + declareParsedRangeFields(PARSER, + parser -> ParsedBucket.fromXContent(parser, false), + parser -> ParsedBucket.fromXContent(parser, true)); + } + + public static ParsedGeoDistance fromXContent(XContentParser parser, String name) throws IOException { + ParsedGeoDistance aggregation = PARSER.parse(parser, null); + aggregation.setName(name); + return aggregation; + } + + public static class ParsedBucket extends ParsedRange.ParsedBucket { + + static ParsedBucket fromXContent(final XContentParser parser, final boolean keyed) throws IOException { + return parseRangeBucketXContent(parser, ParsedBucket::new, keyed); + } + } +} diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/AggregationsTests.java b/core/src/test/java/org/elasticsearch/search/aggregations/AggregationsTests.java index d741240e15804..4cfc87c171c5a 100644 --- a/core/src/test/java/org/elasticsearch/search/aggregations/AggregationsTests.java +++ b/core/src/test/java/org/elasticsearch/search/aggregations/AggregationsTests.java @@ -37,6 +37,9 @@ import org.elasticsearch.search.aggregations.bucket.nested.InternalNestedTests; import org.elasticsearch.search.aggregations.bucket.nested.InternalReverseNestedTests; import org.elasticsearch.search.aggregations.bucket.sampler.InternalSamplerTests; +import org.elasticsearch.search.aggregations.bucket.range.InternalRangeTests; +import org.elasticsearch.search.aggregations.bucket.range.date.InternalDateRangeTests; +import org.elasticsearch.search.aggregations.bucket.range.geodistance.InternalGeoDistanceTests; import org.elasticsearch.search.aggregations.bucket.terms.DoubleTermsTests; import org.elasticsearch.search.aggregations.bucket.terms.LongTermsTests; import org.elasticsearch.search.aggregations.bucket.terms.StringTermsTests; @@ -119,6 +122,9 @@ private static List getAggsTests() { aggsTests.add(new InternalFilterTests()); aggsTests.add(new InternalSamplerTests()); aggsTests.add(new InternalGeoHashGridTests()); + aggsTests.add(new InternalRangeTests()); + aggsTests.add(new InternalDateRangeTests()); + aggsTests.add(new InternalGeoDistanceTests()); return Collections.unmodifiableList(aggsTests); } diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/range/InternalRangeTestCase.java b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/range/InternalRangeTestCase.java index 1edaea2f8ecf7..d23af79d33568 100644 --- a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/range/InternalRangeTestCase.java +++ b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/range/InternalRangeTestCase.java @@ -20,15 +20,16 @@ package org.elasticsearch.search.aggregations.bucket.range; import org.elasticsearch.search.aggregations.InternalAggregation; +import org.elasticsearch.search.aggregations.InternalAggregations; +import org.elasticsearch.search.aggregations.InternalMultiBucketAggregationTestCase; import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator; -import org.elasticsearch.test.InternalAggregationTestCase; import org.junit.Before; import java.util.List; import java.util.Map; import java.util.TreeMap; -public abstract class InternalRangeTestCase extends InternalAggregationTestCase { +public abstract class InternalRangeTestCase extends InternalMultiBucketAggregationTestCase { private boolean keyed; @@ -40,13 +41,17 @@ public void setUp() throws Exception { } @Override - protected T createTestInstance(String name, List pipelineAggregators, Map metaData) { - return createTestInstance(name, pipelineAggregators, metaData, keyed); + protected T createTestInstance(String name, + List pipelineAggregators, + Map metaData, + InternalAggregations aggregations) { + return createTestInstance(name, pipelineAggregators, metaData, aggregations, keyed); } protected abstract T createTestInstance(String name, List pipelineAggregators, Map metaData, + InternalAggregations aggregations, boolean keyed); @Override protected void assertReduced(T reduced, List inputs) { diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/range/InternalRangeTests.java b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/range/InternalRangeTests.java index 9264028d0734a..8bbf0e187e8ba 100644 --- a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/range/InternalRangeTests.java +++ b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/range/InternalRangeTests.java @@ -23,6 +23,7 @@ import org.elasticsearch.common.io.stream.Writeable; import org.elasticsearch.search.DocValueFormat; import org.elasticsearch.search.aggregations.InternalAggregations; +import org.elasticsearch.search.aggregations.ParsedMultiBucketAggregation; import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator; import org.junit.Before; @@ -43,7 +44,7 @@ public void setUp() throws Exception { format = randomNumericDocValueFormat(); final int interval = randomFrom(1, 5, 10, 25, 50, 100); - final int numRanges = 1;//randomIntBetween(1, 10); + final int numRanges = randomIntBetween(1, 10); List> listOfRanges = new ArrayList<>(numRanges); for (int i = 0; i < numRanges; i++) { @@ -62,7 +63,10 @@ public void setUp() throws Exception { } @Override - protected InternalRange createTestInstance(String name, List pipelineAggregators, Map metaData, + protected InternalRange createTestInstance(String name, + List pipelineAggregators, + Map metaData, + InternalAggregations aggregations, boolean keyed) { final List buckets = new ArrayList<>(); for (int i = 0; i < ranges.size(); ++i) { @@ -70,13 +74,18 @@ protected InternalRange createTestInstance(String name, List int docCount = randomIntBetween(0, 1000); double from = range.v1(); double to = range.v2(); - buckets.add( new InternalRange.Bucket("range_" + i, from, to, docCount, InternalAggregations.EMPTY, keyed, format)); + buckets.add(new InternalRange.Bucket("range_" + i, from, to, docCount, aggregations, keyed, format)); } - return new InternalRange<>(name, buckets, format, keyed, pipelineAggregators, Collections.emptyMap()); + return new InternalRange<>(name, buckets, format, keyed, pipelineAggregators, metaData); } @Override protected Writeable.Reader instanceReader() { return InternalRange::new; } + + @Override + protected Class implementationClass() { + return ParsedRange.class; + } } diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/range/date/InternalDateRangeTests.java b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/range/date/InternalDateRangeTests.java index bbfcdf7463aae..318e5f6b5ad6f 100644 --- a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/range/date/InternalDateRangeTests.java +++ b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/range/date/InternalDateRangeTests.java @@ -23,6 +23,7 @@ import org.elasticsearch.common.io.stream.Writeable; import org.elasticsearch.search.DocValueFormat; import org.elasticsearch.search.aggregations.InternalAggregations; +import org.elasticsearch.search.aggregations.ParsedMultiBucketAggregation; import org.elasticsearch.search.aggregations.bucket.range.InternalRangeTestCase; import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator; import org.joda.time.DateTime; @@ -78,6 +79,7 @@ public void setUp() throws Exception { protected InternalDateRange createTestInstance(String name, List pipelineAggregators, Map metaData, + InternalAggregations aggregations, boolean keyed) { final List buckets = new ArrayList<>(); for (int i = 0; i < dateRanges.size(); ++i) { @@ -85,7 +87,7 @@ protected InternalDateRange createTestInstance(String name, int docCount = randomIntBetween(0, 1000); double from = range.v1(); double to = range.v2(); - buckets.add( new InternalDateRange.Bucket("range_" + i, from, to, docCount, InternalAggregations.EMPTY, keyed, format)); + buckets.add(new InternalDateRange.Bucket("range_" + i, from, to, docCount, aggregations, keyed, format)); } return new InternalDateRange(name, buckets, format, keyed, pipelineAggregators, metaData); } @@ -94,4 +96,9 @@ protected InternalDateRange createTestInstance(String name, protected Writeable.Reader instanceReader() { return InternalDateRange::new; } + + @Override + protected Class implementationClass() { + return ParsedDateRange.class; + } } diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/range/geodistance/InternalGeoDistanceTests.java b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/range/geodistance/InternalGeoDistanceTests.java index 9dd2a7a67c75b..25c0a9ae3e103 100644 --- a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/range/geodistance/InternalGeoDistanceTests.java +++ b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/range/geodistance/InternalGeoDistanceTests.java @@ -22,6 +22,7 @@ import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.io.stream.Writeable; import org.elasticsearch.search.aggregations.InternalAggregations; +import org.elasticsearch.search.aggregations.ParsedMultiBucketAggregation; import org.elasticsearch.search.aggregations.bucket.range.InternalRangeTestCase; import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator; import org.junit.Before; @@ -58,6 +59,7 @@ public void setUp() throws Exception { } geoDistanceRanges = Collections.unmodifiableList(listOfRanges); } + @Override protected Writeable.Reader instanceReader() { return InternalGeoDistance::new; @@ -67,6 +69,7 @@ protected Writeable.Reader instanceReader() { protected InternalGeoDistance createTestInstance(String name, List pipelineAggregators, Map metaData, + InternalAggregations aggregations, boolean keyed) { final List buckets = new ArrayList<>(); for (int i = 0; i < geoDistanceRanges.size(); ++i) { @@ -74,8 +77,13 @@ protected InternalGeoDistance createTestInstance(String name, int docCount = randomIntBetween(0, 1000); double from = range.v1(); double to = range.v2(); - buckets.add(new InternalGeoDistance.Bucket("range_" + i, from, to, docCount, InternalAggregations.EMPTY, keyed)); + buckets.add(new InternalGeoDistance.Bucket("range_" + i, from, to, docCount, aggregations, keyed)); } return new InternalGeoDistance(name, buckets, keyed, pipelineAggregators, metaData); } + + @Override + protected Class implementationClass() { + return ParsedGeoDistance.class; + } } diff --git a/test/framework/src/main/java/org/elasticsearch/test/InternalAggregationTestCase.java b/test/framework/src/main/java/org/elasticsearch/test/InternalAggregationTestCase.java index da7ac647c5c54..66dd194e01863 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/InternalAggregationTestCase.java +++ b/test/framework/src/main/java/org/elasticsearch/test/InternalAggregationTestCase.java @@ -59,6 +59,12 @@ import org.elasticsearch.search.aggregations.bucket.nested.ReverseNestedAggregationBuilder; import org.elasticsearch.search.aggregations.bucket.sampler.InternalSampler; import org.elasticsearch.search.aggregations.bucket.sampler.ParsedSampler; +import org.elasticsearch.search.aggregations.bucket.range.ParsedRange; +import org.elasticsearch.search.aggregations.bucket.range.RangeAggregationBuilder; +import org.elasticsearch.search.aggregations.bucket.range.date.DateRangeAggregationBuilder; +import org.elasticsearch.search.aggregations.bucket.range.date.ParsedDateRange; +import org.elasticsearch.search.aggregations.bucket.range.geodistance.GeoDistanceAggregationBuilder; +import org.elasticsearch.search.aggregations.bucket.range.geodistance.ParsedGeoDistance; import org.elasticsearch.search.aggregations.bucket.terms.DoubleTerms; import org.elasticsearch.search.aggregations.bucket.terms.LongTerms; import org.elasticsearch.search.aggregations.bucket.terms.ParsedDoubleTerms; @@ -164,6 +170,9 @@ public static List getNamedXContents() { namedXContents.put(FilterAggregationBuilder.NAME, (p, c) -> ParsedFilter.fromXContent(p, (String) c)); namedXContents.put(InternalSampler.NAME, (p, c) -> ParsedSampler.fromXContent(p, (String) c)); namedXContents.put(GeoGridAggregationBuilder.NAME, (p, c) -> ParsedGeoHashGrid.fromXContent(p, (String) c)); + namedXContents.put(RangeAggregationBuilder.NAME, (p, c) -> ParsedRange.fromXContent(p, (String) c)); + namedXContents.put(DateRangeAggregationBuilder.NAME, (p, c) -> ParsedDateRange.fromXContent(p, (String) c)); + namedXContents.put(GeoDistanceAggregationBuilder.NAME, (p, c) -> ParsedGeoDistance.fromXContent(p, (String) c)); return namedXContents.entrySet().stream() .map(entry -> new NamedXContentRegistry.Entry(Aggregation.class, new ParseField(entry.getKey()), entry.getValue())) From f18949c2b73452c4957b695407bbbc4424f41e2e Mon Sep 17 00:00:00 2001 From: Tanguy Leroux Date: Wed, 10 May 2017 17:39:53 +0200 Subject: [PATCH 2/3] Add missing verifications for Range aggs --- .../InternalMultiBucketAggregationTestCase.java | 2 +- .../bucket/range/InternalRangeTestCase.java | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/InternalMultiBucketAggregationTestCase.java b/core/src/test/java/org/elasticsearch/search/aggregations/InternalMultiBucketAggregationTestCase.java index b16b7f49d7e02..df977abbe8118 100644 --- a/core/src/test/java/org/elasticsearch/search/aggregations/InternalMultiBucketAggregationTestCase.java +++ b/core/src/test/java/org/elasticsearch/search/aggregations/InternalMultiBucketAggregationTestCase.java @@ -117,7 +117,7 @@ private void assertMultiBucketsAggregation(Aggregation expected, Aggregation act } } - private void assertBucket(MultiBucketsAggregation.Bucket expected, MultiBucketsAggregation.Bucket actual, boolean checkOrder) { + protected void assertBucket(MultiBucketsAggregation.Bucket expected, MultiBucketsAggregation.Bucket actual, boolean checkOrder) { assertTrue(expected instanceof InternalMultiBucketAggregation.InternalBucket); assertTrue(actual instanceof ParsedMultiBucketAggregation.ParsedBucket); diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/range/InternalRangeTestCase.java b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/range/InternalRangeTestCase.java index d23af79d33568..1901f4800e0df 100644 --- a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/range/InternalRangeTestCase.java +++ b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/range/InternalRangeTestCase.java @@ -22,6 +22,7 @@ import org.elasticsearch.search.aggregations.InternalAggregation; import org.elasticsearch.search.aggregations.InternalAggregations; import org.elasticsearch.search.aggregations.InternalMultiBucketAggregationTestCase; +import org.elasticsearch.search.aggregations.bucket.MultiBucketsAggregation; import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator; import org.junit.Before; @@ -70,4 +71,20 @@ protected void assertReduced(T reduced, List inputs) { } assertEquals(expectedCounts, actualCounts); } + + @Override + protected void assertBucket(MultiBucketsAggregation.Bucket expected, MultiBucketsAggregation.Bucket actual, boolean checkOrder) { + super.assertBucket(expected, actual, checkOrder); + + assertTrue(expected instanceof InternalRange.Bucket); + assertTrue(actual instanceof ParsedRange.ParsedBucket); + + Range.Bucket expectedRange = (Range.Bucket) expected; + Range.Bucket actualRange = (Range.Bucket) actual; + + assertEquals(expectedRange.getFrom(), actualRange.getFrom()); + assertEquals(expectedRange.getFromAsString(), actualRange.getFromAsString()); + assertEquals(expectedRange.getTo(), actualRange.getTo()); + assertEquals(expectedRange.getToAsString(), actualRange.getToAsString()); + } } From 13c2d129a57811dcacda3ac26f63647558cd1f39 Mon Sep 17 00:00:00 2001 From: Tanguy Leroux Date: Fri, 12 May 2017 16:21:34 +0200 Subject: [PATCH 3/3] Apply feedback --- .../search/aggregations/bucket/range/ParsedRange.java | 8 ++++---- .../aggregations/bucket/range/InternalRangeTests.java | 9 +++++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/range/ParsedRange.java b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/range/ParsedRange.java index be584da1226a8..85066296d5fdb 100644 --- a/core/src/main/java/org/elasticsearch/search/aggregations/bucket/range/ParsedRange.java +++ b/core/src/main/java/org/elasticsearch/search/aggregations/bucket/range/ParsedRange.java @@ -70,9 +70,9 @@ public static ParsedRange fromXContent(XContentParser parser, String name) throw public static class ParsedBucket extends ParsedMultiBucketAggregation.ParsedBucket implements Range.Bucket { protected String key; - protected double from; + protected double from = Double.NEGATIVE_INFINITY; protected String fromAsString; - protected double to; + protected double to = Double.POSITIVE_INFINITY; protected String toAsString; @Override @@ -123,13 +123,13 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws builder.startObject(); builder.field(CommonFields.KEY.getPreferredName(), key); } - if (!Double.isInfinite(from)) { + if (Double.isInfinite(from) == false) { builder.field(CommonFields.FROM.getPreferredName(), from); if (fromAsString != null) { builder.field(CommonFields.FROM_AS_STRING.getPreferredName(), fromAsString); } } - if (!Double.isInfinite(to)) { + if (Double.isInfinite(to) == false) { builder.field(CommonFields.TO.getPreferredName(), to); if (toAsString != null) { builder.field(CommonFields.TO_AS_STRING.getPreferredName(), toAsString); diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/range/InternalRangeTests.java b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/range/InternalRangeTests.java index 8bbf0e187e8ba..a235471852608 100644 --- a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/range/InternalRangeTests.java +++ b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/range/InternalRangeTests.java @@ -59,6 +59,15 @@ public void setUp() throws Exception { listOfRanges.add(Tuple.tuple(0.0, max / 2)); listOfRanges.add(Tuple.tuple(max / 3, max / 3 * 2)); } + if (rarely()) { + listOfRanges.add(Tuple.tuple(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY)); + } + if (rarely()) { + listOfRanges.add(Tuple.tuple(Double.NEGATIVE_INFINITY, randomDouble())); + } + if (rarely()) { + listOfRanges.add(Tuple.tuple(randomDouble(), Double.POSITIVE_INFINITY)); + } ranges = Collections.unmodifiableList(listOfRanges); }