Skip to content

Commit 21556f9

Browse files
committed
Aggregations Refactor: Refactor Geobounds Aggregation
1 parent 84c8f70 commit 21556f9

File tree

3 files changed

+127
-35
lines changed

3 files changed

+127
-35
lines changed

core/src/main/java/org/elasticsearch/search/aggregations/metrics/geobounds/GeoBoundsAggregator.java

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,14 @@
2020
package org.elasticsearch.search.aggregations.metrics.geobounds;
2121

2222
import org.apache.lucene.index.LeafReaderContext;
23+
import org.elasticsearch.common.ParseField;
2324
import org.elasticsearch.common.geo.GeoPoint;
25+
import org.elasticsearch.common.io.stream.StreamInput;
26+
import org.elasticsearch.common.io.stream.StreamOutput;
2427
import org.elasticsearch.common.lease.Releasables;
2528
import org.elasticsearch.common.util.BigArrays;
2629
import org.elasticsearch.common.util.DoubleArray;
30+
import org.elasticsearch.common.xcontent.XContentBuilder;
2731
import org.elasticsearch.index.fielddata.MultiGeoPointValues;
2832
import org.elasticsearch.search.aggregations.Aggregator;
2933
import org.elasticsearch.search.aggregations.InternalAggregation;
@@ -32,16 +36,20 @@
3236
import org.elasticsearch.search.aggregations.metrics.MetricsAggregator;
3337
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
3438
import org.elasticsearch.search.aggregations.support.AggregationContext;
39+
import org.elasticsearch.search.aggregations.support.ValueType;
3540
import org.elasticsearch.search.aggregations.support.ValuesSource;
3641
import org.elasticsearch.search.aggregations.support.ValuesSourceAggregatorFactory;
37-
import org.elasticsearch.search.aggregations.support.ValuesSourceParser;
42+
import org.elasticsearch.search.aggregations.support.ValuesSourceType;
3843

3944
import java.io.IOException;
4045
import java.util.List;
4146
import java.util.Map;
47+
import java.util.Objects;
4248

