Skip to content

Commit 54921c8

Browse files
committed
Aggregations: Adds GeoBounds Aggregation
The GeoBounds Aggregation is a new single bucket aggregation which outputs the coordinates of a bounding box containing all the points from all the documents passed to the aggregation as well as the doc count. Geobound Aggregation also use a wrap_logitude parameter which specifies whether the resulting bounding box is permitted to overlap the international date line. This option defaults to true. This aggregation introduces the idea of MetricsAggregation which do not return double values and cannot be used for sorting. The existing MetricsAggregation has been renamed to NumericMetricsAggregation and is a subclass of MetricsAggregation. MetricsAggregations do not store doc counts and do not support child aggregations. Closes #5634
1 parent 648d012 commit 54921c8

37 files changed

+1058
-89
lines changed

docs/reference/search/aggregations.asciidoc

+7-5
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,13 @@ minimum value among all other values associated with the same document).
109109

110110
The aggregations in this family compute metrics based on values extracted in one way or another from the documents that
111111
are being aggregated. The values are typically extracted from the fields of the document (using the field data), but
112-
can also be generated using scripts. Some aggregations output a single metric (e.g. `avg`) and are called `single-value
113-
metrics aggregation`, others generate multiple metrics (e.g. `stats`) and are called `multi-value metrics aggregation`.
114-
The distinction between single-value and multi-value metrics aggregations plays a role when these aggregations serve as
115-
direct sub-aggregations of some bucket aggregations (some bucket aggregation enable you to sort the returned buckets based
116-
on the metrics in each bucket).
112+
can also be generated using scripts.
113+
114+
Numeric metrics aggregations are a special type of metrics aggregation which output numeric values. Some aggregations output
115+
a single numeric metric (e.g. `avg`) and are called `single-value numeric metrics aggregation`, others generate multiple
116+
metrics (e.g. `stats`) and are called `multi-value numeric metrics aggregation`. The distinction between single-value and
117+
multi-value numeric metrics aggregations plays a role when these aggregations serve as direct sub-aggregations of some
118+
bucket aggregations (some bucket aggregation enable you to sort the returned buckets based on the numeric metrics in each bucket).
117119

118120

119121
[float]

docs/reference/search/aggregations/metrics.asciidoc

+2
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,5 @@ include::metrics/valuecount-aggregation.asciidoc[]
1717
include::metrics/percentile-aggregation.asciidoc[]
1818

1919
include::metrics/cardinality-aggregation.asciidoc[]
20+
21+
include::metrics/geobounds-aggregation.asciidoc[]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
[[search-aggregations-metrics-geobounds-aggregation]]
2+
=== Geo Bounds Aggregation
3+
4+
coming[1.3.0]
5+
6+
A metric aggregation that computes the bounding box containing all geo_point values for a field.
7+
8+
.Experimental!
9+
[IMPORTANT]
10+
=====
11+
This feature is marked as experimental, and may be subject to change in the
12+
future. If you use this feature, please let us know your experience with it!
13+
=====
14+
15+
Example:
16+
17+
[source,js]
18+
--------------------------------------------------
19+
{
20+
"query" : {
21+
"match" : { "business_type" : "shop" }
22+
},
23+
"aggs" : {
24+
"viewport" : {
25+
"geo_bounds" : {
26+
"field" : "location" <1>
27+
"wrap_longitude" : "true" <2>
28+
}
29+
}
30+
}
31+
}
32+
--------------------------------------------------
33+
34+
<1> The `geo_bounds` aggregation specifies the field to use to obtain the bounds
35+
<2> `wrap_longitude` is an optional parameter which specifies whether the bounding box should be allowed to overlap the international date line. The default value is `true`
36+
37+
The above aggregation demonstrates how one would compute the bounding box of the location field for all documents with a business type of shop
38+
39+
The response for the above aggregation:
40+
41+
[source,js]
42+
--------------------------------------------------
43+
{
44+
...
45+
46+
"aggregations": {
47+
"viewport": {
48+
"bounds": {
49+
"top_left": {
50+
"lat": 80.45,
51+
"lon": -160.22
52+
},
53+
"bottom_right": {
54+
"lat": 40.65,
55+
"lon": 42.57
56+
}
57+
}
58+
}
59+
}
60+
}
61+
--------------------------------------------------

