Geo: bounding box filter, closes #290.

This commit is contained in:
kimchy 2010-08-03 01:51:46 +03:00
parent d1e404c1b3
commit de8ffaf5fb
12 changed files with 645 additions and 4 deletions

View File

@ -0,0 +1,140 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.common.lucene.geo;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.DocIdSet;
import org.apache.lucene.search.Filter;
import org.elasticsearch.common.lucene.docset.GetDocSet;
import org.elasticsearch.index.cache.field.data.FieldDataCache;
import org.elasticsearch.index.field.data.FieldData;
import org.elasticsearch.index.field.data.NumericFieldData;
import java.io.IOException;
/**
* @author kimchy (shay.banon)
*/
public class GeoBoundingBoxFilter extends Filter {
private final Point topLeft;
private final Point bottomRight;
private final String latFieldName;
private final String lonFieldName;
private final FieldData.Type fieldDataType;
private final FieldDataCache fieldDataCache;
public GeoBoundingBoxFilter(Point topLeft, Point bottomRight, String latFieldName, String lonFieldName, FieldData.Type fieldDataType, FieldDataCache fieldDataCache) {
this.topLeft = topLeft;
this.bottomRight = bottomRight;
this.latFieldName = latFieldName;
this.lonFieldName = lonFieldName;
this.fieldDataType = fieldDataType;
this.fieldDataCache = fieldDataCache;
}
public Point topLeft() {
return topLeft;
}
public Point bottomRight() {
return bottomRight;
}
public String latFieldName() {
return latFieldName;
}
public String lonFieldName() {
return lonFieldName;
}
@Override public DocIdSet getDocIdSet(IndexReader reader) throws IOException {
final NumericFieldData latFieldData = (NumericFieldData) fieldDataCache.cache(fieldDataType, reader, latFieldName);
final NumericFieldData lonFieldData = (NumericFieldData) fieldDataCache.cache(fieldDataType, reader, lonFieldName);
if (topLeft.lon > bottomRight.lon) {
return new GetDocSet(reader.maxDoc()) {
@Override public boolean get(int doc) throws IOException {
if (!latFieldData.hasValue(doc) || !lonFieldData.hasValue(doc)) {
return false;
}
if (latFieldData.multiValued()) {
double[] lats = latFieldData.doubleValues(doc);
double[] lons = latFieldData.doubleValues(doc);
for (int i = 0; i < lats.length; i++) {
if (topLeft.lon >= lons[i] && bottomRight.lon <= lons[i]
&& topLeft.lat >= lats[i] && bottomRight.lat <= lats[i]) {
return true;
}
}
} else {
double lat = latFieldData.doubleValue(doc);
double lon = lonFieldData.doubleValue(doc);
if (topLeft.lon >= lon && bottomRight.lon <= lon
&& topLeft.lat >= lat && bottomRight.lat <= lat) {
return true;
}
}
return false;
}
};
} else {
return new GetDocSet(reader.maxDoc()) {
@Override public boolean get(int doc) throws IOException {
if (!latFieldData.hasValue(doc) || !lonFieldData.hasValue(doc)) {
return false;
}
if (latFieldData.multiValued()) {
double[] lats = latFieldData.doubleValues(doc);
double[] lons = latFieldData.doubleValues(doc);
for (int i = 0; i < lats.length; i++) {
if (topLeft.lon <= lons[i] && bottomRight.lon >= lons[i]
&& topLeft.lat >= lats[i] && bottomRight.lat <= lats[i]) {
return true;
}
}
} else {
double lat = latFieldData.doubleValue(doc);
double lon = lonFieldData.doubleValue(doc);
if (topLeft.lon <= lon && bottomRight.lon >= lon
&& topLeft.lat >= lat && bottomRight.lat <= lat) {
return true;
}
}
return false;
}
};
}
}
public static class Point {
public double lat;
public double lon;
}
}

View File

