diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/search/geo/GeoBoundingBoxFilter.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/search/geo/GeoBoundingBoxFilter.java index aec26663566..1f74e0ea4cc 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/search/geo/GeoBoundingBoxFilter.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/search/geo/GeoBoundingBoxFilter.java @@ -66,79 +66,103 @@ public class GeoBoundingBoxFilter extends Filter { //checks to see if bounding box crosses 180 degrees if (topLeft.lon > bottomRight.lon) { - return new GetDocSet(reader.maxDoc()) { - - @Override public boolean isCacheable() { - // not cacheable for several reasons: - // 1. It is only relevant when _cache is set to true, and then, we really want to create in mem bitset - // 2. Its already fast without in mem bitset, since it works with field data - return false; - } - - @Override public boolean get(int doc) throws IOException { - if (!fieldData.hasValue(doc)) { - return false; - } - - if (fieldData.multiValued()) { - double[] lats = fieldData.latValues(doc); - double[] lons = fieldData.lonValues(doc); - for (int i = 0; i < lats.length; i++) { - double lat = lats[i]; - double lon = lons[i]; - if (((topLeft.lon <= lon && 180 >= lon) || (-180 <= lon && bottomRight.lon >= lon)) && - (topLeft.lat >= lat && bottomRight.lat <= lat)) { - return true; - } - } - } else { - double lat = fieldData.latValue(doc); - double lon = fieldData.lonValue(doc); - - if (((topLeft.lon <= lon && 180 >= lon) || (-180 <= lon && bottomRight.lon >= lon)) && - (topLeft.lat >= lat && bottomRight.lat <= lat)) { - return true; - } - } - return false; - } - }; + return new LeftGeoBoundingBoxDocSet(reader.maxDoc(), fieldData, topLeft, bottomRight); } else { - return new GetDocSet(reader.maxDoc()) { + return new RightGeoBoundingBoxDocSet(reader.maxDoc(), fieldData, topLeft, bottomRight); + } + } - @Override public boolean isCacheable() { - // not cacheable for several reasons: - // 1. It is only relevant when _cache is set to true, and then, we really want to create in mem bitset - // 2. Its already fast without in mem bitset, since it works with field data - return false; - } + public static class LeftGeoBoundingBoxDocSet extends GetDocSet { + private final GeoPointFieldData fieldData; + private final Point topLeft; + private final Point bottomRight; - @Override public boolean get(int doc) throws IOException { - if (!fieldData.hasValue(doc)) { - return false; + public LeftGeoBoundingBoxDocSet(int maxDoc, GeoPointFieldData fieldData, Point topLeft, Point bottomRight) { + super(maxDoc); + this.fieldData = fieldData; + this.topLeft = topLeft; + this.bottomRight = bottomRight; + } + + @Override public boolean isCacheable() { + // not cacheable for several reasons: + // 1. It is only relevant when _cache is set to true, and then, we really want to create in mem bitset + // 2. Its already fast without in mem bitset, since it works with field data + return false; + } + + @Override public boolean get(int doc) throws IOException { + if (!fieldData.hasValue(doc)) { + return false; + } + + if (fieldData.multiValued()) { + double[] lats = fieldData.latValues(doc); + double[] lons = fieldData.lonValues(doc); + for (int i = 0; i < lats.length; i++) { + double lat = lats[i]; + double lon = lons[i]; + if (((topLeft.lon <= lon && 180 >= lon) || (-180 <= lon && bottomRight.lon >= lon)) && + (topLeft.lat >= lat && bottomRight.lat <= lat)) { + return true; } - - if (fieldData.multiValued()) { - double[] lats = fieldData.latValues(doc); - double[] lons = fieldData.lonValues(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 = fieldData.latValue(doc); - double lon = fieldData.lonValue(doc); - - if (topLeft.lon <= lon && bottomRight.lon >= lon - && topLeft.lat >= lat && bottomRight.lat <= lat) { - return true; - } - } - return false; } - }; + } else { + double lat = fieldData.latValue(doc); + double lon = fieldData.lonValue(doc); + + if (((topLeft.lon <= lon && 180 >= lon) || (-180 <= lon && bottomRight.lon >= lon)) && + (topLeft.lat >= lat && bottomRight.lat <= lat)) { + return true; + } + } + return false; + } + } + + public static class RightGeoBoundingBoxDocSet extends GetDocSet { + private final GeoPointFieldData fieldData; + private final Point topLeft; + private final Point bottomRight; + + public RightGeoBoundingBoxDocSet(int maxDoc, GeoPointFieldData fieldData, Point topLeft, Point bottomRight) { + super(maxDoc); + this.fieldData = fieldData; + this.topLeft = topLeft; + this.bottomRight = bottomRight; + } + + @Override public boolean isCacheable() { + // not cacheable for several reasons: + // 1. It is only relevant when _cache is set to true, and then, we really want to create in mem bitset + // 2. Its already fast without in mem bitset, since it works with field data + return false; + } + + @Override public boolean get(int doc) throws IOException { + if (!fieldData.hasValue(doc)) { + return false; + } + + if (fieldData.multiValued()) { + double[] lats = fieldData.latValues(doc); + double[] lons = fieldData.lonValues(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 = fieldData.latValue(doc); + double lon = fieldData.lonValue(doc); + + if (topLeft.lon <= lon && bottomRight.lon >= lon + && topLeft.lat >= lat && bottomRight.lat <= lat) { + return true; + } + } + return false; } } diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/search/geo/GeoDistanceFilter.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/search/geo/GeoDistanceFilter.java index 50f69c5c569..fc45043db5f 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/search/geo/GeoDistanceFilter.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/search/geo/GeoDistanceFilter.java @@ -78,36 +78,7 @@ public class GeoDistanceFilter extends Filter { @Override public DocIdSet getDocIdSet(IndexReader reader) throws IOException { final GeoPointFieldData fieldData = (GeoPointFieldData) fieldDataCache.cache(GeoPointFieldDataType.TYPE, reader, fieldName); - return new GetDocSet(reader.maxDoc()) { - - @Override public boolean isCacheable() { - // not cacheable for several reasons: - // 1. It is only relevant when _cache is set to true, and then, we really want to create in mem bitset - // 2. Its already fast without in mem bitset, since it works with field data - return false; - } - - @Override public boolean get(int doc) throws IOException { - if (!fieldData.hasValue(doc)) { - return false; - } - - if (fieldData.multiValued()) { - double[] lats = fieldData.latValues(doc); - double[] lons = fieldData.lonValues(doc); - for (int i = 0; i < lats.length; i++) { - double d = geoDistance.calculate(lat, lon, lats[i], lons[i], DistanceUnit.MILES); - if (d < distance) { - return true; - } - } - return false; - } else { - double d = geoDistance.calculate(lat, lon, fieldData.latValue(doc), fieldData.lonValue(doc), DistanceUnit.MILES); - return d < distance; - } - } - }; + return new GeoDistanceDocSet(reader.maxDoc(), geoDistance, fieldData, lat, lon, distance); } @Override @@ -140,4 +111,49 @@ public class GeoDistanceFilter extends Filter { result = 31 * result + (fieldName != null ? fieldName.hashCode() : 0); return result; } + + public static class GeoDistanceDocSet extends GetDocSet { + private final GeoDistance geoDistance; + private final GeoPointFieldData fieldData; + private final double lat; + private final double lon; + private final double distance; + + public GeoDistanceDocSet(int maxDoc, GeoDistance geoDistance, GeoPointFieldData fieldData, double lat, double lon, double distance) { + super(maxDoc); + this.geoDistance = geoDistance; + this.fieldData = fieldData; + this.lat = lat; + this.lon = lon; + this.distance = distance; + } + + @Override public boolean isCacheable() { + // not cacheable for several reasons: + // 1. It is only relevant when _cache is set to true, and then, we really want to create in mem bitset + // 2. Its already fast without in mem bitset, since it works with field data + return false; + } + + @Override public boolean get(int doc) throws IOException { + if (!fieldData.hasValue(doc)) { + return false; + } + + if (fieldData.multiValued()) { + double[] lats = fieldData.latValues(doc); + double[] lons = fieldData.lonValues(doc); + for (int i = 0; i < lats.length; i++) { + double d = geoDistance.calculate(lat, lon, lats[i], lons[i], DistanceUnit.MILES); + if (d < distance) { + return true; + } + } + return false; + } else { + double d = geoDistance.calculate(lat, lon, fieldData.latValue(doc), fieldData.lonValue(doc), DistanceUnit.MILES); + return d < distance; + } + } + } } diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/search/geo/GeoDistanceRangeFilter.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/search/geo/GeoDistanceRangeFilter.java index 0537d8545d6..dbf35de5290 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/search/geo/GeoDistanceRangeFilter.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/search/geo/GeoDistanceRangeFilter.java @@ -37,7 +37,6 @@ import java.io.IOException; public class GeoDistanceRangeFilter extends Filter { private final double lat; - private final double lon; private final double inclusiveLowerPoint; // in miles @@ -90,39 +89,7 @@ public class GeoDistanceRangeFilter extends Filter { @Override public DocIdSet getDocIdSet(IndexReader reader) throws IOException { final GeoPointFieldData fieldData = (GeoPointFieldData) fieldDataCache.cache(GeoPointFieldDataType.TYPE, reader, fieldName); - return new GetDocSet(reader.maxDoc()) { - - @Override public boolean isCacheable() { - // not cacheable for several reasons: - // 1. It is only relevant when _cache is set to true, and then, we really want to create in mem bitset - // 2. Its already fast without in mem bitset, since it works with field data - return false; - } - - @Override public boolean get(int doc) throws IOException { - if (!fieldData.hasValue(doc)) { - return false; - } - - if (fieldData.multiValued()) { - double[] lats = fieldData.latValues(doc); - double[] lons = fieldData.lonValues(doc); - for (int i = 0; i < lats.length; i++) { - double d = geoDistance.calculate(lat, lon, lats[i], lons[i], DistanceUnit.MILES); - if (d >= inclusiveLowerPoint && d <= inclusiveUpperPoint) { - return true; - } - } - return false; - } else { - double d = geoDistance.calculate(lat, lon, fieldData.latValue(doc), fieldData.lonValue(doc), DistanceUnit.MILES); - if (d >= inclusiveLowerPoint && d <= inclusiveUpperPoint) { - return true; - } - return false; - } - } - }; + return new GeoDistanceRangeDocSet(reader.maxDoc(), fieldData, geoDistance, lat, lon, inclusiveLowerPoint, inclusiveUpperPoint); } @Override @@ -158,4 +125,55 @@ public class GeoDistanceRangeFilter extends Filter { result = 31 * result + (fieldName != null ? fieldName.hashCode() : 0); return result; } + + public static class GeoDistanceRangeDocSet extends GetDocSet { + + private final GeoPointFieldData fieldData; + private final GeoDistance geoDistance; + private final double lat; + private final double lon; + private final double inclusiveLowerPoint; // in miles + private final double inclusiveUpperPoint; // in miles + + public GeoDistanceRangeDocSet(int maxDoc, GeoPointFieldData fieldData, GeoDistance geoDistance, double lat, double lon, double inclusiveLowerPoint, double inclusiveUpperPoint) { + super(maxDoc); + this.fieldData = fieldData; + this.geoDistance = geoDistance; + this.lat = lat; + this.lon = lon; + this.inclusiveLowerPoint = inclusiveLowerPoint; + this.inclusiveUpperPoint = inclusiveUpperPoint; + } + + @Override public boolean isCacheable() { + // not cacheable for several reasons: + // 1. It is only relevant when _cache is set to true, and then, we really want to create in mem bitset + // 2. Its already fast without in mem bitset, since it works with field data + return false; + } + + @Override public boolean get(int doc) throws IOException { + if (!fieldData.hasValue(doc)) { + return false; + } + + if (fieldData.multiValued()) { + double[] lats = fieldData.latValues(doc); + double[] lons = fieldData.lonValues(doc); + for (int i = 0; i < lats.length; i++) { + double d = geoDistance.calculate(lat, lon, lats[i], lons[i], DistanceUnit.MILES); + if (d >= inclusiveLowerPoint && d <= inclusiveUpperPoint) { + return true; + } + } + return false; + } else { + double d = geoDistance.calculate(lat, lon, fieldData.latValue(doc), fieldData.lonValue(doc), DistanceUnit.MILES); + if (d >= inclusiveLowerPoint && d <= inclusiveUpperPoint) { + return true; + } + return false; + } + } + } } diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/search/geo/GeoPolygonFilter.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/search/geo/GeoPolygonFilter.java index 907f3e00112..08f4374f899 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/search/geo/GeoPolygonFilter.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/search/geo/GeoPolygonFilter.java @@ -56,55 +56,64 @@ public class GeoPolygonFilter extends Filter { @Override public DocIdSet getDocIdSet(IndexReader reader) throws IOException { final GeoPointFieldData fieldData = (GeoPointFieldData) fieldDataCache.cache(GeoPointFieldDataType.TYPE, reader, fieldName); - - return new GetDocSet(reader.maxDoc()) { - - @Override public boolean isCacheable() { - // not cacheable for several reasons: - // 1. It is only relevant when _cache is set to true, and then, we really want to create in mem bitset - // 2. Its already fast without in mem bitset, since it works with field data - return false; - } - - @Override public boolean get(int doc) throws IOException { - if (!fieldData.hasValue(doc)) { - return false; - } - - if (fieldData.multiValued()) { - double[] lats = fieldData.latValues(doc); - double[] lons = fieldData.lonValues(doc); - for (int i = 0; i < lats.length; i++) { - if (pointInPolygon(points, lats[i], lons[i])) { - return true; - } - } - } else { - double lat = fieldData.latValue(doc); - double lon = fieldData.lonValue(doc); - return pointInPolygon(points, lat, lon); - } - return false; - } - }; + return new GeoPolygonDocSet(reader.maxDoc(), fieldData, points); } - private static boolean pointInPolygon(Point[] points, double lat, double lon) { - int i; - int j = points.length - 1; - boolean inPoly = false; + public static class GeoPolygonDocSet extends GetDocSet { + private final GeoPointFieldData fieldData; + private final Point[] points; - for (i = 0; i < points.length; i++) { - if (points[i].lon < lon && points[j].lon >= lon - || points[j].lon < lon && points[i].lon >= lon) { - if (points[i].lat + (lon - points[i].lon) / - (points[j].lon - points[i].lon) * (points[j].lat - points[i].lat) < lat) { - inPoly = !inPoly; - } - } - j = i; + public GeoPolygonDocSet(int maxDoc, GeoPointFieldData fieldData, Point[] points) { + super(maxDoc); + this.fieldData = fieldData; + this.points = points; + } + + @Override public boolean isCacheable() { + // not cacheable for several reasons: + // 1. It is only relevant when _cache is set to true, and then, we really want to create in mem bitset + // 2. Its already fast without in mem bitset, since it works with field data + return false; + } + + @Override public boolean get(int doc) throws IOException { + if (!fieldData.hasValue(doc)) { + return false; + } + + if (fieldData.multiValued()) { + double[] lats = fieldData.latValues(doc); + double[] lons = fieldData.lonValues(doc); + for (int i = 0; i < lats.length; i++) { + if (pointInPolygon(points, lats[i], lons[i])) { + return true; + } + } + } else { + double lat = fieldData.latValue(doc); + double lon = fieldData.lonValue(doc); + return pointInPolygon(points, lat, lon); + } + return false; + } + + private static boolean pointInPolygon(Point[] points, double lat, double lon) { + int i; + int j = points.length - 1; + boolean inPoly = false; + + for (i = 0; i < points.length; i++) { + if (points[i].lon < lon && points[j].lon >= lon + || points[j].lon < lon && points[i].lon >= lon) { + if (points[i].lat + (lon - points[i].lon) / + (points[j].lon - points[i].lon) * (points[j].lat - points[i].lat) < lat) { + inPoly = !inPoly; + } + } + j = i; + } + return inPoly; } - return inPoly; } public static class Point {