src/main/java/org/elasticsearch/index/query/functionscore/DecayFunctionParser.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
import org.elasticsearch.index.query.functionscore.gauss.GaussDecayFunctionBuilder;
5151
import org.elasticsearch.index.query.functionscore.gauss.GaussDecayFunctionParser;
5252
import org.elasticsearch.search.MultiValueMode;
53-
import org.elasticsearch.search.aggregations.metrics.MetricsAggregation;
53+
import org.elasticsearch.search.aggregations.metrics.InternalNumericMetricsAggregation;
5454
import org.elasticsearch.search.internal.SearchContext;
5555

5656
import java.io.IOException;

src/main/java/org/elasticsearch/search/aggregations/AggregationBuilders.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,17 @@
2525
import org.elasticsearch.search.aggregations.bucket.histogram.HistogramBuilder;
2626
import org.elasticsearch.search.aggregations.bucket.missing.MissingBuilder;
2727
import org.elasticsearch.search.aggregations.bucket.nested.NestedBuilder;
28+
import org.elasticsearch.search.aggregations.bucket.nested.ReverseNestedBuilder;
2829
import org.elasticsearch.search.aggregations.bucket.range.RangeBuilder;
2930
import org.elasticsearch.search.aggregations.bucket.range.date.DateRangeBuilder;
3031
import org.elasticsearch.search.aggregations.bucket.range.geodistance.GeoDistanceBuilder;
3132
import org.elasticsearch.search.aggregations.bucket.range.ipv4.IPv4RangeBuilder;
32-
import org.elasticsearch.search.aggregations.bucket.nested.ReverseNestedBuilder;
3333
import org.elasticsearch.search.aggregations.bucket.significant.SignificantTermsBuilder;
3434
import org.elasticsearch.search.aggregations.bucket.terms.TermsBuilder;
3535
import org.elasticsearch.search.aggregations.bucket.tophits.TopHitsBuilder;
3636
import org.elasticsearch.search.aggregations.metrics.avg.AvgBuilder;
3737
import org.elasticsearch.search.aggregations.metrics.cardinality.CardinalityBuilder;
38+
import org.elasticsearch.search.aggregations.metrics.geobounds.GeoBoundsBuilder;
3839
import org.elasticsearch.search.aggregations.metrics.max.MaxBuilder;
3940
import org.elasticsearch.search.aggregations.metrics.min.MinBuilder;
4041
import org.elasticsearch.search.aggregations.metrics.percentiles.PercentilesBuilder;
@@ -146,4 +147,8 @@ public static CardinalityBuilder cardinality(String name) {
146147
public static TopHitsBuilder topHits(String name) {
147148
return new TopHitsBuilder(name);
148149
}
150+
151+
public static GeoBoundsBuilder geoBounds(String name) {
152+
return new GeoBoundsBuilder(name);
153+
}
149154
}