@ -179,10 +179,14 @@ public abstract class FilterBuilders {
return new ScriptFilterBuilder(script);
}
public static GeoDistanceFilterBuilder geoDistance(String name) {
public static GeoDistanceFilterBuilder geoDistanceFilter(String name) {
return new GeoDistanceFilterBuilder(name);
}
public static GeoBoundingBoxFilterBuilder geoBoundingBoxFilter(String name) {
return new GeoBoundingBoxFilterBuilder(name);
}
public static BoolFilterBuilder boolFilter() {
return new BoolFilterBuilder();
}

View File

@ -0,0 +1,93 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.index.query.xcontent;
import org.elasticsearch.common.lucene.geo.GeoBoundingBoxFilter;
import org.elasticsearch.common.xcontent.builder.XContentBuilder;
import org.elasticsearch.index.query.QueryBuilderException;
import java.io.IOException;
/**
* @author kimchy (shay.banon)
*/
public class GeoBoundingBoxFilterBuilder extends BaseFilterBuilder {
private final String name;
private GeoBoundingBoxFilter.Point topLeft;
private String topLeftGeohash;
private GeoBoundingBoxFilter.Point bottomRight;
private String bottomRightGeohash;
public GeoBoundingBoxFilterBuilder(String name) {
this.name = name;
}
public GeoBoundingBoxFilterBuilder topLeft(double lat, double lon) {
topLeft = new GeoBoundingBoxFilter.Point();
topLeft.lat = lat;
topLeft.lon = lon;
return this;
}
public GeoBoundingBoxFilterBuilder bottomRight(double lat, double lon) {
bottomRight = new GeoBoundingBoxFilter.Point();
bottomRight.lat = lat;
bottomRight.lon = lon;
return this;
}
public GeoBoundingBoxFilterBuilder topLeft(String geohash) {
this.topLeftGeohash = geohash;
return this;
}
public GeoBoundingBoxFilterBuilder bottomRight(String geohash) {
this.bottomRightGeohash = geohash;
return this;
}
@Override protected void doXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject(GeoBoundingBoxFilterParser.NAME);
builder.field("field", name);
if (topLeftGeohash != null) {
builder.field("top_left", topLeftGeohash);
} else if (topLeft != null) {
builder.startArray("top_left").value(topLeft.lat).value(topLeft.lon).endArray();
} else {
throw new QueryBuilderException("geo_bounding_box requires 'top_left' to be set");
}
if (bottomRightGeohash != null) {
builder.field("bottom_right", bottomRightGeohash);
} else if (bottomRight != null) {
builder.startArray("bottom_right").value(bottomRight.lat).value(bottomRight.lon).endArray();
} else {
throw new QueryBuilderException("geo_bounding_box requires 'bottom_right' to be set");
}
builder.endObject();
}
}

View File

