mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-02-26 23:07:45 +00:00
Don't assume fixed earth diameter in the geo-distance bounding box optimization.
We switched to Lucene's SloppyMath way of computing an approximate value of the eath diameter given a latitude in order to compute distances, yet the bounding box optimization of the geo distance filter still assumed a constant earth diameter, equal to the average. Close #6008
This commit is contained in:
parent
6feeac98c8
commit
c306d8c5f5
@ -140,7 +140,8 @@ public enum GeoDistance {
|
|||||||
|
|
||||||
public static DistanceBoundingCheck distanceBoundingCheck(double sourceLatitude, double sourceLongitude, double distance, DistanceUnit unit) {
|
public static DistanceBoundingCheck distanceBoundingCheck(double sourceLatitude, double sourceLongitude, double distance, DistanceUnit unit) {
|
||||||
// angular distance in radians on a great circle
|
// angular distance in radians on a great circle
|
||||||
double radDist = distance / unit.getEarthRadius();
|
// assume worst-case: use the minor axis
|
||||||
|
double radDist = unit.toMeters(distance) / GeoUtils.EARTH_SEMI_MINOR_AXIS;
|
||||||
|
|
||||||
double radLat = Math.toRadians(sourceLatitude);
|
double radLat = Math.toRadians(sourceLatitude);
|
||||||
double radLon = Math.toRadians(sourceLongitude);
|
double radLon = Math.toRadians(sourceLongitude);
|
||||||
|
@ -52,7 +52,7 @@ public class GeoDistanceFilter extends Filter {
|
|||||||
private final IndexGeoPointFieldData indexFieldData;
|
private final IndexGeoPointFieldData indexFieldData;
|
||||||
|
|
||||||
private final GeoDistance.FixedSourceDistance fixedSourceDistance;
|
private final GeoDistance.FixedSourceDistance fixedSourceDistance;
|
||||||
private GeoDistance.DistanceBoundingCheck distanceBoundingCheck;
|
private final GeoDistance.DistanceBoundingCheck distanceBoundingCheck;
|
||||||
private final Filter boundingBoxFilter;
|
private final Filter boundingBoxFilter;
|
||||||
|
|
||||||
public GeoDistanceFilter(double lat, double lon, double distance, GeoDistance geoDistance, IndexGeoPointFieldData indexFieldData, GeoPointFieldMapper mapper,
|
public GeoDistanceFilter(double lat, double lon, double distance, GeoDistance geoDistance, IndexGeoPointFieldData indexFieldData, GeoPointFieldMapper mapper,
|
||||||
@ -64,6 +64,7 @@ public class GeoDistanceFilter extends Filter {
|
|||||||
this.indexFieldData = indexFieldData;
|
this.indexFieldData = indexFieldData;
|
||||||
|
|
||||||
this.fixedSourceDistance = geoDistance.fixedSourceDistance(lat, lon, DistanceUnit.DEFAULT);
|
this.fixedSourceDistance = geoDistance.fixedSourceDistance(lat, lon, DistanceUnit.DEFAULT);
|
||||||
|
GeoDistance.DistanceBoundingCheck distanceBoundingCheck = null;
|
||||||
if (optimizeBbox != null && !"none".equals(optimizeBbox)) {
|
if (optimizeBbox != null && !"none".equals(optimizeBbox)) {
|
||||||
distanceBoundingCheck = GeoDistance.distanceBoundingCheck(lat, lon, distance, DistanceUnit.DEFAULT);
|
distanceBoundingCheck = GeoDistance.distanceBoundingCheck(lat, lon, distance, DistanceUnit.DEFAULT);
|
||||||
if ("memory".equals(optimizeBbox)) {
|
if ("memory".equals(optimizeBbox)) {
|
||||||
@ -78,6 +79,7 @@ public class GeoDistanceFilter extends Filter {
|
|||||||
distanceBoundingCheck = GeoDistance.ALWAYS_INSTANCE;
|
distanceBoundingCheck = GeoDistance.ALWAYS_INSTANCE;
|
||||||
boundingBoxFilter = null;
|
boundingBoxFilter = null;
|
||||||
}
|
}
|
||||||
|
this.distanceBoundingCheck = distanceBoundingCheck;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double lat() {
|
public double lat() {
|
||||||
|
@ -19,7 +19,9 @@
|
|||||||
|
|
||||||
package org.elasticsearch.search.geo;
|
package org.elasticsearch.search.geo;
|
||||||
|
|
||||||
|
import org.elasticsearch.action.index.IndexRequestBuilder;
|
||||||
import org.elasticsearch.action.search.SearchResponse;
|
import org.elasticsearch.action.search.SearchResponse;
|
||||||
|
import org.elasticsearch.action.search.SearchType;
|
||||||
import org.elasticsearch.common.geo.GeoDistance;
|
import org.elasticsearch.common.geo.GeoDistance;
|
||||||
import org.elasticsearch.common.geo.GeoHashUtils;
|
import org.elasticsearch.common.geo.GeoHashUtils;
|
||||||
import org.elasticsearch.common.unit.DistanceUnit;
|
import org.elasticsearch.common.unit.DistanceUnit;
|
||||||
@ -36,6 +38,9 @@ import org.elasticsearch.test.ElasticsearchIntegrationTest;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||||
import static org.elasticsearch.index.query.FilterBuilders.*;
|
import static org.elasticsearch.index.query.FilterBuilders.*;
|
||||||
@ -633,4 +638,44 @@ public class GeoDistanceTests extends ElasticsearchIntegrationTest {
|
|||||||
assertHitCount(result, 1);
|
assertHitCount(result, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private double randomLon() {
|
||||||
|
return randomDouble() * 360 - 180;
|
||||||
|
}
|
||||||
|
|
||||||
|
private double randomLat() {
|
||||||
|
return randomDouble() * 180 - 90;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDuelOptimizations() throws Exception {
|
||||||
|
assertAcked(prepareCreate("index").addMapping("type", "location", "type=geo_point,lat_lon=true"));
|
||||||
|
final int numDocs = scaledRandomIntBetween(3000, 10000);
|
||||||
|
List<IndexRequestBuilder> docs = new ArrayList<>();
|
||||||
|
for (int i = 0; i < numDocs; ++i) {
|
||||||
|
docs.add(client().prepareIndex("index", "type").setSource(jsonBuilder().startObject().startObject("location").field("lat", randomLat()).field("lon", randomLon()).endObject().endObject()));
|
||||||
|
}
|
||||||
|
indexRandom(true, docs);
|
||||||
|
ensureSearchable();
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; ++i) {
|
||||||
|
final double originLat = randomLat();
|
||||||
|
final double originLon = randomLon();
|
||||||
|
final String distance = DistanceUnit.KILOMETERS.toString(randomInt(10000));
|
||||||
|
for (GeoDistance geoDistance : Arrays.asList(GeoDistance.ARC, GeoDistance.SLOPPY_ARC)) {
|
||||||
|
logger.info("Now testing GeoDistance={}, distance={}, origin=({}, {})", geoDistance, distance, originLat, originLon);
|
||||||
|
long matches = -1;
|
||||||
|
for (String optimizeBbox : Arrays.asList("none", "memory", "indexed")) {
|
||||||
|
SearchResponse resp = client().prepareSearch("index").setSearchType(SearchType.COUNT).setQuery(QueryBuilders.constantScoreQuery(
|
||||||
|
FilterBuilders.geoDistanceFilter("location").point(originLat, originLon).distance(distance).geoDistance(geoDistance).optimizeBbox(optimizeBbox))).execute().actionGet();
|
||||||
|
assertSearchResponse(resp);
|
||||||
|
logger.info("{} -> {} hits", optimizeBbox, resp.getHits().totalHits());
|
||||||
|
if (matches < 0) {
|
||||||
|
matches = resp.getHits().totalHits();
|
||||||
|
} else {
|
||||||
|
assertEquals(matches, resp.getHits().totalHits());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user