src/main/java/org/elasticsearch/search/aggregations/AggregationModule.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,17 @@
2828
import org.elasticsearch.search.aggregations.bucket.histogram.HistogramParser;
2929
import org.elasticsearch.search.aggregations.bucket.missing.MissingParser;
3030
import org.elasticsearch.search.aggregations.bucket.nested.NestedParser;
31+
import org.elasticsearch.search.aggregations.bucket.nested.ReverseNestedParser;
3132
import org.elasticsearch.search.aggregations.bucket.range.RangeParser;
3233
import org.elasticsearch.search.aggregations.bucket.range.date.DateRangeParser;
3334
import org.elasticsearch.search.aggregations.bucket.range.geodistance.GeoDistanceParser;
3435
import org.elasticsearch.search.aggregations.bucket.range.ipv4.IpRangeParser;
35-
import org.elasticsearch.search.aggregations.bucket.nested.ReverseNestedParser;
3636
import org.elasticsearch.search.aggregations.bucket.significant.SignificantTermsParser;
3737
import org.elasticsearch.search.aggregations.bucket.terms.TermsParser;
3838
import org.elasticsearch.search.aggregations.bucket.tophits.TopHitsParser;
3939
import org.elasticsearch.search.aggregations.metrics.avg.AvgParser;
4040
import org.elasticsearch.search.aggregations.metrics.cardinality.CardinalityParser;
41+
import org.elasticsearch.search.aggregations.metrics.geobounds.GeoBoundsParser;
4142
import org.elasticsearch.search.aggregations.metrics.max.MaxParser;
4243
import org.elasticsearch.search.aggregations.metrics.min.MinParser;
4344
import org.elasticsearch.search.aggregations.metrics.percentiles.PercentilesParser;
@@ -81,6 +82,7 @@ public AggregationModule() {
8182
parsers.add(NestedParser.class);
8283
parsers.add(ReverseNestedParser.class);
8384
parsers.add(TopHitsParser.class);
85+
parsers.add(GeoBoundsParser.class);
8486
}
8587