@ -0,0 +1,153 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.index.query.xcontent;
import org.apache.lucene.search.Filter;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.lucene.geo.GeoBoundingBoxFilter;
import org.elasticsearch.common.lucene.geo.GeoHashUtils;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.AbstractIndexComponent;
import org.elasticsearch.index.Index;
import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.mapper.xcontent.XContentGeoPointFieldMapper;
import org.elasticsearch.index.query.QueryParsingException;
import org.elasticsearch.index.settings.IndexSettings;
import java.io.IOException;
/**
* @author kimchy (shay.banon)
*/
public class GeoBoundingBoxFilterParser extends AbstractIndexComponent implements XContentFilterParser {
public static final String NAME = "geo_bounding_box";
@Inject public GeoBoundingBoxFilterParser(Index index, @IndexSettings Settings indexSettings) {
super(index, indexSettings);
}
@Override public String[] names() {
return new String[]{NAME, "geoBoundingBox"};
}
@Override public Filter parse(QueryParseContext parseContext) throws IOException, QueryParsingException {
XContentParser parser = parseContext.parser();
GeoBoundingBoxFilter.Point topLeft = new GeoBoundingBoxFilter.Point();
GeoBoundingBoxFilter.Point bottomRight = new GeoBoundingBoxFilter.Point();
String latFieldName = null;
String lonFieldName = null;
String currentFieldName = null;
XContentParser.Token token;
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
currentFieldName = parser.currentName();
} else if (token == XContentParser.Token.START_ARRAY) {
GeoBoundingBoxFilter.Point point = null;
if ("top_left".equals(currentFieldName) || "topLeft".equals(currentFieldName)) {
point = topLeft;
} else if ("bottom_right".equals(currentFieldName) || "bottomRight".equals(currentFieldName)) {
point = bottomRight;
}
if (point != null) {
token = parser.nextToken();
point.lat = parser.doubleValue();
token = parser.nextToken();
point.lon = parser.doubleValue();
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
}
}
} else if (token == XContentParser.Token.START_OBJECT) {
GeoBoundingBoxFilter.Point point = null;
if ("top_left".equals(currentFieldName) || "topLeft".equals(currentFieldName)) {
point = topLeft;
} else if ("bottom_right".equals(currentFieldName) || "bottomRight".equals(currentFieldName)) {
point = bottomRight;
}
if (point != null) {
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
currentFieldName = parser.currentName();
} else if (token.isValue()) {
if (currentFieldName.equals(XContentGeoPointFieldMapper.Names.LAT)) {
point.lat = parser.doubleValue();
} else if (currentFieldName.equals(XContentGeoPointFieldMapper.Names.LON)) {
point.lon = parser.doubleValue();
} else if (currentFieldName.equals(XContentGeoPointFieldMapper.Names.GEOHASH)) {
double[] values = GeoHashUtils.decode(parser.text());
point.lat = values[0];
point.lon = values[1];
}
}
}
}
} else if (token.isValue()) {
if ("field".equals(currentFieldName)) {
latFieldName = parser.text() + XContentGeoPointFieldMapper.Names.LAT_SUFFIX;
lonFieldName = parser.text() + XContentGeoPointFieldMapper.Names.LON_SUFFIX;
} else {
GeoBoundingBoxFilter.Point point = null;
if ("top_left".equals(currentFieldName) || "topLeft".equals(currentFieldName)) {
point = topLeft;
} else if ("bottom_right".equals(currentFieldName) || "bottomRight".equals(currentFieldName)) {
point = bottomRight;
}
if (point != null) {
String value = parser.text();
int comma = value.indexOf(',');
if (comma != -1) {
point.lat = Double.parseDouble(value.substring(0, comma).trim());
point.lon = Double.parseDouble(value.substring(comma + 1).trim());
} else {
double[] values = GeoHashUtils.decode(value);
point.lat = values[0];
point.lon = values[1];
}
}
}
}
}
MapperService mapperService = parseContext.mapperService();
FieldMapper mapper = mapperService.smartNameFieldMapper(latFieldName);
if (mapper == null) {
throw new QueryParsingException(index, "failed to find lat field [" + latFieldName + "]");
}
latFieldName = mapper.names().indexName();
mapper = mapperService.smartNameFieldMapper(lonFieldName);
if (mapper == null) {
throw new QueryParsingException(index, "failed to find lon field [" + lonFieldName + "]");
}
lonFieldName = mapper.names().indexName();
return new GeoBoundingBoxFilter(topLeft, bottomRight, latFieldName, lonFieldName, mapper.fieldDataType(), parseContext.indexCache().fieldData());
}
}

View File

