Skip to content

Commit 2c07544

Browse files
committed
fixed some concerns by @colings86
1 parent 93ec1cd commit 2c07544

File tree

11 files changed

+113
-90
lines changed

11 files changed

+113
-90
lines changed

qa/rolling-upgrade/src/test/resources/rest-api-spec/test/old_cluster/10_basic.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,3 +229,15 @@
229229
- '{"location": "48.861111,2.336389", "name": "Musée du Louvre"}'
230230
- '{"index": {"_index": "geo_agg_index", "_type": "doc"}}'
231231
- '{"location": "48.860000,2.327000", "name": "Musée Orsay"}'
232+
- do:
233+
search:
234+
index: geo_agg_index
235+
body:
236+
aggregations:
237+
mygrid:
238+
geohash_grid:
239+
field : location
240+
precision : 1
241+
- match: { hits.total: 6 }
242+
- match: { aggregations.mygrid.buckets.0.key: u }
243+
- match: { aggregations.mygrid.buckets.0.doc_count: 6 }

server/src/main/java/org/elasticsearch/common/geo/GeoUtils.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,8 @@ public static int parsePrecisionString(String precision) {
557557
try {
558558
// we want to treat simple integer strings as precision levels, not distances
559559
return checkPrecisionRange(Integer.parseInt(precision));
560-
// Do not catch IllegalArgumentException here
560+
// checkPrecisionRange could also throw IllegalArgumentException, but let it through
561+
// to keep errors somewhat consistent with how they were shown before this change
561562
} catch (NumberFormatException e) {
562563
// try to parse as a distance value
563564
final int parsedPrecision = GeoUtils.geoHashLevelsForPrecision(precision);

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.elasticsearch.search.aggregations.bucket.filter.FiltersAggregator.KeyedFilter;
3131
import org.elasticsearch.search.aggregations.bucket.geogrid.GeoGridAggregationBuilder;
3232
import org.elasticsearch.search.aggregations.bucket.geogrid.GeoHashGrid;
33+
import org.elasticsearch.search.aggregations.bucket.geogrid.GeoHashType;
3334
import org.elasticsearch.search.aggregations.bucket.global.Global;
3435
import org.elasticsearch.search.aggregations.bucket.global.GlobalAggregationBuilder;
3536
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramAggregationBuilder;
@@ -237,7 +238,7 @@ public static HistogramAggregationBuilder histogram(String name) {
237238
* Create a new {@link GeoHashGrid} aggregation with the given name.
238239
*/
239240
public static GeoGridAggregationBuilder geohashGrid(String name) {
240-
return new GeoGridAggregationBuilder(name);
241+
return new GeoGridAggregationBuilder(name, GeoHashType.DEFAULT);
241242
}
242243

243244
/**

server/src/main/java/org/elasticsearch/search/aggregations/bucket/geogrid/GeoGridAggregationBuilder.java

Lines changed: 62 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@
2525
import org.elasticsearch.common.geo.GeoPoint;
2626
import org.elasticsearch.common.io.stream.StreamInput;
2727
import org.elasticsearch.common.io.stream.StreamOutput;
28+
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
2829
import org.elasticsearch.common.xcontent.ObjectParser;
2930
import org.elasticsearch.common.xcontent.XContentBuilder;
30-
import org.elasticsearch.common.xcontent.XContentLocation;
3131
import org.elasticsearch.common.xcontent.XContentParseException;
3232
import org.elasticsearch.common.xcontent.XContentParser;
3333
import org.elasticsearch.index.fielddata.AbstractSortingNumericDocValues;
@@ -54,78 +54,65 @@
5454
import java.util.stream.Collectors;
5555
import java.util.stream.Stream;
5656

57+
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.optionalConstructorArg;
58+
5759
public class GeoGridAggregationBuilder extends ValuesSourceAggregationBuilder<ValuesSource.GeoPoint, GeoGridAggregationBuilder>
58-
implements MultiBucketAggregationBuilder {
60+
implements MultiBucketAggregationBuilder {
5961
public static final String NAME = "geohash_grid";
6062
public static final int DEFAULT_MAX_NUM_CELLS = 10000;
6163

62-
private static final ObjectParser<GeoGridAggregationBuilder, Void> PARSER;
64+
private static final ConstructingObjectParser<GeoGridAggregationBuilder, String> PARSER;
65+
6366
static {
64-
PARSER = new ObjectParser<>(GeoGridAggregationBuilder.NAME);
65-
ValuesSourceParserHelper.declareGeoFields(PARSER, false, false);
66-
PARSER.declareString(GeoGridAggregationBuilder::type, GeoHashGridParams.FIELD_TYPE);
67-
PARSER.declareField(GeoGridAggregationBuilder::parsePrecision, GeoHashGridParams.FIELD_PRECISION, ObjectParser.ValueType.INT);
67+
PARSER = new ConstructingObjectParser<>(GeoGridAggregationBuilder.NAME, false,
68+
(a, name) -> new GeoGridAggregationBuilder(name, (String) a[0]));
69+
70+
PARSER.declareString(optionalConstructorArg(), GeoHashGridParams.FIELD_TYPE);
71+
PARSER.declareField(
72+
GeoGridAggregationBuilder::precisionRaw,
73+
GeoGridAggregationBuilder::parsePrecision,
74+
GeoHashGridParams.FIELD_PRECISION,
75+
ObjectParser.ValueType.VALUE);
6876
PARSER.declareInt(GeoGridAggregationBuilder::size, GeoHashGridParams.FIELD_SIZE);
6977
PARSER.declareInt(GeoGridAggregationBuilder::shardSize, GeoHashGridParams.FIELD_SHARD_SIZE);
78+
79+
ValuesSourceParserHelper.declareGeoFields(PARSER, false, false);
7080
}
7181

72-
private static void parsePrecision(XContentParser parser, GeoGridAggregationBuilder builder, Void context)
73-
throws IOException {
82+
private static Object parsePrecision(XContentParser parser, String name)
83+
throws IOException {
84+
// Delay actual parsing until builder.precision()
7485
// In some cases, this value cannot be fully parsed until after we know the type
75-
// Store precision as is until the end of parsing.
76-
// ValueType.INT could be either a number or a string
77-
builder.precisionLocation = parser.getTokenLocation();
78-
if (parser.currentToken() == XContentParser.Token.VALUE_NUMBER) {
79-
builder.precisionRaw = parser.intValue();
80-
} else {
81-
builder.precisionRaw = parser.text();
86+
final XContentParser.Token token = parser.currentToken();
87+
switch (token) {
88+
case VALUE_NUMBER:
89+
return parser.intValue();
90+
case VALUE_STRING:
91+
return parser.text();
92+
default:
93+
throw new XContentParseException(parser.getTokenLocation(),
94+
"[geohash_grid] failed to parse field [precision] in [" + name +
95+
"]. It must be either an integer or a string");
8296
}
8397
}
8498

85-
public static GeoGridAggregationBuilder parse(String aggregationName, XContentParser parser) throws IOException {
86-
GeoGridAggregationBuilder builder = PARSER.parse(parser,
87-
new GeoGridAggregationBuilder(aggregationName), null);
88-
89-
try {
90-
// delayed precision validation
91-
final GeoHashTypeProvider typeHandler = builder.type.getHandler();
92-
93-
if (builder.precisionRaw == null) {
94-
builder.precision(typeHandler.getDefaultPrecision());
95-
} else if (builder.precisionRaw instanceof String) {
96-
builder.precision(typeHandler.parsePrecisionString((String) builder.precisionRaw));
97-
} else {
98-
builder.precision((int) builder.precisionRaw);
99-
}
100-
101-
return builder;
102-
} catch (Exception e) {
103-
throw new XContentParseException(builder.precisionLocation,
104-
"[geohash_grid] failed to parse field [precision]", e);
105-
}
99+
public static GeoGridAggregationBuilder parse(String aggregationName, XContentParser parser) {
100+
return PARSER.apply(parser, aggregationName);
106101
}
107102

108-
private GeoHashType type = GeoHashType.DEFAULT;
109-
110-
/**
111-
* Contains unparsed precision value during the parsing.
112-
* This value will be converted into an integer precision at the end of parsing.
113-
*/
114-
private Object precisionRaw = null;
115-
116-
/**
117-
* Stores the location of the precision parameter, in case precision is
118-
* incorrect and an error has to be reported to the user. Only valid during parsing.
119-
*/
120-
private XContentLocation precisionLocation = null;
121-
122-
private int precision = GeoHashType.DEFAULT.getHandler().getDefaultPrecision();
123-
103+
private final GeoHashType type;
104+
private int precision;
124105
private int requiredSize = DEFAULT_MAX_NUM_CELLS;
125106
private int shardSize = -1;
126107

127-
public GeoGridAggregationBuilder(String name) {
108+
public GeoGridAggregationBuilder(String name, String type) {
109+
this(name, parseType(type, name));
110+
}
111+
112+
public GeoGridAggregationBuilder(String name, GeoHashType type) {
128113
super(name, ValuesSourceType.GEOPOINT, ValueType.GEOPOINT);
114+
this.type = type;
115+
this.precision = type.getHandler().getDefaultPrecision();
129116
}
130117

131118
protected GeoGridAggregationBuilder(GeoGridAggregationBuilder clone, Builder factoriesBuilder, Map<String, Object> metaData) {
@@ -160,9 +147,9 @@ protected void innerWriteTo(StreamOutput out) throws IOException {
160147
out.writeVInt(shardSize);
161148
}
162149

163-
public GeoGridAggregationBuilder type(String type) {
150+
private static GeoHashType parseType(String type, String name) {
164151
try {
165-
this.type = GeoHashType.forString(type);
152+
return type == null ? GeoHashType.DEFAULT : GeoHashType.forString(type);
166153
} catch (IllegalArgumentException e) {
167154
throw new IllegalArgumentException(
168155
"[type] is not valid. Allowed values: " +
@@ -171,16 +158,25 @@ public GeoGridAggregationBuilder type(String type) {
171158
.collect(Collectors.joining(", ")) +
172159
". Found [" + type + "] in [" + name + "]");
173160
}
174-
// Some tests bypass parsing steps, so keep the default precision consistent.
175-
// Note that tests must set precision after setting the type
176-
this.precision = this.type.getHandler().getDefaultPrecision();
177-
return this;
178161
}
179162

180163
public GeoHashType type() {
181164
return type;
182165
}
183166

167+
private GeoGridAggregationBuilder precisionRaw(Object precision) {
168+
final GeoHashTypeProvider typeHandler = this.type.getHandler();
169+
170+
if (precision == null) {
171+
this.precision(typeHandler.getDefaultPrecision());
172+
} else if (precision instanceof String) {
173+
this.precision(typeHandler.parsePrecisionString((String) precision));
174+
} else {
175+
this.precision((int) precision);
176+
}
177+
return this;
178+
}
179+
184180
public GeoGridAggregationBuilder precision(int precision) {
185181
this.precision = type.getHandler().validatePrecision(precision);
186182
return this;
@@ -193,7 +189,7 @@ public int precision() {
193189
public GeoGridAggregationBuilder size(int size) {
194190
if (size <= 0) {
195191
throw new IllegalArgumentException(
196-
"[size] must be greater than 0. Found [" + size + "] in [" + name + "]");
192+
"[size] must be greater than 0. Found [" + size + "] in [" + name + "]");
197193
}
198194
this.requiredSize = size;
199195
return this;
@@ -206,7 +202,7 @@ public int size() {
206202
public GeoGridAggregationBuilder shardSize(int shardSize) {
207203
if (shardSize <= 0) {
208204
throw new IllegalArgumentException(
209-
"[shardSize] must be greater than 0. Found [" + shardSize + "] in [" + name + "]");
205+
"[shardSize] must be greater than 0. Found [" + shardSize + "] in [" + name + "]");
210206
}
211207
this.shardSize = shardSize;
212208
return this;
@@ -218,8 +214,8 @@ public int shardSize() {
218214

219215
@Override
220216
protected ValuesSourceAggregatorFactory<ValuesSource.GeoPoint, ?> innerBuild(SearchContext context,
221-
ValuesSourceConfig<ValuesSource.GeoPoint> config, AggregatorFactory<?> parent, Builder subFactoriesBuilder)
222-
throws IOException {
217+
ValuesSourceConfig<ValuesSource.GeoPoint> config, AggregatorFactory<?> parent, Builder subFactoriesBuilder)
218+
throws IOException {
223219
int shardSize = this.shardSize;
224220

225221
int requiredSize = this.requiredSize;
@@ -232,14 +228,14 @@ public int shardSize() {
232228

233229
if (requiredSize <= 0 || shardSize <= 0) {
234230
throw new ElasticsearchException(
235-
"parameters [required_size] and [shard_size] must be >0 in geohash_grid aggregation [" + name + "].");
231+
"parameters [required_size] and [shard_size] must be >0 in geohash_grid aggregation [" + name + "].");
236232
}
237233

238234
if (shardSize < requiredSize) {
239235
shardSize = requiredSize;
240236
}
241237
return new GeoHashGridAggregatorFactory(name, config, type, precision, requiredSize, shardSize, context, parent,
242-
subFactoriesBuilder, metaData);
238+
subFactoriesBuilder, metaData);
243239
}
244240

245241
@Override

server/src/main/java/org/elasticsearch/search/aggregations/bucket/geogrid/GeoHashHandler.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
import org.elasticsearch.common.geo.GeoPoint;
2424
import org.elasticsearch.common.geo.GeoUtils;
2525

26+
/**
27+
* A simple wrapper for GeoUtils handling of the geohash hashing algorithm
28+
*/
2629
public class GeoHashHandler implements GeoHashTypeProvider {
2730
@Override
2831
public int getDefaultPrecision() {
@@ -50,7 +53,7 @@ public String hashAsString(long hash) {
5053
}
5154

5255
@Override
53-
public GeoPoint hashAsObject(long hash) {
56+
public GeoPoint hashAsGeoPoint(long hash) {
5457
return GeoPoint.fromGeohash(hash);
5558
}
5659
}

server/src/main/java/org/elasticsearch/search/aggregations/bucket/geogrid/GeoHashType.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public void writeTo(StreamOutput out) throws IOException {
6868
if (out.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) {
6969
out.writeEnum(this);
7070
} else if (this != DEFAULT) {
71-
throw new UnsupportedOperationException("Geo aggregation type [" + this +
71+
throw new UnsupportedOperationException("Geo aggregation type [" + toString() +
7272
"] is not supported by the node version " + out.getVersion().toString());
7373
}
7474
}

server/src/main/java/org/elasticsearch/search/aggregations/bucket/geogrid/GeoHashTypeProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,5 +60,5 @@ public interface GeoHashTypeProvider {
6060
* @param hash as generated by the {@link #calculateHash}
6161
* @return center of the grid cell
6262
*/
63-
GeoPoint hashAsObject(long hash);
63+
GeoPoint hashAsGeoPoint(long hash);
6464
}

server/src/main/java/org/elasticsearch/search/aggregations/bucket/geogrid/InternalGeoHashGrid.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
package org.elasticsearch.search.aggregations.bucket.geogrid;
2020

2121
import org.apache.lucene.util.PriorityQueue;
22-
import org.elasticsearch.common.geo.GeoHashUtils;
2322
import org.elasticsearch.common.geo.GeoPoint;
2423
import org.elasticsearch.common.io.stream.StreamInput;
2524
import org.elasticsearch.common.io.stream.StreamOutput;
@@ -86,8 +85,7 @@ public String getKeyAsString() {
8685

8786
@Override
8887
public GeoPoint getKey() {
89-
// TODO/FIXME: is it ok to change from GeoPoint to Object, and return different types?
90-
return type.getHandler().hashAsObject(geohashAsLong);
88+
return type.getHandler().hashAsGeoPoint(geohashAsLong);
9189
}
9290

9391
@Override

server/src/test/java/org/elasticsearch/search/aggregations/bucket/GeoHashGridTests.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,8 @@ public static int maxPrecision(GeoHashType type) {
5959
@Override
6060
protected GeoGridAggregationBuilder createTestAggregatorBuilder() {
6161
String name = randomAlphaOfLengthBetween(3, 20);
62-
GeoGridAggregationBuilder factory = new GeoGridAggregationBuilder(name);
63-
if (randomBoolean()) {
64-
factory.type(randomType().toString());
65-
}
62+
String type = randomBoolean() ? randomType().toString() : null;
63+
GeoGridAggregationBuilder factory = new GeoGridAggregationBuilder(name, type);
6664
if (randomBoolean()) {
6765
factory.precision(randomPrecision(factory.type()));
6866
}

server/src/test/java/org/elasticsearch/search/aggregations/bucket/geogrid/GeoHashGridAggregatorTests.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,7 @@ private void testCase(Query query, String field, GeoHashType type, int precision
116116
IndexReader indexReader = DirectoryReader.open(directory);
117117
IndexSearcher indexSearcher = newSearcher(indexReader, true, true);
118118

119-
GeoGridAggregationBuilder aggregationBuilder = new GeoGridAggregationBuilder("_name").field(field);
120-
aggregationBuilder.type(type.name());
119+
GeoGridAggregationBuilder aggregationBuilder = new GeoGridAggregationBuilder("_name", type).field(field);
121120
aggregationBuilder.precision(precision);
122121
MappedFieldType fieldType = new GeoPointFieldMapper.GeoPointFieldType();
123122
fieldType.setHasDocValues(true);

0 commit comments

Comments
 (0)