8688
/**

src/main/java/org/elasticsearch/search/aggregations/TransportAggregationModule.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@
2626
import org.elasticsearch.search.aggregations.bucket.histogram.InternalHistogram;
2727
import org.elasticsearch.search.aggregations.bucket.missing.InternalMissing;
2828
import org.elasticsearch.search.aggregations.bucket.nested.InternalNested;
29+
import org.elasticsearch.search.aggregations.bucket.nested.InternalReverseNested;
2930
import org.elasticsearch.search.aggregations.bucket.range.InternalRange;
3031
import org.elasticsearch.search.aggregations.bucket.range.date.InternalDateRange;
3132
import org.elasticsearch.search.aggregations.bucket.range.geodistance.InternalGeoDistance;
3233
import org.elasticsearch.search.aggregations.bucket.range.ipv4.InternalIPv4Range;
33-
import org.elasticsearch.search.aggregations.bucket.nested.InternalReverseNested;
3434
import org.elasticsearch.search.aggregations.bucket.significant.SignificantLongTerms;
3535
import org.elasticsearch.search.aggregations.bucket.significant.SignificantStringTerms;
3636
import org.elasticsearch.search.aggregations.bucket.significant.UnmappedSignificantTerms;
@@ -41,6 +41,7 @@
4141
import org.elasticsearch.search.aggregations.bucket.tophits.InternalTopHits;
4242
import org.elasticsearch.search.aggregations.metrics.avg.InternalAvg;
4343
import org.elasticsearch.search.aggregations.metrics.cardinality.InternalCardinality;
44+
import org.elasticsearch.search.aggregations.metrics.geobounds.InternalGeoBounds;
4445
import org.elasticsearch.search.aggregations.metrics.max.InternalMax;
4546
import org.elasticsearch.search.aggregations.metrics.min.InternalMin;
4647
import org.elasticsearch.search.aggregations.metrics.percentiles.InternalPercentiles;
@@ -89,5 +90,6 @@ protected void configure() {
8990
InternalNested.registerStream();
9091
InternalReverseNested.registerStream();
9192
InternalTopHits.registerStreams();
93+
InternalGeoBounds.registerStream();
9294
}
9395
}

src/main/java/org/elasticsearch/search/aggregations/bucket/terms/InternalOrder.java

+6-6
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
import org.elasticsearch.search.aggregations.bucket.BucketsAggregator;
2929
import org.elasticsearch.search.aggregations.bucket.MultiBucketsAggregation;
3030
import org.elasticsearch.search.aggregations.bucket.SingleBucketAggregator;
31-
import org.elasticsearch.search.aggregations.metrics.MetricsAggregator;
31+
import org.elasticsearch.search.aggregations.metrics.NumericMetricsAggregator;
3232
import org.elasticsearch.search.aggregations.support.OrderPath;
3333

3434
import java.io.IOException;
@@ -171,13 +171,13 @@ public int compare(Terms.Bucket o1, Terms.Bucket o2) {
171171
// with only support single-bucket aggregators
172172
assert !(aggregator instanceof BucketsAggregator) : "this should be picked up before the aggregation is executed - on validate";
173173

174-
if (aggregator instanceof MetricsAggregator.MultiValue) {
174+
if (aggregator instanceof NumericMetricsAggregator.MultiValue) {
175175
assert key != null : "this should be picked up before the aggregation is executed - on validate";
176176
return new Comparator<Terms.Bucket>() {
177177
@Override
178178
public int compare(Terms.Bucket o1, Terms.Bucket o2) {
179-
double v1 = ((MetricsAggregator.MultiValue) aggregator).metric(key, ((InternalTerms.Bucket) o1).bucketOrd);
180-
double v2 = ((MetricsAggregator.MultiValue) aggregator).metric(key, ((InternalTerms.Bucket) o2).bucketOrd);
179+
double v1 = ((NumericMetricsAggregator.MultiValue) aggregator).metric(key, ((InternalTerms.Bucket) o1).bucketOrd);
180+
double v2 = ((NumericMetricsAggregator.MultiValue) aggregator).metric(key, ((InternalTerms.Bucket) o2).bucketOrd);
181181
// some metrics may return NaN (eg. avg, variance, etc...) in which case we'd like to push all of those to
182182
// the bottom
183183
return Comparators.compareDiscardNaN(v1, v2, asc);
@@ -189,8 +189,8 @@ public int compare(Terms.Bucket o1, Terms.Bucket o2) {
189189
return new Comparator<Terms.Bucket>() {
190190
@Override
191191
public int compare(Terms.Bucket o1, Terms.Bucket o2) {
192-
double v1 = ((MetricsAggregator.SingleValue) aggregator).metric(((InternalTerms.Bucket) o1).bucketOrd);
193-
double v2 = ((MetricsAggregator.SingleValue) aggregator).metric(((InternalTerms.Bucket) o2).bucketOrd);
192+
double v1 = ((NumericMetricsAggregator.SingleValue) aggregator).metric(((InternalTerms.Bucket) o1).bucketOrd);
193+
double v2 = ((NumericMetricsAggregator.SingleValue) aggregator).metric(((InternalTerms.Bucket) o2).bucketOrd);
194194
// some metrics may return NaN (eg. avg, variance, etc...) in which case we'd like to push all of those to
195195
// the bottom
196196
return Comparators.compareDiscardNaN(v1, v2, asc);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.search.aggregations.metrics;
21+
22+
import org.elasticsearch.search.aggregations.InternalAggregation;
23+
24+
public abstract class InternalMetricsAggregation extends InternalAggregation {
25+
26+
protected InternalMetricsAggregation() {} // for serialization
27+
28+
protected InternalMetricsAggregation(String name) {
29+
super(name);
30+
}
31+
}

src/main/java/org/elasticsearch/search/aggregations/metrics/MetricsAggregation.java renamed to src/main/java/org/elasticsearch/search/aggregations/metrics/InternalNumericMetricsAggregation.java

+5-6
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,16 @@
1818
*/
1919
package org.elasticsearch.search.aggregations.metrics;
2020

21-
import org.elasticsearch.search.aggregations.InternalAggregation;
2221
import org.elasticsearch.search.aggregations.support.format.ValueFormatter;
2322