@ -87,6 +87,7 @@ public class XContentQueryParserRegistry {
add(filterParsersMap, new PrefixFilterParser(index, indexSettings));
add(filterParsersMap, new ScriptFilterParser(index, indexSettings));
add(filterParsersMap, new GeoDistanceFilterParser(index, indexSettings));
add(filterParsersMap, new GeoBoundingBoxFilterParser(index, indexSettings));
add(filterParsersMap, new QueryFilterParser(index, indexSettings));
add(filterParsersMap, new BoolFilterParser(index, indexSettings));
add(filterParsersMap, new AndFilterParser(index, indexSettings));

View File

@ -23,6 +23,7 @@ import org.apache.lucene.index.Term;
import org.apache.lucene.search.*;
import org.apache.lucene.search.spans.*;
import org.apache.lucene.util.NumericUtils;
import org.elasticsearch.common.lucene.geo.GeoBoundingBoxFilter;
import org.elasticsearch.common.lucene.geo.GeoDistanceFilter;
import org.elasticsearch.common.lucene.search.*;
import org.elasticsearch.common.lucene.search.function.BoostScoreFunction;
@ -1013,6 +1014,66 @@ public class SimpleIndexQueryParserTests {
assertThat(filter.distance(), closeTo(12, 0.00001));
}
@Test public void testGeoBoundingBoxFilter1() throws IOException {
IndexQueryParser queryParser = newQueryParser();
String query = copyToStringFromClasspath("/org/elasticsearch/index/query/xcontent/geo_boundingbox1.json");
Query parsedQuery = queryParser.parse(query);
assertThat(parsedQuery, instanceOf(FilteredQuery.class));
FilteredQuery filteredQuery = (FilteredQuery) parsedQuery;
GeoBoundingBoxFilter filter = (GeoBoundingBoxFilter) filteredQuery.getFilter();
assertThat(filter.latFieldName(), equalTo("location.lat"));
assertThat(filter.lonFieldName(), equalTo("location.lon"));
assertThat(filter.topLeft().lat, closeTo(40, 0.00001));
assertThat(filter.topLeft().lon, closeTo(-70, 0.00001));
assertThat(filter.bottomRight().lat, closeTo(30, 0.00001));
assertThat(filter.bottomRight().lon, closeTo(-80, 0.00001));
}
@Test public void testGeoBoundingBoxFilter2() throws IOException {
IndexQueryParser queryParser = newQueryParser();
String query = copyToStringFromClasspath("/org/elasticsearch/index/query/xcontent/geo_boundingbox2.json");
Query parsedQuery = queryParser.parse(query);
assertThat(parsedQuery, instanceOf(FilteredQuery.class));
FilteredQuery filteredQuery = (FilteredQuery) parsedQuery;
GeoBoundingBoxFilter filter = (GeoBoundingBoxFilter) filteredQuery.getFilter();
assertThat(filter.latFieldName(), equalTo("location.lat"));
assertThat(filter.lonFieldName(), equalTo("location.lon"));
assertThat(filter.topLeft().lat, closeTo(40, 0.00001));
assertThat(filter.topLeft().lon, closeTo(-70, 0.00001));
assertThat(filter.bottomRight().lat, closeTo(30, 0.00001));
assertThat(filter.bottomRight().lon, closeTo(-80, 0.00001));
}
@Test public void testGeoBoundingBoxFilter3() throws IOException {
IndexQueryParser queryParser = newQueryParser();
String query = copyToStringFromClasspath("/org/elasticsearch/index/query/xcontent/geo_boundingbox3.json");
Query parsedQuery = queryParser.parse(query);
assertThat(parsedQuery, instanceOf(FilteredQuery.class));
FilteredQuery filteredQuery = (FilteredQuery) parsedQuery;
GeoBoundingBoxFilter filter = (GeoBoundingBoxFilter) filteredQuery.getFilter();
assertThat(filter.latFieldName(), equalTo("location.lat"));
assertThat(filter.lonFieldName(), equalTo("location.lon"));
assertThat(filter.topLeft().lat, closeTo(40, 0.00001));
assertThat(filter.topLeft().lon, closeTo(-70, 0.00001));
assertThat(filter.bottomRight().lat, closeTo(30, 0.00001));
assertThat(filter.bottomRight().lon, closeTo(-80, 0.00001));
}
@Test public void testGeoBoundingBoxFilter4() throws IOException {
IndexQueryParser queryParser = newQueryParser();
String query = copyToStringFromClasspath("/org/elasticsearch/index/query/xcontent/geo_boundingbox4.json");
Query parsedQuery = queryParser.parse(query);
assertThat(parsedQuery, instanceOf(FilteredQuery.class));
FilteredQuery filteredQuery = (FilteredQuery) parsedQuery;
GeoBoundingBoxFilter filter = (GeoBoundingBoxFilter) filteredQuery.getFilter();
assertThat(filter.latFieldName(), equalTo("location.lat"));
assertThat(filter.lonFieldName(), equalTo("location.lon"));
assertThat(filter.topLeft().lat, closeTo(40, 0.00001));
assertThat(filter.topLeft().lon, closeTo(-70, 0.00001));
assertThat(filter.bottomRight().lat, closeTo(30, 0.00001));
assertThat(filter.bottomRight().lon, closeTo(-80, 0.00001));
}
private XContentIndexQueryParser newQueryParser() throws IOException {
return new XContentIndexQueryParser(new Index("test"), EMPTY_SETTINGS, new ScriptService(EMPTY_SETTINGS),
newMapperService(), new IndexCache(index), new RobinIndexEngine(index), new AnalysisService(index), null, null, null, "test", null);

View File

@ -0,0 +1,14 @@
{
"filtered" : {
"query" : {
"match_all" : {}
},
"filter" : {
"geo_bounding_box" : {
"field" : "person.location",
"top_left" : [40, -70],
"bottom_right" : [30, -80]
}
}
}
}

View File

@ -0,0 +1,20 @@
{
"filtered" : {
"query" : {
"match_all" : {}
},
"filter" : {
"geo_bounding_box" : {
"field" : "person.location",
"top_left" : {
"lat" : 40,
"lon" : -70
},
"bottom_right" : {
"lat" : 30,
"lon" : -80
}
}
}
}
}

View File

@ -0,0 +1,14 @@
{
"filtered" : {
"query" : {
"match_all" : {}
},
"filter" : {
"geo_bounding_box" : {
"field" : "person.location",
"top_left" : "40, -70",
"bottom_right" : "30, -80"
}
}
}
}

View File

@ -0,0 +1,14 @@
{
"filtered" : {
"query" : {
"match_all" : {}
},
"filter" : {
"geo_bounding_box" : {
"field" : "person.location",
"top_left" : "drn5x1g8cu2y",
"bottom_right" : "30, -80"
}
}
}
}

View File

@ -0,0 +1,121 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.test.integration.search.geo;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.test.integration.AbstractNodesTests;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import static org.elasticsearch.common.xcontent.XContentFactory.*;
import static org.elasticsearch.index.query.xcontent.FilterBuilders.*;
import static org.elasticsearch.index.query.xcontent.QueryBuilders.*;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
/**
* @author kimchy (shay.banon)
*/
public class GeoBoundingBoxTests extends AbstractNodesTests {
private Client client;
@BeforeClass public void createNodes() throws Exception {
startNode("server1");
startNode("server2");
client = getClient();
}
@AfterClass public void closeNodes() {
client.close();
closeAllNodes();
}
protected Client getClient() {
return client("server1");
}
@Test public void simpleBoundingBoxTest() throws Exception {
try {
client.admin().indices().prepareDelete("test").execute().actionGet();
} catch (Exception e) {
// ignore
}
client.admin().indices().prepareCreate("test").execute().actionGet();
client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet();
client.prepareIndex("test", "type1", "1").setSource(jsonBuilder().startObject()
.field("name", "New York")
.startObject("location").field("lat", 40.7143528).field("lon", -74.0059731).endObject()
.endObject()).execute().actionGet();
// to NY: 5.286 km
client.prepareIndex("test", "type1", "2").setSource(jsonBuilder().startObject()
.field("name", "Times Square")
.startObject("location").field("lat", 40.759011).field("lon", -73.9844722).endObject()
.endObject()).execute().actionGet();
// to NY: 0.4621 km
client.prepareIndex("test", "type1", "3").setSource(jsonBuilder().startObject()
.field("name", "Tribeca")
.startObject("location").field("lat", 40.718266).field("lon", -74.007819).endObject()
.endObject()).execute().actionGet();
// to NY: 1.055 km
client.prepareIndex("test", "type1", "4").setSource(jsonBuilder().startObject()
.field("name", "Wall Street")
.startObject("location").field("lat", 40.7051157).field("lon", -74.0088305).endObject()
.endObject()).execute().actionGet();
// to NY: 1.258 km
client.prepareIndex("test", "type1", "5").setSource(jsonBuilder().startObject()
.field("name", "Soho")
.startObject("location").field("lat", 40.7247222).field("lon", -74).endObject()
.endObject()).execute().actionGet();
// to NY: 2.029 km
client.prepareIndex("test", "type1", "6").setSource(jsonBuilder().startObject()
.field("name", "Greenwich Village")
.startObject("location").field("lat", 40.731033).field("lon", -73.9962255).endObject()
.endObject()).execute().actionGet();
// to NY: 8.572 km
client.prepareIndex("test", "type1", "7").setSource(jsonBuilder().startObject()
.field("name", "Brooklyn")
.startObject("location").field("lat", 40.65).field("lon", -73.95).endObject()
.endObject()).execute().actionGet();
client.admin().indices().prepareRefresh().execute().actionGet();
SearchResponse searchResponse = client.prepareSearch() // from NY
.setQuery(filtered(matchAllQuery(), geoBoundingBoxFilter("location").topLeft(40.73, -74.1).bottomRight(40.717, -73.99)))
.execute().actionGet();
assertThat(searchResponse.hits().getTotalHits(), equalTo(2l));
assertThat(searchResponse.hits().hits().length, equalTo(2));
for (SearchHit hit : searchResponse.hits()) {
System.err.println("-->" + hit.id());
assertThat(hit.id(), anyOf(equalTo("1"), equalTo("3"), equalTo("5")));
}
}
}

View File

@ -108,22 +108,28 @@ public class GeoDistanceTests extends AbstractNodesTests {
client.admin().indices().prepareRefresh().execute().actionGet();
SearchResponse searchResponse = client.prepareSearch() // from NY
.setQuery(filtered(matchAllQuery(), geoDistance("location").distance("3km").point(40.7143528, -74.0059731)))
.setQuery(filtered(matchAllQuery(), geoDistanceFilter("location").distance("3km").point(40.7143528, -74.0059731)))
.execute().actionGet();
assertThat(searchResponse.hits().getTotalHits(), equalTo(5l));
assertThat(searchResponse.hits().hits().length, equalTo(5));
for (SearchHit hit : searchResponse.hits()) {
assertThat(hit.id(), anyOf(equalTo("1"), equalTo("3"), equalTo("4"), equalTo("5"), equalTo("6")));
}
searchResponse = client.prepareSearch() // from NY
.setQuery(filtered(matchAllQuery(), geoDistance("location").distance("2km").point(40.7143528, -74.0059731)))
.setQuery(filtered(matchAllQuery(), geoDistanceFilter("location").distance("2km").point(40.7143528, -74.0059731)))
.execute().actionGet();
assertThat(searchResponse.hits().getTotalHits(), equalTo(4l));
assertThat(searchResponse.hits().hits().length, equalTo(4));
for (SearchHit hit : searchResponse.hits()) {
assertThat(hit.id(), anyOf(equalTo("1"), equalTo("3"), equalTo("4"), equalTo("5")));
}
searchResponse = client.prepareSearch() // from NY
.setQuery(filtered(matchAllQuery(), geoDistance("location").distance("1.242mi").point(40.7143528, -74.0059731)))
.setQuery(filtered(matchAllQuery(), geoDistanceFilter("location").distance("1.242mi").point(40.7143528, -74.0059731)))
.execute().actionGet();
assertThat(searchResponse.hits().getTotalHits(), equalTo(4l));
assertThat(searchResponse.hits().hits().length, equalTo(4));
for (SearchHit hit : searchResponse.hits()) {
assertThat(hit.id(), anyOf(equalTo("1"), equalTo("3"), equalTo("4"), equalTo("5")));
}