use static classes for docsets instead of inner classes to make sure we don't rely on hotspot to inline field lookups

This commit is contained in:
Shay Banon 2011-08-17 04:20:43 +03:00
parent 451c87f486
commit 55f62eca8a
4 changed files with 244 additions and 177 deletions

View File

@ -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;
}
}

View File

@ -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;
}
}
}
}

View File

@ -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;
}
}
}
}

View File

@ -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 {