2423
/**
2524
*
2625
*/
27-
public abstract class MetricsAggregation extends InternalAggregation {
26+
public abstract class InternalNumericMetricsAggregation extends InternalMetricsAggregation {
2827

2928
protected ValueFormatter valueFormatter;
3029

31-
public static abstract class SingleValue extends MetricsAggregation {
30+
public static abstract class SingleValue extends InternalNumericMetricsAggregation {
3231

3332
protected SingleValue() {}
3433

@@ -39,7 +38,7 @@ protected SingleValue(String name) {
3938
public abstract double value();
4039
}
4140

42-
public static abstract class MultiValue extends MetricsAggregation {
41+
public static abstract class MultiValue extends InternalNumericMetricsAggregation {
4342

4443
protected MultiValue() {}
4544

@@ -51,9 +50,9 @@ protected MultiValue(String name) {
5150

5251
}
5352

54-
protected MetricsAggregation() {} // for serialization
53+
protected InternalNumericMetricsAggregation() {} // for serialization
5554

56-
protected MetricsAggregation(String name) {
55+
protected InternalNumericMetricsAggregation(String name) {
5756
super(name);
5857
}
5958

src/main/java/org/elasticsearch/search/aggregations/metrics/MetricsAggregator.java

+2-24
Original file line numberDiff line numberDiff line change
@@ -16,38 +16,16 @@
1616
* specific language governing permissions and limitations
1717
* under the License.
1818
*/
19+
1920
package org.elasticsearch.search.aggregations.metrics;
2021

2122
import org.elasticsearch.search.aggregations.Aggregator;
2223
import org.elasticsearch.search.aggregations.AggregatorFactories;
2324
import org.elasticsearch.search.aggregations.support.AggregationContext;
2425

25-
/**
26-
*
27-
*/
2826
public abstract class MetricsAggregator extends Aggregator {
2927

30-
private MetricsAggregator(String name, long estimatedBucketsCount, AggregationContext context, Aggregator parent) {
28+
protected MetricsAggregator(String name, long estimatedBucketsCount, AggregationContext context, Aggregator parent) {
3129
super(name, BucketAggregationMode.MULTI_BUCKETS, AggregatorFactories.EMPTY, estimatedBucketsCount, context, parent);
3230
}
33-
34-
public static abstract class SingleValue extends MetricsAggregator {
35-
36-
protected SingleValue(String name, long estimatedBucketsCount, AggregationContext context, Aggregator parent) {
37-
super(name, estimatedBucketsCount, context, parent);
38-
}
39-
40-
public abstract double metric(long owningBucketOrd);
41-
}
42-
43-
public static abstract class MultiValue extends MetricsAggregator {
44-
45-
protected MultiValue(String name, long estimatedBucketsCount, AggregationContext context, Aggregator parent) {
46-
super(name, estimatedBucketsCount, context, parent);
47-
}
48-
49-
public abstract boolean hasMetric(String name);
50-
51-
public abstract double metric(String name, long owningBucketOrd);
52-
}
5331
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.elasticsearch.search.aggregations.metrics;
20+
21+
import org.elasticsearch.search.aggregations.Aggregator;
22+
import org.elasticsearch.search.aggregations.support.AggregationContext;
23+
24+
/**
25+
*
26+
*/
27+
public abstract class NumericMetricsAggregator extends MetricsAggregator {
28+
29+
private NumericMetricsAggregator(String name, long estimatedBucketsCount, AggregationContext context, Aggregator parent) {
30+
super(name, estimatedBucketsCount, context, parent);
31+
}
32+
33+
public static abstract class SingleValue extends NumericMetricsAggregator {
34+
35+
protected SingleValue(String name, long estimatedBucketsCount, AggregationContext context, Aggregator parent) {
36+
super(name, estimatedBucketsCount, context, parent);
37+
}
38+
39+
public abstract double metric(long owningBucketOrd);
40+
}
41+
42+
public static abstract class MultiValue extends NumericMetricsAggregator {
43+
44+
protected MultiValue(String name, long estimatedBucketsCount, AggregationContext context, Aggregator parent) {
45+
super(name, estimatedBucketsCount, context, parent);
46+
}
47+
48+
public abstract boolean hasMetric(String name);
49+
50+
public abstract double metric(String name, long owningBucketOrd);
51+
}
52+
}

src/main/java/org/elasticsearch/search/aggregations/metrics/NumericValuesSourceMetricsAggregatorParser.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
/**
3434
*
3535
*/
36-
public abstract class NumericValuesSourceMetricsAggregatorParser<S extends MetricsAggregation> implements Aggregator.Parser {
36+
public abstract class NumericValuesSourceMetricsAggregatorParser<S extends InternalNumericMetricsAggregation> implements Aggregator.Parser {
3737

3838
protected final InternalAggregation.Type aggType;
3939

0 commit comments

Comments
 (0)