Geo: Fixes BoundingBox across complete longitudinal range

Adds a special case to the GeoBoundingBoxFilterParser so that the left of the box is not normalised in the case where left and right are 360 apart.  Before this change the left would be normalised to 180 in this case and the filter would only match points with a longitude of 180 (or -180).

Closes #5128
This commit is contained in:
Colin Goodheart-Smithe 2014-08-19 17:11:52 +01:00
parent da963ee1f7
commit f8d75faaad
2 changed files with 85 additions and 3 deletions

View File

@ -155,10 +155,17 @@ public class GeoBoundingBoxFilterParser implements FilterParser {
final GeoPoint topLeft = sparse.reset(top, left); //just keep the object
final GeoPoint bottomRight = new GeoPoint(bottom, right);
if (normalize) {
GeoUtils.normalizePoint(topLeft);
GeoUtils.normalizePoint(bottomRight);
// Special case: if the difference bettween the left and right is 360 and the right is greater than the left, we are asking for
// the complete longitude range so need to set longitude to the complete longditude range
boolean completeLonRange = ((right - left) % 360 == 0 && right > left);
GeoUtils.normalizePoint(topLeft, true, !completeLonRange);
GeoUtils.normalizePoint(bottomRight, true, !completeLonRange);
if (completeLonRange) {
topLeft.resetLon(-180);
bottomRight.resetLon(180);
}
}
MapperService.SmartNameFieldMappers smartMappers = parseContext.smartFieldMappers(fieldName);

View File

@ -261,5 +261,80 @@ public class GeoBoundingBoxTests extends ElasticsearchIntegrationTest {
).execute().actionGet();
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
}
@Test
public void completeLonRangeTest() throws Exception {
XContentBuilder xContentBuilder = XContentFactory.jsonBuilder().startObject().startObject("type1")
.startObject("properties").startObject("location").field("type", "geo_point").field("lat_lon", true).endObject().endObject()
.endObject().endObject();
assertAcked(prepareCreate("test").addMapping("type1", xContentBuilder));
ensureGreen();
client().prepareIndex("test", "type1", "1").setSource(jsonBuilder().startObject()
.field("userid", 880)
.field("title", "Place in Stockholm")
.startObject("location").field("lat", 59.328355000000002).field("lon", 18.036842).endObject()
.endObject())
.setRefresh(true)
.execute().actionGet();
client().prepareIndex("test", "type1", "2").setSource(jsonBuilder().startObject()
.field("userid", 534)
.field("title", "Place in Montreal")
.startObject("location").field("lat", 45.509526999999999).field("lon", -73.570986000000005).endObject()
.endObject())
.setRefresh(true)
.execute().actionGet();
SearchResponse searchResponse = client().prepareSearch()
.setQuery(
filteredQuery(matchAllQuery(),
geoBoundingBoxFilter("location").topLeft(50, -180).bottomRight(-50, 180))
).execute().actionGet();
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
searchResponse = client().prepareSearch()
.setQuery(
filteredQuery(matchAllQuery(),
geoBoundingBoxFilter("location").topLeft(50, -180).bottomRight(-50, 180).type("indexed"))
).execute().actionGet();
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
searchResponse = client().prepareSearch()
.setQuery(
filteredQuery(matchAllQuery(),
geoBoundingBoxFilter("location").topLeft(90, -180).bottomRight(-90, 180))
).execute().actionGet();
assertThat(searchResponse.getHits().totalHits(), equalTo(2l));
searchResponse = client().prepareSearch()
.setQuery(
filteredQuery(matchAllQuery(),
geoBoundingBoxFilter("location").topLeft(90, -180).bottomRight(-90, 180).type("indexed"))
).execute().actionGet();
assertThat(searchResponse.getHits().totalHits(), equalTo(2l));
searchResponse = client().prepareSearch()
.setQuery(
filteredQuery(matchAllQuery(),
geoBoundingBoxFilter("location").topLeft(50, 0).bottomRight(-50, 360))
).execute().actionGet();
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
searchResponse = client().prepareSearch()
.setQuery(
filteredQuery(matchAllQuery(),
geoBoundingBoxFilter("location").topLeft(50, 0).bottomRight(-50, 360).type("indexed"))
).execute().actionGet();
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
searchResponse = client().prepareSearch()
.setQuery(
filteredQuery(matchAllQuery(),
geoBoundingBoxFilter("location").topLeft(90, 0).bottomRight(-90, 360))
).execute().actionGet();
assertThat(searchResponse.getHits().totalHits(), equalTo(2l));
searchResponse = client().prepareSearch()
.setQuery(
filteredQuery(matchAllQuery(),
geoBoundingBoxFilter("location").topLeft(90, 0).bottomRight(-90, 360).type("indexed"))
).execute().actionGet();
assertThat(searchResponse.getHits().totalHits(), equalTo(2l));
}
}