4349
public final class GeoBoundsAggregator extends MetricsAggregator {
4450

51+
static final ParseField WRAP_LONGITUDE_FIELD = new ParseField("wrap_longitude");
52+
4553
private final ValuesSource.GeoPoint valuesSource;
4654
private final boolean wrapLongitude;
4755
DoubleArray tops;
@@ -168,13 +176,26 @@ public void doClose() {
168176

169177
public static class Factory extends ValuesSourceAggregatorFactory<ValuesSource.GeoPoint> {
170178

171-
private final boolean wrapLongitude;
179+
private boolean wrapLongitude = true;
180+
181+
public Factory(String name) {
182+
super(name, InternalGeoBounds.TYPE, ValuesSourceType.GEOPOINT, ValueType.GEOPOINT);
183+
}
172184

173-
protected Factory(String name, ValuesSourceParser.Input<ValuesSource.GeoPoint> input, boolean wrapLongitude) {
174-
super(name, InternalGeoBounds.TYPE, input);
185+
/**
186+
* Set whether to wrap longitudes. Defaults to true.
187+
*/
188+
public void wrapLongitude(boolean wrapLongitude) {
175189
this.wrapLongitude = wrapLongitude;
176190
}
177191

192+
/**
193+
* Get whether to wrap longitudes.
194+
*/
195+
public boolean wrapLongitude() {
196+
return wrapLongitude;
197+
}
198+
178199
@Override
179200
protected Aggregator createUnmapped(AggregationContext aggregationContext, Aggregator parent,
180201
List<PipelineAggregator> pipelineAggregators, Map<String, Object> metaData) throws IOException {
@@ -188,5 +209,35 @@ protected Aggregator doCreateInternal(ValuesSource.GeoPoint valuesSource, Aggreg
188209
return new GeoBoundsAggregator(name, aggregationContext, parent, valuesSource, wrapLongitude, pipelineAggregators, metaData);
189210
}
190211

212+
@Override
213+
protected ValuesSourceAggregatorFactory<ValuesSource.GeoPoint> innerReadFrom(String name, ValuesSourceType valuesSourceType,
214+
ValueType targetValueType, StreamInput in) throws IOException {
215+
Factory factory = new Factory(name);
216+
factory.wrapLongitude = in.readBoolean();
217+
return factory;
218+
}
219+
220+
@Override
221+
protected void innerWriteTo(StreamOutput out) throws IOException {
222+
out.writeBoolean(wrapLongitude);
223+
}
224+
225+
@Override
226+
public XContentBuilder doXContentBody(XContentBuilder builder, Params params) throws IOException {
227+
builder.field(WRAP_LONGITUDE_FIELD.getPreferredName(), wrapLongitude);
228+
return builder;
229+
}
230+
231+
@Override
232+
protected int innerHashCode() {
233+
return Objects.hash(wrapLongitude);
234+
}
235+
236+
@Override
237+
protected boolean innerEquals(Object obj) {
238+
Factory other = (Factory) obj;
239+
return Objects.equals(wrapLongitude, other.wrapLongitude);
240+
}
241+
191242
}
192243
}

core/src/main/java/org/elasticsearch/search/aggregations/metrics/geobounds/GeoBoundsParser.java

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -19,58 +19,57 @@
1919

2020
package org.elasticsearch.search.aggregations.metrics.geobounds;
2121

22+
import org.elasticsearch.common.ParseField;
23+
import org.elasticsearch.common.ParseFieldMatcher;
2224
import org.elasticsearch.common.xcontent.XContentParser;
23-
import org.elasticsearch.search.SearchParseException;
24-
import org.elasticsearch.search.aggregations.Aggregator;
25+
import org.elasticsearch.common.xcontent.XContentParser.Token;
2526
import org.elasticsearch.search.aggregations.AggregatorFactory;
27+
import org.elasticsearch.search.aggregations.support.AbstractValuesSourceParser.GeoPointValuesSourceParser;
2628
import org.elasticsearch.search.aggregations.support.ValueType;
2729
import org.elasticsearch.search.aggregations.support.ValuesSource.GeoPoint;
28-
import org.elasticsearch.search.aggregations.support.ValuesSourceParser;
29-
import org.elasticsearch.search.internal.SearchContext;
30+
import org.elasticsearch.search.aggregations.support.ValuesSourceAggregatorFactory;
31+
import org.elasticsearch.search.aggregations.support.ValuesSourceType;
3032

3133
import java.io.IOException;
34+
import java.util.Map;
3235

33-
public class GeoBoundsParser implements Aggregator.Parser {
36+
public class GeoBoundsParser extends GeoPointValuesSourceParser {
37+
38+
public GeoBoundsParser() {
39+
super(false, false);
40+
}
3441

3542
@Override
3643
public String type() {
3744
return InternalGeoBounds.TYPE.name();
3845
}
3946

4047
@Override
41-
public AggregatorFactory parse(String aggregationName, XContentParser parser, SearchContext context) throws IOException {
42-
ValuesSourceParser<GeoPoint> vsParser = ValuesSourceParser.geoPoint(aggregationName, InternalGeoBounds.TYPE, context)
43-
.targetValueType(ValueType.GEOPOINT)
44-
.formattable(true)
45-
.build();
46-
boolean wrapLongitude = true;
47-
XContentParser.Token token;
48-
String currentFieldName = null;
49-
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
50-
if (token == XContentParser.Token.FIELD_NAME) {
51-
currentFieldName = parser.currentName();
52-
} else if (vsParser.token(currentFieldName, token, parser)) {
53-
continue;
48+
protected ValuesSourceAggregatorFactory<GeoPoint> createFactory(String aggregationName, ValuesSourceType valuesSourceType,
49+
ValueType targetValueType, Map<ParseField, Object> otherOptions) {
50+
GeoBoundsAggregator.Factory factory = new GeoBoundsAggregator.Factory(aggregationName);
51+
Boolean wrapLongitude = (Boolean) otherOptions.get(GeoBoundsAggregator.WRAP_LONGITUDE_FIELD);
52+
if (wrapLongitude != null) {
53+
factory.wrapLongitude(wrapLongitude);
54+
}
55+
return factory;
56+
}
5457

55-
} else if (token == XContentParser.Token.VALUE_BOOLEAN) {
56-
if ("wrap_longitude".equals(currentFieldName) || "wrapLongitude".equals(currentFieldName)) {
57-
wrapLongitude = parser.booleanValue();
58-
} else {
59-
throw new SearchParseException(context, "Unknown key for a " + token + " in aggregation [" + aggregationName + "]: ["
60-
+ currentFieldName + "].", parser.getTokenLocation());
61-
}
62-
} else {
63-
throw new SearchParseException(context, "Unknown key for a " + token + " in aggregation [" + aggregationName + "]: ["
64-
+ currentFieldName + "].", parser.getTokenLocation());
58+
@Override
59+
protected boolean token(String aggregationName, String currentFieldName, Token token, XContentParser parser,
60+
ParseFieldMatcher parseFieldMatcher, Map<ParseField, Object> otherOptions) throws IOException {
61+
if (token == XContentParser.Token.VALUE_BOOLEAN) {
62+
if (parseFieldMatcher.match(currentFieldName, GeoBoundsAggregator.WRAP_LONGITUDE_FIELD)) {
63+
otherOptions.put(GeoBoundsAggregator.WRAP_LONGITUDE_FIELD, parser.booleanValue());
64+
return true;
6565
}
6666
}
67-
return new GeoBoundsAggregator.Factory(aggregationName, vsParser.input(), wrapLongitude);
67+
return false;
6868
}
6969

70-
// NORELEASE implement this method when refactoring this aggregation
7170
@Override
7271
public AggregatorFactory[] getFactoryPrototypes() {
73-
return null;
72+
return new AggregatorFactory[] { new GeoBoundsAggregator.Factory(null) };
7473
}
7574

7675
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
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.BaseAggregationTestCase;
23+
import org.elasticsearch.search.aggregations.metrics.geobounds.GeoBoundsAggregator;
24+
import org.elasticsearch.search.aggregations.metrics.geobounds.GeoBoundsAggregator.Factory;
25+
26+
public class GeoBoundsTests extends BaseAggregationTestCase<GeoBoundsAggregator.Factory> {
27+
28+
@Override
29+
protected Factory createTestAggregatorFactory() {
30+
Factory factory = new Factory(randomAsciiOfLengthBetween(1, 20));
31+
String field = randomAsciiOfLengthBetween(3, 20);
32+
factory.field(field);
33+
if (randomBoolean()) {
34+
factory.wrapLongitude(randomBoolean());
35+
}
36+
if (randomBoolean()) {
37+
factory.missing("0,0");
38+
}
39+
return factory;
40+
}
41+
42+
}

0 commit comments

Comments
 (0)