Geo: better handling of malformed geo_points (#35554)

Improves handling of malformed geo_points when `ignore_malformed` is
set to true

Closes #35419
This commit is contained in:
Igor Motov 2018-11-26 09:44:42 -10:00 committed by GitHub
parent 900caa20ef
commit 663563f64b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 89 additions and 3 deletions

View File

@ -97,8 +97,18 @@ public final class GeoPoint implements ToXContentFragment {
throw new ElasticsearchParseException("failed to parse [{}], expected 2 or 3 coordinates "
+ "but found: [{}]", vals.length);
}
double lat = Double.parseDouble(vals[0].trim());
double lon = Double.parseDouble(vals[1].trim());
final double lat;
final double lon;
try {
lat = Double.parseDouble(vals[0].trim());
} catch (NumberFormatException ex) {
throw new ElasticsearchParseException("latitude must be a number");
}
try {
lon = Double.parseDouble(vals[1].trim());
} catch (NumberFormatException ex) {
throw new ElasticsearchParseException("longitude must be a number");
}
if (vals.length > 2) {
GeoPoint.assertZValue(ignoreZValue, Double.parseDouble(vals[2].trim()));
}

View File

@ -260,7 +260,11 @@ public class GeoPointFieldMapper extends FieldMapper implements ArrayValueMapper
throw new IllegalArgumentException("illegal longitude value [" + point.lon() + "] for " + name());
}
} else {
GeoUtils.normalizePoint(point);
if (isNormalizable(point.lat()) && isNormalizable(point.lon())) {
GeoUtils.normalizePoint(point);
} else {
throw new ElasticsearchParseException("cannot normalize the point - not a number");
}
}
if (fieldType().indexOptions() != IndexOptions.NONE) {
context.doc().add(new LatLonPoint(fieldType().name(), point.lat(), point.lon()));
@ -386,4 +390,8 @@ public class GeoPointFieldMapper extends FieldMapper implements ArrayValueMapper
public Explicit<Boolean> ignoreZValue() {
return ignoreZValue;
}
private boolean isNormalizable(double coord) {
return Double.isNaN(coord) == false && Double.isInfinite(coord) == false;
}
}

View File

@ -456,4 +456,72 @@ public class GeoPointFieldMapperTests extends ESSingleNodeTestCase {
assertThat(ex.getRootCause().getMessage(), equalTo("unsupported symbol [.] in geohash [1234.333]"));
}
public void testInvalidGeopointValuesIgnored() throws Exception {
String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type")
.startObject("properties")
.startObject("location")
.field("type", "geo_point")
.field("ignore_malformed", "true")
.endObject()
.endObject().endObject().endObject());
DocumentMapper defaultMapper = createIndex("test").mapperService().documentMapperParser()
.parse("type", new CompressedXContent(mapping));
assertThat(defaultMapper.parse(SourceToParse.source("test", "type", "1",
BytesReference.bytes(XContentFactory.jsonBuilder()
.startObject().field("location", "1234.333").endObject()
), XContentType.JSON)).rootDoc().getField("location"), nullValue());
assertThat(defaultMapper.parse(SourceToParse.source("test", "type", "1",
BytesReference.bytes(XContentFactory.jsonBuilder()
.startObject().field("lat", "-").field("lon", 1.3).endObject()
), XContentType.JSON)).rootDoc().getField("location"), nullValue());
assertThat(defaultMapper.parse(SourceToParse.source("test", "type", "1",
BytesReference.bytes(XContentFactory.jsonBuilder()
.startObject().field("lat", 1.3).field("lon", "-").endObject()
), XContentType.JSON)).rootDoc().getField("location"), nullValue());
assertThat(defaultMapper.parse(SourceToParse.source("test", "type", "1",
BytesReference.bytes(XContentFactory.jsonBuilder()
.startObject().field("location", "-,1.3").endObject()
), XContentType.JSON)).rootDoc().getField("location"), nullValue());
assertThat(defaultMapper.parse(SourceToParse.source("test", "type", "1",
BytesReference.bytes(XContentFactory.jsonBuilder()
.startObject().field("location", "1.3,-").endObject()
), XContentType.JSON)).rootDoc().getField("location"), nullValue());
assertThat(defaultMapper.parse(SourceToParse.source("test", "type", "1",
BytesReference.bytes(XContentFactory.jsonBuilder()
.startObject().field("lat", "NaN").field("lon", "NaN").endObject()
), XContentType.JSON)).rootDoc().getField("location"), nullValue());
assertThat(defaultMapper.parse(SourceToParse.source("test", "type", "1",
BytesReference.bytes(XContentFactory.jsonBuilder()
.startObject().field("lat", 12).field("lon", "NaN").endObject()
), XContentType.JSON)).rootDoc().getField("location"), nullValue());
assertThat(defaultMapper.parse(SourceToParse.source("test", "type", "1",
BytesReference.bytes(XContentFactory.jsonBuilder()
.startObject().field("lat", "NaN").field("lon", 10).endObject()
), XContentType.JSON)).rootDoc().getField("location"), nullValue());
assertThat(defaultMapper.parse(SourceToParse.source("test", "type", "1",
BytesReference.bytes(XContentFactory.jsonBuilder()
.startObject().field("location", "NaN,NaN").endObject()
), XContentType.JSON)).rootDoc().getField("location"), nullValue());
assertThat(defaultMapper.parse(SourceToParse.source("test", "type", "1",
BytesReference.bytes(XContentFactory.jsonBuilder()
.startObject().field("location", "10,NaN").endObject()
), XContentType.JSON)).rootDoc().getField("location"), nullValue());
assertThat(defaultMapper.parse(SourceToParse.source("test", "type", "1",
BytesReference.bytes(XContentFactory.jsonBuilder()
.startObject().field("location", "NaN,12").endObject()
), XContentType.JSON)).rootDoc().getField("location"), nullValue());
}
}