LUCENE-7117, LUCENE-7118: Remove multidimensional arrays from PointRangeQuery

This commit is contained in:
Robert Muir 2016-03-20 16:05:17 -04:00
parent cc01ba39cd
commit 51b109620b
13 changed files with 178 additions and 214 deletions

View File

@ -173,7 +173,7 @@ public final class BinaryPoint extends Field {
* @return a query matching documents within this range.
*/
public static Query newRangeQuery(String field, byte[][] lowerValue, byte[][] upperValue) {
return new PointRangeQuery(field, lowerValue, upperValue) {
return new PointRangeQuery(field, pack(lowerValue).bytes, pack(upperValue).bytes, lowerValue.length) {
@Override
protected String toString(int dimension, byte[] value) {
assert value != null;

View File

@ -126,16 +126,6 @@ public final class DoublePoint extends Field {
return result.toString();
}
/** Encode n-dimensional double point into binary encoding */
private static byte[][] encode(double value[]) {
byte[][] encoded = new byte[value.length][];
for (int i = 0; i < value.length; i++) {
encoded[i] = new byte[Double.BYTES];
encodeDimension(value[i], encoded[i], 0);
}
return encoded;
}
// public helper methods (e.g. for queries)
/** Encode single double dimension */
@ -207,7 +197,7 @@ public final class DoublePoint extends Field {
*/
public static Query newRangeQuery(String field, double[] lowerValue, double[] upperValue) {
PointRangeQuery.checkArgs(field, lowerValue, upperValue);
return new PointRangeQuery(field, encode(lowerValue), encode(upperValue)) {
return new PointRangeQuery(field, pack(lowerValue).bytes, pack(upperValue).bytes, lowerValue.length) {
@Override
protected String toString(int dimension, byte[] value) {
return Double.toString(decodeDimension(value, 0));

View File

@ -126,16 +126,6 @@ public final class FloatPoint extends Field {
return result.toString();
}
/** Encode n-dimensional float values into binary encoding */
private static byte[][] encode(float value[]) {
byte[][] encoded = new byte[value.length][];
for (int i = 0; i < value.length; i++) {
encoded[i] = new byte[Float.BYTES];
encodeDimension(value[i], encoded[i], 0);
}
return encoded;
}
// public helper methods (e.g. for queries)
/** Encode single float dimension */
@ -207,7 +197,7 @@ public final class FloatPoint extends Field {
*/
public static Query newRangeQuery(String field, float[] lowerValue, float[] upperValue) {
PointRangeQuery.checkArgs(field, lowerValue, upperValue);
return new PointRangeQuery(field, encode(lowerValue), encode(upperValue)) {
return new PointRangeQuery(field, pack(lowerValue).bytes, pack(upperValue).bytes, lowerValue.length) {
@Override
protected String toString(int dimension, byte[] value) {
return Float.toString(decodeDimension(value, 0));

View File

@ -125,16 +125,6 @@ public final class IntPoint extends Field {
result.append('>');
return result.toString();
}
/** Encode n-dimensional integer values into binary encoding */
private static byte[][] encode(int value[]) {
byte[][] encoded = new byte[value.length][];
for (int i = 0; i < value.length; i++) {
encoded[i] = new byte[Integer.BYTES];
encodeDimension(value[i], encoded[i], 0);
}
return encoded;
}
// public helper methods (e.g. for queries)
@ -205,7 +195,7 @@ public final class IntPoint extends Field {
*/
public static Query newRangeQuery(String field, int[] lowerValue, int[] upperValue) {
PointRangeQuery.checkArgs(field, lowerValue, upperValue);
return new PointRangeQuery(field, encode(lowerValue), encode(upperValue)) {
return new PointRangeQuery(field, pack(lowerValue).bytes, pack(upperValue).bytes, lowerValue.length) {
@Override
protected String toString(int dimension, byte[] value) {
return Integer.toString(decodeDimension(value, 0));

View File

@ -126,16 +126,6 @@ public final class LongPoint extends Field {
return result.toString();
}
/** Encode n-dimensional long values into binary encoding */
private static byte[][] encode(long value[]) {
byte[][] encoded = new byte[value.length][];
for (int i = 0; i < value.length; i++) {
encoded[i] = new byte[Long.BYTES];
encodeDimension(value[i], encoded[i], 0);
}
return encoded;
}
// public helper methods (e.g. for queries)
/** Encode single long dimension */
@ -205,7 +195,7 @@ public final class LongPoint extends Field {
*/
public static Query newRangeQuery(String field, long[] lowerValue, long[] upperValue) {
PointRangeQuery.checkArgs(field, lowerValue, upperValue);
return new PointRangeQuery(field, encode(lowerValue), encode(upperValue)) {
return new PointRangeQuery(field, pack(lowerValue).bytes, pack(upperValue).bytes, lowerValue.length) {
@Override
protected String toString(int dimension, byte[] value) {
return Long.toString(decodeDimension(value, 0));

View File

@ -47,8 +47,8 @@ public abstract class PointRangeQuery extends Query {
final String field;
final int numDims;
final int bytesPerDim;
final byte[][] lowerPoint;
final byte[][] upperPoint;
final byte[] lowerPoint;
final byte[] upperPoint;
/**
* Expert: create a multidimensional range query for point values.
@ -56,40 +56,26 @@ public abstract class PointRangeQuery extends Query {
* @param field field name. must not be {@code null}.
* @param lowerPoint lower portion of the range (inclusive).
* @param upperPoint upper portion of the range (inclusive).
* @param numDims number of dimensions.
* @throws IllegalArgumentException if {@code field} is null, or if {@code lowerValue.length != upperValue.length}
*/
protected PointRangeQuery(String field, byte[][] lowerPoint, byte[][] upperPoint) {
protected PointRangeQuery(String field, byte[] lowerPoint, byte[] upperPoint, int numDims) {
checkArgs(field, lowerPoint, upperPoint);
this.field = field;
if (lowerPoint.length == 0) {
throw new IllegalArgumentException("lowerPoint has length of zero");
}
this.numDims = lowerPoint.length;
if (upperPoint.length != numDims) {
if (lowerPoint.length % numDims != 0) {
throw new IllegalArgumentException("lowerPoint is not a fixed multiple of numDims");
}
if (upperPoint.length != upperPoint.length) {
throw new IllegalArgumentException("lowerPoint has length=" + numDims + " but upperPoint has different length=" + upperPoint.length);
}
this.numDims = numDims;
this.bytesPerDim = lowerPoint.length / numDims;
this.lowerPoint = lowerPoint;
this.upperPoint = upperPoint;
if (lowerPoint[0] == null) {
throw new IllegalArgumentException("lowerPoint[0] is null");
}
this.bytesPerDim = lowerPoint[0].length;
for (int i = 0; i < numDims; i++) {
if (lowerPoint[i] == null) {
throw new IllegalArgumentException("lowerPoint[" + i + "] is null");
}
if (upperPoint[i] == null) {
throw new IllegalArgumentException("upperPoint[" + i + "] is null");
}
if (lowerPoint[i].length != bytesPerDim) {
throw new IllegalArgumentException("all dimensions must have same bytes length, but saw " + bytesPerDim + " and " + lowerPoint[i].length);
}
if (upperPoint[i].length != bytesPerDim) {
throw new IllegalArgumentException("all dimensions must have same bytes length, but saw " + bytesPerDim + " and " + upperPoint[i].length);
}
}
}
/**
@ -116,8 +102,7 @@ public abstract class PointRangeQuery extends Query {
return new ConstantScoreWeight(this) {
private DocIdSet buildMatchingDocIdSet(LeafReader reader, PointValues values,
byte[] packedLower, byte[] packedUpper) throws IOException {
private DocIdSet buildMatchingDocIdSet(LeafReader reader, PointValues values) throws IOException {
DocIdSetBuilder result = new DocIdSetBuilder(reader.maxDoc());
values.intersect(field,
@ -137,11 +122,11 @@ public abstract class PointRangeQuery extends Query {
public void visit(int docID, byte[] packedValue) {
for(int dim=0;dim<numDims;dim++) {
int offset = dim*bytesPerDim;
if (StringHelper.compare(bytesPerDim, packedValue, offset, packedLower, offset) < 0) {
if (StringHelper.compare(bytesPerDim, packedValue, offset, lowerPoint, offset) < 0) {
// Doc's value is too low, in this dimension
return;
}
if (StringHelper.compare(bytesPerDim, packedValue, offset, packedUpper, offset) > 0) {
if (StringHelper.compare(bytesPerDim, packedValue, offset, upperPoint, offset) > 0) {
// Doc's value is too high, in this dimension
return;
}
@ -159,13 +144,13 @@ public abstract class PointRangeQuery extends Query {
for(int dim=0;dim<numDims;dim++) {
int offset = dim*bytesPerDim;
if (StringHelper.compare(bytesPerDim, minPackedValue, offset, packedUpper, offset) > 0 ||
StringHelper.compare(bytesPerDim, maxPackedValue, offset, packedLower, offset) < 0) {
if (StringHelper.compare(bytesPerDim, minPackedValue, offset, upperPoint, offset) > 0 ||
StringHelper.compare(bytesPerDim, maxPackedValue, offset, lowerPoint, offset) < 0) {
return Relation.CELL_OUTSIDE_QUERY;
}
crosses |= StringHelper.compare(bytesPerDim, minPackedValue, offset, packedLower, offset) < 0 ||
StringHelper.compare(bytesPerDim, maxPackedValue, offset, packedUpper, offset) > 0;
crosses |= StringHelper.compare(bytesPerDim, minPackedValue, offset, lowerPoint, offset) < 0 ||
StringHelper.compare(bytesPerDim, maxPackedValue, offset, upperPoint, offset) > 0;
}
if (crosses) {
@ -197,16 +182,6 @@ public abstract class PointRangeQuery extends Query {
if (bytesPerDim != fieldInfo.getPointNumBytes()) {
throw new IllegalArgumentException("field=\"" + field + "\" was indexed with bytesPerDim=" + fieldInfo.getPointNumBytes() + " but this query has bytesPerDim=" + bytesPerDim);
}
int bytesPerDim = fieldInfo.getPointNumBytes();
byte[] packedLower = new byte[numDims * bytesPerDim];
byte[] packedUpper = new byte[numDims * bytesPerDim];
// Carefully pack lower and upper bounds
for(int dim=0;dim<numDims;dim++) {
System.arraycopy(lowerPoint[dim], 0, packedLower, dim*bytesPerDim, bytesPerDim);
System.arraycopy(upperPoint[dim], 0, packedUpper, dim*bytesPerDim, bytesPerDim);
}
boolean allDocsMatch;
if (values.getDocCount(field) == reader.maxDoc()) {
@ -215,8 +190,8 @@ public abstract class PointRangeQuery extends Query {
allDocsMatch = true;
for (int i = 0; i < numDims; ++i) {
int offset = i * bytesPerDim;
if (StringHelper.compare(bytesPerDim, packedLower, offset, fieldPackedLower, offset) > 0
|| StringHelper.compare(bytesPerDim, packedUpper, offset, fieldPackedUpper, offset) < 0) {
if (StringHelper.compare(bytesPerDim, lowerPoint, offset, fieldPackedLower, offset) > 0
|| StringHelper.compare(bytesPerDim, upperPoint, offset, fieldPackedUpper, offset) < 0) {
allDocsMatch = false;
break;
}
@ -230,7 +205,7 @@ public abstract class PointRangeQuery extends Query {
// all docs have a value and all points are within bounds, so everything matches
iterator = DocIdSetIterator.all(reader.maxDoc());
} else {
iterator = buildMatchingDocIdSet(reader, values, packedLower, packedUpper).iterator();
iterator = buildMatchingDocIdSet(reader, values).iterator();
}
return new ConstantScoreScorer(this, score(), iterator);
@ -263,15 +238,12 @@ public abstract class PointRangeQuery extends Query {
return false;
}
// Cannot use Arrays.equals here, because it in turn uses byte[].equals
// to compare each value, which only uses "=="
for(int dim=0;dim<numDims;dim++) {
if (Arrays.equals(lowerPoint[dim], q.lowerPoint[dim]) == false) {
return false;
}
if (Arrays.equals(upperPoint[dim], q.upperPoint[dim]) == false) {
return false;
}
if (!Arrays.equals(lowerPoint, q.lowerPoint)) {
return false;
}
if (!Arrays.equals(upperPoint, q.upperPoint)) {
return false;
}
return true;
@ -290,11 +262,13 @@ public abstract class PointRangeQuery extends Query {
if (i > 0) {
sb.append(',');
}
int startOffset = bytesPerDim * i;
sb.append('[');
sb.append(toString(i, lowerPoint[i]));
sb.append(toString(i, Arrays.copyOfRange(lowerPoint, startOffset, startOffset + bytesPerDim)));
sb.append(" TO ");
sb.append(toString(i, upperPoint[i]));
sb.append(toString(i, Arrays.copyOfRange(upperPoint, startOffset, startOffset + bytesPerDim)));
sb.append(']');
}

View File

@ -1896,82 +1896,112 @@ public class TestPointQueries extends LuceneTestCase {
}
public void testPointRangeEquals() {
Query q = IntPoint.newRangeQuery("a", 0, 1000);
assertEquals(q, IntPoint.newRangeQuery("a", 0, 1000));
assertFalse(q.equals(IntPoint.newRangeQuery("a", 1, 1000)));
Query q1 = IntPoint.newRangeQuery("a", 0, 1000);
Query q2 = IntPoint.newRangeQuery("a", 0, 1000);
assertEquals(q1, q2);
assertEquals(q1.hashCode(), q2.hashCode());
assertFalse(q1.equals(IntPoint.newRangeQuery("a", 1, 1000)));
q = LongPoint.newRangeQuery("a", 0, 1000);
assertEquals(q, LongPoint.newRangeQuery("a", 0, 1000));
assertFalse(q.equals(LongPoint.newRangeQuery("a", 1, 1000)));
q1 = LongPoint.newRangeQuery("a", 0, 1000);
q2 = LongPoint.newRangeQuery("a", 0, 1000);
assertEquals(q1, q2);
assertEquals(q1.hashCode(), q2.hashCode());
assertFalse(q1.equals(LongPoint.newRangeQuery("a", 1, 1000)));
q = FloatPoint.newRangeQuery("a", 0, 1000);
assertEquals(q, FloatPoint.newRangeQuery("a", 0, 1000));
assertFalse(q.equals(FloatPoint.newRangeQuery("a", 1, 1000)));
q1 = FloatPoint.newRangeQuery("a", 0, 1000);
q2 = FloatPoint.newRangeQuery("a", 0, 1000);
assertEquals(q1, q2);
assertEquals(q1.hashCode(), q2.hashCode());
assertFalse(q1.equals(FloatPoint.newRangeQuery("a", 1, 1000)));
q = DoublePoint.newRangeQuery("a", 0, 1000);
assertEquals(q, DoublePoint.newRangeQuery("a", 0, 1000));
assertFalse(q.equals(DoublePoint.newRangeQuery("a", 1, 1000)));
q1 = DoublePoint.newRangeQuery("a", 0, 1000);
q2 = DoublePoint.newRangeQuery("a", 0, 1000);
assertEquals(q1, q2);
assertEquals(q1.hashCode(), q2.hashCode());
assertFalse(q1.equals(DoublePoint.newRangeQuery("a", 1, 1000)));
byte[] zeros = new byte[5];
byte[] ones = new byte[5];
Arrays.fill(ones, (byte) 0xff);
q = BinaryPoint.newRangeQuery("a", new byte[][] {zeros}, new byte[][] {ones});
assertEquals(q, BinaryPoint.newRangeQuery("a", new byte[][] {zeros}, new byte[][] {ones}));
q1 = BinaryPoint.newRangeQuery("a", new byte[][] {zeros}, new byte[][] {ones});
q2 = BinaryPoint.newRangeQuery("a", new byte[][] {zeros}, new byte[][] {ones});
assertEquals(q1, q2);
assertEquals(q1.hashCode(), q2.hashCode());
byte[] other = ones.clone();
other[2] = (byte) 5;
assertFalse(q.equals(BinaryPoint.newRangeQuery("a", new byte[][] {zeros}, new byte[][] {other})));
assertFalse(q1.equals(BinaryPoint.newRangeQuery("a", new byte[][] {zeros}, new byte[][] {other})));
}
public void testPointExactEquals() {
Query q = IntPoint.newExactQuery("a", 1000);
assertEquals(q, IntPoint.newExactQuery("a", 1000));
assertFalse(q.equals(IntPoint.newExactQuery("a", 1)));
Query q1 = IntPoint.newExactQuery("a", 1000);
Query q2 = IntPoint.newExactQuery("a", 1000);
assertEquals(q1, q2);
assertEquals(q1.hashCode(), q2.hashCode());
assertFalse(q1.equals(IntPoint.newExactQuery("a", 1)));
q = LongPoint.newExactQuery("a", 1000);
assertEquals(q, LongPoint.newExactQuery("a", 1000));
assertFalse(q.equals(LongPoint.newExactQuery("a", 1)));
q1 = LongPoint.newExactQuery("a", 1000);
q2 = LongPoint.newExactQuery("a", 1000);
assertEquals(q1, q2);
assertEquals(q1.hashCode(), q2.hashCode());
assertFalse(q1.equals(LongPoint.newExactQuery("a", 1)));
q = FloatPoint.newExactQuery("a", 1000);
assertEquals(q, FloatPoint.newExactQuery("a", 1000));
assertFalse(q.equals(FloatPoint.newExactQuery("a", 1)));
q1 = FloatPoint.newExactQuery("a", 1000);
q2 = FloatPoint.newExactQuery("a", 1000);
assertEquals(q1, q2);
assertEquals(q1.hashCode(), q2.hashCode());
assertFalse(q1.equals(FloatPoint.newExactQuery("a", 1)));
q = DoublePoint.newExactQuery("a", 1000);
assertEquals(q, DoublePoint.newExactQuery("a", 1000));
assertFalse(q.equals(DoublePoint.newExactQuery("a", 1)));
q1 = DoublePoint.newExactQuery("a", 1000);
q2 = DoublePoint.newExactQuery("a", 1000);
assertEquals(q1, q2);
assertEquals(q1.hashCode(), q2.hashCode());
assertFalse(q1.equals(DoublePoint.newExactQuery("a", 1)));
byte[] ones = new byte[5];
Arrays.fill(ones, (byte) 0xff);
q = BinaryPoint.newExactQuery("a", ones);
assertEquals(q, BinaryPoint.newExactQuery("a", ones));
q1 = BinaryPoint.newExactQuery("a", ones);
q2 = BinaryPoint.newExactQuery("a", ones);
assertEquals(q1, q2);
assertEquals(q1.hashCode(), q2.hashCode());
byte[] other = ones.clone();
other[2] = (byte) 5;
assertFalse(q.equals(BinaryPoint.newExactQuery("a", other)));
assertFalse(q1.equals(BinaryPoint.newExactQuery("a", other)));
}
public void testPointInSetEquals() {
Query q = IntPoint.newSetQuery("a", 0, 1000, 17);
assertEquals(q, IntPoint.newSetQuery("a", 17, 0, 1000));
assertFalse(q.equals(IntPoint.newSetQuery("a", 1, 17, 1000)));
Query q1 = IntPoint.newSetQuery("a", 0, 1000, 17);
Query q2 = IntPoint.newSetQuery("a", 17, 0, 1000);
assertEquals(q1, q2);
assertEquals(q1.hashCode(), q2.hashCode());
assertFalse(q1.equals(IntPoint.newSetQuery("a", 1, 17, 1000)));
q = LongPoint.newSetQuery("a", 0, 1000, 17);
assertEquals(q, LongPoint.newSetQuery("a", 17, 0, 1000));
assertFalse(q.equals(LongPoint.newSetQuery("a", 1, 17, 1000)));
q1 = LongPoint.newSetQuery("a", 0, 1000, 17);
q2 = LongPoint.newSetQuery("a", 17, 0, 1000);
assertEquals(q1, q2);
assertEquals(q1.hashCode(), q2.hashCode());
assertFalse(q1.equals(LongPoint.newSetQuery("a", 1, 17, 1000)));
q = FloatPoint.newSetQuery("a", 0, 1000, 17);
assertEquals(q, FloatPoint.newSetQuery("a", 17, 0, 1000));
assertFalse(q.equals(FloatPoint.newSetQuery("a", 1, 17, 1000)));
q1 = FloatPoint.newSetQuery("a", 0, 1000, 17);
q2 = FloatPoint.newSetQuery("a", 17, 0, 1000);
assertEquals(q1, q2);
assertEquals(q1.hashCode(), q2.hashCode());
assertFalse(q1.equals(FloatPoint.newSetQuery("a", 1, 17, 1000)));
q = DoublePoint.newSetQuery("a", 0, 1000, 17);
assertEquals(q, DoublePoint.newSetQuery("a", 17, 0, 1000));
assertFalse(q.equals(DoublePoint.newSetQuery("a", 1, 17, 1000)));
q1 = DoublePoint.newSetQuery("a", 0, 1000, 17);
q2 = DoublePoint.newSetQuery("a", 17, 0, 1000);
assertEquals(q1, q2);
assertEquals(q1.hashCode(), q2.hashCode());
assertFalse(q1.equals(DoublePoint.newSetQuery("a", 1, 17, 1000)));
byte[] zeros = new byte[5];
byte[] ones = new byte[5];
Arrays.fill(ones, (byte) 0xff);
q = BinaryPoint.newSetQuery("a", new byte[][] {zeros, ones});
assertEquals(q, BinaryPoint.newSetQuery("a", new byte[][] {zeros, ones}));
q1 = BinaryPoint.newSetQuery("a", new byte[][] {zeros, ones});
q2 = BinaryPoint.newSetQuery("a", new byte[][] {zeros, ones});
assertEquals(q1, q2);
assertEquals(q1.hashCode(), q2.hashCode());
byte[] other = ones.clone();
other[2] = (byte) 5;
assertFalse(q.equals(BinaryPoint.newSetQuery("a", new byte[][] {zeros, other})));
assertFalse(q1.equals(BinaryPoint.newSetQuery("a", new byte[][] {zeros, other})));
}
}

View File

@ -129,16 +129,6 @@ public class BigIntegerPoint extends Field {
result.append('>');
return result.toString();
}
/** sugar: Encode n-dimensional BigInteger values into binary encoding */
private static byte[][] encode(BigInteger value[]) {
byte[][] encoded = new byte[value.length][];
for (int i = 0; i < value.length; i++) {
encoded[i] = new byte[BYTES];
encodeDimension(value[i], encoded[i], 0);
}
return encoded;
}
// public helper methods (e.g. for queries)
@ -212,7 +202,7 @@ public class BigIntegerPoint extends Field {
*/
public static Query newRangeQuery(String field, BigInteger[] lowerValue, BigInteger[] upperValue) {
PointRangeQuery.checkArgs(field, lowerValue, upperValue);
return new PointRangeQuery(field, BigIntegerPoint.encode(lowerValue), BigIntegerPoint.encode(upperValue)) {
return new PointRangeQuery(field, pack(lowerValue).bytes, pack(upperValue).bytes, lowerValue.length) {
@Override
protected String toString(int dimension, byte[] value) {
return BigIntegerPoint.decodeDimension(value, 0).toString();

View File

@ -196,11 +196,7 @@ public class InetAddressPoint extends Field {
*/
public static Query newRangeQuery(String field, InetAddress lowerValue, InetAddress upperValue) {
PointRangeQuery.checkArgs(field, lowerValue, upperValue);
byte[][] lowerBytes = new byte[1][];
lowerBytes[0] = encode(lowerValue);
byte[][] upperBytes = new byte[1][];
upperBytes[0] = encode(upperValue);
return new PointRangeQuery(field, lowerBytes, upperBytes) {
return new PointRangeQuery(field, encode(lowerValue), encode(upperValue), 1) {
@Override
protected String toString(int dimension, byte[] value) {
return decode(value).getHostAddress(); // for ranges, the range itself is already bracketed

View File

@ -206,13 +206,11 @@ public class LatLonPoint extends Field {
return decodeLongitude(NumericUtils.sortableBytesToInt(src, offset));
}
/** sugar encodes a single point as a 2D byte array */
private static byte[][] encode(double latitude, double longitude) {
byte[][] bytes = new byte[2][];
bytes[0] = new byte[4];
NumericUtils.intToSortableBytes(encodeLatitude(latitude), bytes[0], 0);
bytes[1] = new byte[4];
NumericUtils.intToSortableBytes(encodeLongitude(longitude), bytes[1], 0);
/** sugar encodes a single point as a byte array */
private static byte[] encode(double latitude, double longitude) {
byte[] bytes = new byte[2 * Integer.BYTES];
NumericUtils.intToSortableBytes(encodeLatitude(latitude), bytes, 0);
NumericUtils.intToSortableBytes(encodeLongitude(longitude), bytes, Integer.BYTES);
return bytes;
}
@ -251,8 +249,8 @@ public class LatLonPoint extends Field {
* @throws IllegalArgumentException if {@code field} is null, or the box has invalid coordinates.
*/
public static Query newBoxQuery(String field, double minLatitude, double maxLatitude, double minLongitude, double maxLongitude) {
byte[][] lower = encode(minLatitude, minLongitude);
byte[][] upper = encode(maxLatitude, maxLongitude);
byte[] lower = encode(minLatitude, minLongitude);
byte[] upper = encode(maxLatitude, maxLongitude);
// Crosses date line: we just rewrite into OR of two bboxes, with longitude as an open range:
if (maxLongitude < minLongitude) {
// Disable coord here because a multi-valued doc could match both rects and get unfairly boosted:
@ -260,19 +258,15 @@ public class LatLonPoint extends Field {
q.setDisableCoord(true);
// E.g.: maxLon = -179, minLon = 179
byte[][] leftOpen = new byte[2][];
leftOpen[0] = lower[0];
byte[] leftOpen = lower.clone();
// leave longitude open
leftOpen[1] = new byte[Integer.BYTES];
NumericUtils.intToSortableBytes(Integer.MIN_VALUE, leftOpen[1], 0);
NumericUtils.intToSortableBytes(Integer.MIN_VALUE, leftOpen, Integer.BYTES);
Query left = newBoxInternal(field, leftOpen, upper);
q.add(new BooleanClause(left, BooleanClause.Occur.SHOULD));
byte[][] rightOpen = new byte[2][];
rightOpen[0] = upper[0];
byte[] rightOpen = upper.clone();
// leave longitude open
rightOpen[1] = new byte[Integer.BYTES];
NumericUtils.intToSortableBytes(Integer.MAX_VALUE, rightOpen[1], 0);
NumericUtils.intToSortableBytes(Integer.MAX_VALUE, rightOpen, Integer.BYTES);
Query right = newBoxInternal(field, lower, rightOpen);
q.add(new BooleanClause(right, BooleanClause.Occur.SHOULD));
return new ConstantScoreQuery(q.build());
@ -281,8 +275,8 @@ public class LatLonPoint extends Field {
}
}
private static Query newBoxInternal(String field, byte[][] min, byte[][] max) {
return new PointRangeQuery(field, min, max) {
private static Query newBoxInternal(String field, byte[] min, byte[] max) {
return new PointRangeQuery(field, min, max, 2) {
@Override
protected String toString(int dimension, byte[] value) {
if (dimension == 0) {

View File

@ -96,16 +96,22 @@ public class TestBigIntegerPoint extends LuceneTestCase {
}
public void testQueryEquals() throws Exception {
Query q = BigIntegerPoint.newRangeQuery("a", BigInteger.valueOf(0), BigInteger.valueOf(1000));
assertEquals(q, BigIntegerPoint.newRangeQuery("a", BigInteger.valueOf(0), BigInteger.valueOf(1000)));
assertFalse(q.equals(BigIntegerPoint.newRangeQuery("a", BigInteger.valueOf(1), BigInteger.valueOf(1000))));
Query q1 = BigIntegerPoint.newRangeQuery("a", BigInteger.valueOf(0), BigInteger.valueOf(1000));
Query q2 = BigIntegerPoint.newRangeQuery("a", BigInteger.valueOf(0), BigInteger.valueOf(1000));
assertEquals(q1, q2);
assertEquals(q1.hashCode(), q2.hashCode());
assertFalse(q1.equals(BigIntegerPoint.newRangeQuery("a", BigInteger.valueOf(1), BigInteger.valueOf(1000))));
q = BigIntegerPoint.newExactQuery("a", BigInteger.valueOf(1000));
assertEquals(q, BigIntegerPoint.newExactQuery("a", BigInteger.valueOf(1000)));
assertFalse(q.equals(BigIntegerPoint.newExactQuery("a", BigInteger.valueOf(1))));
q1 = BigIntegerPoint.newExactQuery("a", BigInteger.valueOf(1000));
q2 = BigIntegerPoint.newExactQuery("a", BigInteger.valueOf(1000));
assertEquals(q1, q2);
assertEquals(q1.hashCode(), q2.hashCode());
assertFalse(q1.equals(BigIntegerPoint.newExactQuery("a", BigInteger.valueOf(1))));
q = BigIntegerPoint.newSetQuery("a", BigInteger.valueOf(0), BigInteger.valueOf(1000), BigInteger.valueOf(17));
assertEquals(q, BigIntegerPoint.newSetQuery("a", BigInteger.valueOf(17), BigInteger.valueOf(0), BigInteger.valueOf(1000)));
assertFalse(q.equals(BigIntegerPoint.newSetQuery("a", BigInteger.valueOf(1), BigInteger.valueOf(17), BigInteger.valueOf(1000))));
q1 = BigIntegerPoint.newSetQuery("a", BigInteger.valueOf(0), BigInteger.valueOf(1000), BigInteger.valueOf(17));
q2 = BigIntegerPoint.newSetQuery("a", BigInteger.valueOf(17), BigInteger.valueOf(0), BigInteger.valueOf(1000));
assertEquals(q1, q2);
assertEquals(q1.hashCode(), q2.hashCode());
assertFalse(q1.equals(BigIntegerPoint.newSetQuery("a", BigInteger.valueOf(1), BigInteger.valueOf(17), BigInteger.valueOf(1000))));
}
}

View File

@ -92,21 +92,29 @@ public class TestInetAddressPoint extends LuceneTestCase {
}
public void testQueryEquals() throws Exception {
Query q = InetAddressPoint.newRangeQuery("a", InetAddress.getByName("1.2.3.3"), InetAddress.getByName("1.2.3.5"));
assertEquals(q, InetAddressPoint.newRangeQuery("a", InetAddress.getByName("1.2.3.3"), InetAddress.getByName("1.2.3.5")));
assertFalse(q.equals(InetAddressPoint.newRangeQuery("a", InetAddress.getByName("1.2.3.3"), InetAddress.getByName("1.2.3.7"))));
Query q1 = InetAddressPoint.newRangeQuery("a", InetAddress.getByName("1.2.3.3"), InetAddress.getByName("1.2.3.5"));
Query q2 = InetAddressPoint.newRangeQuery("a", InetAddress.getByName("1.2.3.3"), InetAddress.getByName("1.2.3.5"));
assertEquals(q1, q2);
assertEquals(q1.hashCode(), q2.hashCode());
assertFalse(q1.equals(InetAddressPoint.newRangeQuery("a", InetAddress.getByName("1.2.3.3"), InetAddress.getByName("1.2.3.7"))));
q = InetAddressPoint.newPrefixQuery("a", InetAddress.getByName("1.2.3.3"), 16);
assertEquals(q, InetAddressPoint.newPrefixQuery("a", InetAddress.getByName("1.2.3.3"), 16));
assertFalse(q.equals(InetAddressPoint.newPrefixQuery("a", InetAddress.getByName("1.1.3.5"), 16)));
assertFalse(q.equals(InetAddressPoint.newPrefixQuery("a", InetAddress.getByName("1.2.3.5"), 24)));
q1 = InetAddressPoint.newPrefixQuery("a", InetAddress.getByName("1.2.3.3"), 16);
q2 = InetAddressPoint.newPrefixQuery("a", InetAddress.getByName("1.2.3.3"), 16);
assertEquals(q1, q2);
assertEquals(q1.hashCode(), q2.hashCode());
assertFalse(q1.equals(InetAddressPoint.newPrefixQuery("a", InetAddress.getByName("1.1.3.5"), 16)));
assertFalse(q1.equals(InetAddressPoint.newPrefixQuery("a", InetAddress.getByName("1.2.3.5"), 24)));
q = InetAddressPoint.newExactQuery("a", InetAddress.getByName("1.2.3.3"));
assertEquals(q, InetAddressPoint.newExactQuery("a", InetAddress.getByName("1.2.3.3")));
assertFalse(q.equals(InetAddressPoint.newExactQuery("a", InetAddress.getByName("1.2.3.5"))));
q1 = InetAddressPoint.newExactQuery("a", InetAddress.getByName("1.2.3.3"));
q2 = InetAddressPoint.newExactQuery("a", InetAddress.getByName("1.2.3.3"));
assertEquals(q1, q2);
assertEquals(q1.hashCode(), q2.hashCode());
assertFalse(q1.equals(InetAddressPoint.newExactQuery("a", InetAddress.getByName("1.2.3.5"))));
q = InetAddressPoint.newSetQuery("a", InetAddress.getByName("1.2.3.3"), InetAddress.getByName("1.2.3.5"));
assertEquals(q, InetAddressPoint.newSetQuery("a", InetAddress.getByName("1.2.3.3"), InetAddress.getByName("1.2.3.5")));
assertFalse(q.equals(InetAddressPoint.newSetQuery("a", InetAddress.getByName("1.2.3.3"), InetAddress.getByName("1.2.3.7"))));
q1 = InetAddressPoint.newSetQuery("a", InetAddress.getByName("1.2.3.3"), InetAddress.getByName("1.2.3.5"));
q2 = InetAddressPoint.newSetQuery("a", InetAddress.getByName("1.2.3.3"), InetAddress.getByName("1.2.3.5"));
assertEquals(q1, q2);
assertEquals(q1.hashCode(), q2.hashCode());
assertFalse(q1.equals(InetAddressPoint.newSetQuery("a", InetAddress.getByName("1.2.3.3"), InetAddress.getByName("1.2.3.7"))));
}
}

View File

@ -186,21 +186,27 @@ public class TestLatLonPoint extends LuceneTestCase {
}
public void testQueryEquals() throws Exception {
Query q = LatLonPoint.newBoxQuery("field", 50, 70, -40, 20);
assertEquals(q, LatLonPoint.newBoxQuery("field", 50, 70, -40, 20));
assertFalse(q.equals(LatLonPoint.newBoxQuery("field", 50, 70, -40, 10)));
Query q1 = LatLonPoint.newBoxQuery("field", 50, 70, -40, 20);
Query q2 = LatLonPoint.newBoxQuery("field", 50, 70, -40, 20);
assertEquals(q1, q2);
assertEquals(q1.hashCode(), q2.hashCode());
assertFalse(q1.equals(LatLonPoint.newBoxQuery("field", 50, 70, -40, 10)));
q = LatLonPoint.newDistanceQuery("field", 50, 70, 10000);
assertEquals(q, LatLonPoint.newDistanceQuery("field", 50, 70, 10000));
assertFalse(q.equals(LatLonPoint.newDistanceQuery("field", 50, 70, 11000)));
assertFalse(q.equals(LatLonPoint.newDistanceQuery("field", 50, 60, 10000)));
q1 = LatLonPoint.newDistanceQuery("field", 50, 70, 10000);
q2 = LatLonPoint.newDistanceQuery("field", 50, 70, 10000);
assertEquals(q1, q2);
assertEquals(q1.hashCode(), q2.hashCode());
assertFalse(q1.equals(LatLonPoint.newDistanceQuery("field", 50, 70, 11000)));
assertFalse(q1.equals(LatLonPoint.newDistanceQuery("field", 50, 60, 10000)));
double[] polyLats1 = new double[] {30, 40, 40, 30, 30};
double[] polyLons1 = new double[] {90, 90, -40, -40, 90};
double[] polyLats2 = new double[] {20, 40, 40, 20, 20};
q = LatLonPoint.newPolygonQuery("field", polyLats1, polyLons1);
assertEquals(q, LatLonPoint.newPolygonQuery("field", polyLats1, polyLons1));
assertFalse(q.equals(LatLonPoint.newPolygonQuery("field", polyLats2, polyLons1)));
q1 = LatLonPoint.newPolygonQuery("field", polyLats1, polyLons1);
q2 = LatLonPoint.newPolygonQuery("field", polyLats1, polyLons1);
assertEquals(q1, q2);
assertEquals(q1.hashCode(), q2.hashCode());
assertFalse(q1.equals(LatLonPoint.newPolygonQuery("field", polyLats2, polyLons1)));
}
}