mirror of https://github.com/apache/lucene.git
Merge branch 'master' into point_set_query
Conflicts: lucene/core/src/java/org/apache/lucene/document/IntPoint.java
This commit is contained in:
commit
8a4c19777e
|
@ -16,14 +16,22 @@
|
|||
*/
|
||||
package org.apache.lucene.document;
|
||||
|
||||
|
||||
import org.apache.lucene.search.PointRangeQuery;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
|
||||
/** A binary field that is indexed dimensionally such that finding
|
||||
* all documents within an N-dimensional shape or range at search time is
|
||||
* efficient. Multiple values for the same field in one documents
|
||||
* is allowed. */
|
||||
|
||||
/**
|
||||
* A binary field that is indexed dimensionally such that finding
|
||||
* all documents within an N-dimensional shape or range at search time is
|
||||
* efficient. Multiple values for the same field in one documents
|
||||
* is allowed.
|
||||
* <p>
|
||||
* This field defines static factory methods for creating common queries:
|
||||
* <ul>
|
||||
* <li>{@link #newExactQuery newExactQuery()} for matching an exact 1D point.
|
||||
* <li>{@link #newRangeQuery newRangeQuery()} for matching a 1D range.
|
||||
* <li>{@link #newMultiRangeQuery newMultiRangeQuery()} for matching points/ranges in n-dimensional space.
|
||||
* </ul>
|
||||
*/
|
||||
public final class BinaryPoint extends Field {
|
||||
|
||||
private static FieldType getType(byte[][] point) {
|
||||
|
@ -107,4 +115,85 @@ public final class BinaryPoint extends Field {
|
|||
throw new IllegalArgumentException("packedPoint is length=" + packedPoint.length + " but type.pointDimensionCount()=" + type.pointDimensionCount() + " and type.pointNumBytes()=" + type.pointNumBytes());
|
||||
}
|
||||
}
|
||||
|
||||
// static methods for generating queries
|
||||
|
||||
/**
|
||||
* Create a query for matching an exact binary value.
|
||||
* <p>
|
||||
* This is for simple one-dimension points, for multidimensional points use
|
||||
* {@link #newMultiRangeQuery newMultiRangeQuery()} instead.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param value binary value
|
||||
* @throws IllegalArgumentException if {@code field} is null or {@code value} is null
|
||||
* @return a query matching documents with this exact value
|
||||
*/
|
||||
public static PointRangeQuery newExactQuery(String field, byte[] value) {
|
||||
if (value == null) {
|
||||
throw new IllegalArgumentException("value cannot be null");
|
||||
}
|
||||
return newRangeQuery(field, value, true, value, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a range query for binary values.
|
||||
* <p>
|
||||
* This is for simple one-dimension ranges, for multidimensional ranges use
|
||||
* {@link #newMultiRangeQuery newMultiRangeQuery()} instead.
|
||||
* <p>
|
||||
* You can have half-open ranges (which are in fact </≤ or >/≥ queries)
|
||||
* by setting the {@code lowerValue} or {@code upperValue} to {@code null}.
|
||||
* <p>
|
||||
* By setting inclusive ({@code lowerInclusive} or {@code upperInclusive}) to false, it will
|
||||
* match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param lowerValue lower portion of the range. {@code null} means "open".
|
||||
* @param lowerInclusive {@code true} if the lower portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @param upperValue upper portion of the range. {@code null} means "open".
|
||||
* @param upperInclusive {@code true} if the upper portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @throws IllegalArgumentException if {@code field} is null.
|
||||
* @return a query matching documents within this range.
|
||||
*/
|
||||
public static PointRangeQuery newRangeQuery(String field, byte[] lowerValue, boolean lowerInclusive, byte[] upperValue, boolean upperInclusive) {
|
||||
return newMultiRangeQuery(field, new byte[][] {lowerValue}, new boolean[] {lowerInclusive}, new byte[][] {upperValue}, new boolean[] {upperInclusive});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a multidimensional range query for binary values.
|
||||
* <p>
|
||||
* You can have half-open ranges (which are in fact </≤ or >/≥ queries)
|
||||
* by setting a {@code lowerValue} element or {@code upperValue} element to {@code null}.
|
||||
* <p>
|
||||
* By setting a dimension's inclusive ({@code lowerInclusive} or {@code upperInclusive}) to false, it will
|
||||
* match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param lowerValue lower portion of the range. {@code null} values mean "open" for that dimension.
|
||||
* @param lowerInclusive {@code true} if the lower portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @param upperValue upper portion of the range. {@code null} values mean "open" for that dimension.
|
||||
* @param upperInclusive {@code true} if the upper portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @throws IllegalArgumentException if {@code field} is null, or if {@code lowerValue.length != upperValue.length}
|
||||
* @return a query matching documents within this range.
|
||||
*/
|
||||
public static PointRangeQuery newMultiRangeQuery(String field, byte[][] lowerValue, boolean[] lowerInclusive, byte[][] upperValue, boolean[] upperInclusive) {
|
||||
PointRangeQuery.checkArgs(field, lowerValue, upperValue);
|
||||
return new PointRangeQuery(field, lowerValue, lowerInclusive, upperValue, upperInclusive) {
|
||||
@Override
|
||||
protected String toString(byte[] value) {
|
||||
assert value != null;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("binary(");
|
||||
for (int i = 0; i < value.length; i++) {
|
||||
if (i > 0) {
|
||||
sb.append(' ');
|
||||
}
|
||||
sb.append(Integer.toHexString(value[i] & 0xFF));
|
||||
}
|
||||
sb.append(')');
|
||||
return sb.toString();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,14 +16,23 @@
|
|||
*/
|
||||
package org.apache.lucene.document;
|
||||
|
||||
import org.apache.lucene.search.PointRangeQuery;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.apache.lucene.util.NumericUtils;
|
||||
|
||||
/** A double field that is indexed dimensionally such that finding
|
||||
* all documents within an N-dimensional shape or range at search time is
|
||||
* efficient. Multiple values for the same field in one documents
|
||||
* is allowed. */
|
||||
|
||||
/**
|
||||
* A double field that is indexed dimensionally such that finding
|
||||
* all documents within an N-dimensional shape or range at search time is
|
||||
* efficient. Multiple values for the same field in one documents
|
||||
* is allowed.
|
||||
* <p>
|
||||
* This field defines static factory methods for creating common queries:
|
||||
* <ul>
|
||||
* <li>{@link #newExactQuery newExactQuery()} for matching an exact 1D point.
|
||||
* <li>{@link #newRangeQuery newRangeQuery()} for matching a 1D range.
|
||||
* <li>{@link #newMultiRangeQuery newMultiRangeQuery()} for matching points/ranges in n-dimensional space.
|
||||
* </ul>
|
||||
*/
|
||||
public final class DoublePoint extends Field {
|
||||
|
||||
private static FieldType getType(int numDims) {
|
||||
|
@ -78,7 +87,7 @@ public final class DoublePoint extends Field {
|
|||
}
|
||||
|
||||
/** Creates a new DoublePoint, indexing the
|
||||
* provided N-dimensional int point.
|
||||
* provided N-dimensional double point.
|
||||
*
|
||||
* @param name field name
|
||||
* @param point double[] value
|
||||
|
@ -108,10 +117,8 @@ public final class DoublePoint extends Field {
|
|||
return result.toString();
|
||||
}
|
||||
|
||||
// public helper methods (e.g. for queries)
|
||||
|
||||
/** Encode n-dimensional double point into binary encoding */
|
||||
public static byte[][] encode(Double value[]) {
|
||||
private static byte[][] encode(Double value[]) {
|
||||
byte[][] encoded = new byte[value.length][];
|
||||
for (int i = 0; i < value.length; i++) {
|
||||
if (value[i] != null) {
|
||||
|
@ -122,6 +129,8 @@ public final class DoublePoint extends Field {
|
|||
return encoded;
|
||||
}
|
||||
|
||||
// public helper methods (e.g. for queries)
|
||||
|
||||
/** Encode single double dimension */
|
||||
public static void encodeDimension(Double value, byte dest[], int offset) {
|
||||
NumericUtils.longToBytesDirect(NumericUtils.doubleToSortableLong(value), dest, offset);
|
||||
|
@ -131,4 +140,76 @@ public final class DoublePoint extends Field {
|
|||
public static Double decodeDimension(byte value[], int offset) {
|
||||
return NumericUtils.sortableLongToDouble(NumericUtils.bytesToLongDirect(value, offset));
|
||||
}
|
||||
|
||||
// static methods for generating queries
|
||||
|
||||
/**
|
||||
* Create a query for matching an exact double value.
|
||||
* <p>
|
||||
* This is for simple one-dimension points, for multidimensional points use
|
||||
* {@link #newMultiRangeQuery newMultiRangeQuery()} instead.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param value double value
|
||||
* @throws IllegalArgumentException if {@code field} is null.
|
||||
* @return a query matching documents with this exact value
|
||||
*/
|
||||
public static PointRangeQuery newExactQuery(String field, double value) {
|
||||
return newRangeQuery(field, value, true, value, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a range query for double values.
|
||||
* <p>
|
||||
* This is for simple one-dimension ranges, for multidimensional ranges use
|
||||
* {@link #newMultiRangeQuery newMultiRangeQuery()} instead.
|
||||
* <p>
|
||||
* You can have half-open ranges (which are in fact </≤ or >/≥ queries)
|
||||
* by setting the {@code lowerValue} or {@code upperValue} to {@code null}.
|
||||
* <p>
|
||||
* By setting inclusive ({@code lowerInclusive} or {@code upperInclusive}) to false, it will
|
||||
* match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param lowerValue lower portion of the range. {@code null} means "open".
|
||||
* @param lowerInclusive {@code true} if the lower portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @param upperValue upper portion of the range. {@code null} means "open".
|
||||
* @param upperInclusive {@code true} if the upper portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @throws IllegalArgumentException if {@code field} is null.
|
||||
* @return a query matching documents within this range.
|
||||
*/
|
||||
public static PointRangeQuery newRangeQuery(String field, Double lowerValue, boolean lowerInclusive, Double upperValue, boolean upperInclusive) {
|
||||
return newMultiRangeQuery(field,
|
||||
new Double[] { lowerValue },
|
||||
new boolean[] { lowerInclusive },
|
||||
new Double[] { upperValue },
|
||||
new boolean[] { upperInclusive });
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a multidimensional range query for double values.
|
||||
* <p>
|
||||
* You can have half-open ranges (which are in fact </≤ or >/≥ queries)
|
||||
* by setting a {@code lowerValue} element or {@code upperValue} element to {@code null}.
|
||||
* <p>
|
||||
* By setting a dimension's inclusive ({@code lowerInclusive} or {@code upperInclusive}) to false, it will
|
||||
* match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param lowerValue lower portion of the range. {@code null} values mean "open" for that dimension.
|
||||
* @param lowerInclusive {@code true} if the lower portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @param upperValue upper portion of the range. {@code null} values mean "open" for that dimension.
|
||||
* @param upperInclusive {@code true} if the upper portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @throws IllegalArgumentException if {@code field} is null, or if {@code lowerValue.length != upperValue.length}
|
||||
* @return a query matching documents within this range.
|
||||
*/
|
||||
public static PointRangeQuery newMultiRangeQuery(String field, Double[] lowerValue, boolean lowerInclusive[], Double[] upperValue, boolean upperInclusive[]) {
|
||||
PointRangeQuery.checkArgs(field, lowerValue, upperValue);
|
||||
return new PointRangeQuery(field, DoublePoint.encode(lowerValue), lowerInclusive, DoublePoint.encode(upperValue), upperInclusive) {
|
||||
@Override
|
||||
protected String toString(byte[] value) {
|
||||
return DoublePoint.decodeDimension(value, 0).toString();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,14 +16,23 @@
|
|||
*/
|
||||
package org.apache.lucene.document;
|
||||
|
||||
import org.apache.lucene.search.PointRangeQuery;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.apache.lucene.util.NumericUtils;
|
||||
|
||||
/** A field that is indexed dimensionally such that finding
|
||||
* all documents within an N-dimensional at search time is
|
||||
* efficient. Multiple values for the same field in one documents
|
||||
* is allowed. */
|
||||
|
||||
/**
|
||||
* A float field that is indexed dimensionally such that finding
|
||||
* all documents within an N-dimensional at search time is
|
||||
* efficient. Multiple values for the same field in one documents
|
||||
* is allowed.
|
||||
* <p>
|
||||
* This field defines static factory methods for creating common queries:
|
||||
* <ul>
|
||||
* <li>{@link #newExactQuery newExactQuery()} for matching an exact 1D point.
|
||||
* <li>{@link #newRangeQuery newRangeQuery()} for matching a 1D range.
|
||||
* <li>{@link #newMultiRangeQuery newMultiRangeQuery()} for matching points/ranges in n-dimensional space.
|
||||
* </ul>
|
||||
*/
|
||||
public final class FloatPoint extends Field {
|
||||
|
||||
private static FieldType getType(int numDims) {
|
||||
|
@ -81,7 +90,7 @@ public final class FloatPoint extends Field {
|
|||
* provided N-dimensional float point.
|
||||
*
|
||||
* @param name field name
|
||||
* @param point int[] value
|
||||
* @param point float[] value
|
||||
* @throws IllegalArgumentException if the field name or value is null.
|
||||
*/
|
||||
public FloatPoint(String name, float... point) {
|
||||
|
@ -108,10 +117,8 @@ public final class FloatPoint extends Field {
|
|||
return result.toString();
|
||||
}
|
||||
|
||||
// public helper methods (e.g. for queries)
|
||||
|
||||
/** Encode n-dimensional float values into binary encoding */
|
||||
public static byte[][] encode(Float value[]) {
|
||||
private static byte[][] encode(Float value[]) {
|
||||
byte[][] encoded = new byte[value.length][];
|
||||
for (int i = 0; i < value.length; i++) {
|
||||
if (value[i] != null) {
|
||||
|
@ -122,6 +129,8 @@ public final class FloatPoint extends Field {
|
|||
return encoded;
|
||||
}
|
||||
|
||||
// public helper methods (e.g. for queries)
|
||||
|
||||
/** Encode single float dimension */
|
||||
public static void encodeDimension(Float value, byte dest[], int offset) {
|
||||
NumericUtils.intToBytesDirect(NumericUtils.floatToSortableInt(value), dest, offset);
|
||||
|
@ -131,4 +140,76 @@ public final class FloatPoint extends Field {
|
|||
public static Float decodeDimension(byte value[], int offset) {
|
||||
return NumericUtils.sortableIntToFloat(NumericUtils.bytesToIntDirect(value, offset));
|
||||
}
|
||||
|
||||
// static methods for generating queries
|
||||
|
||||
/**
|
||||
* Create a query for matching an exact float value.
|
||||
* <p>
|
||||
* This is for simple one-dimension points, for multidimensional points use
|
||||
* {@link #newMultiRangeQuery newMultiRangeQuery()} instead.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param value float value
|
||||
* @throws IllegalArgumentException if {@code field} is null.
|
||||
* @return a query matching documents with this exact value
|
||||
*/
|
||||
public static PointRangeQuery newExactQuery(String field, float value) {
|
||||
return newRangeQuery(field, value, true, value, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a range query for float values.
|
||||
* <p>
|
||||
* This is for simple one-dimension ranges, for multidimensional ranges use
|
||||
* {@link #newMultiRangeQuery newMultiRangeQuery()} instead.
|
||||
* <p>
|
||||
* You can have half-open ranges (which are in fact </≤ or >/≥ queries)
|
||||
* by setting the {@code lowerValue} or {@code upperValue} to {@code null}.
|
||||
* <p>
|
||||
* By setting inclusive ({@code lowerInclusive} or {@code upperInclusive}) to false, it will
|
||||
* match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param lowerValue lower portion of the range. {@code null} means "open".
|
||||
* @param lowerInclusive {@code true} if the lower portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @param upperValue upper portion of the range. {@code null} means "open".
|
||||
* @param upperInclusive {@code true} if the upper portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @throws IllegalArgumentException if {@code field} is null.
|
||||
* @return a query matching documents within this range.
|
||||
*/
|
||||
public static PointRangeQuery newRangeQuery(String field, Float lowerValue, boolean lowerInclusive, Float upperValue, boolean upperInclusive) {
|
||||
return newMultiRangeQuery(field,
|
||||
new Float[] { lowerValue },
|
||||
new boolean[] { lowerInclusive },
|
||||
new Float[] { upperValue },
|
||||
new boolean[] { upperInclusive });
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a multidimensional range query for float values.
|
||||
* <p>
|
||||
* You can have half-open ranges (which are in fact </≤ or >/≥ queries)
|
||||
* by setting a {@code lowerValue} element or {@code upperValue} element to {@code null}.
|
||||
* <p>
|
||||
* By setting a dimension's inclusive ({@code lowerInclusive} or {@code upperInclusive}) to false, it will
|
||||
* match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param lowerValue lower portion of the range. {@code null} values mean "open" for that dimension.
|
||||
* @param lowerInclusive {@code true} if the lower portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @param upperValue upper portion of the range. {@code null} values mean "open" for that dimension.
|
||||
* @param upperInclusive {@code true} if the upper portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @throws IllegalArgumentException if {@code field} is null, or if {@code lowerValue.length != upperValue.length}
|
||||
* @return a query matching documents within this range.
|
||||
*/
|
||||
public static PointRangeQuery newMultiRangeQuery(String field, Float[] lowerValue, boolean lowerInclusive[], Float[] upperValue, boolean upperInclusive[]) {
|
||||
PointRangeQuery.checkArgs(field, lowerValue, upperValue);
|
||||
return new PointRangeQuery(field, FloatPoint.encode(lowerValue), lowerInclusive, FloatPoint.encode(upperValue), upperInclusive) {
|
||||
@Override
|
||||
protected String toString(byte[] value) {
|
||||
return FloatPoint.decodeDimension(value, 0).toString();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,15 +20,24 @@ import java.io.IOException;
|
|||
import java.util.Arrays;
|
||||
|
||||
import org.apache.lucene.search.PointInSetQuery;
|
||||
import org.apache.lucene.search.PointRangeQuery;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.apache.lucene.util.BytesRefIterator;
|
||||
import org.apache.lucene.util.NumericUtils;
|
||||
|
||||
/** An int field that is indexed dimensionally such that finding
|
||||
* all documents within an N-dimensional shape or range at search time is
|
||||
* efficient. Multiple values for the same field in one documents
|
||||
* is allowed. */
|
||||
|
||||
/**
|
||||
* An int field that is indexed dimensionally such that finding
|
||||
* all documents within an N-dimensional shape or range at search time is
|
||||
* efficient. Multiple values for the same field in one documents
|
||||
* is allowed.
|
||||
* <p>
|
||||
* This field defines static factory methods for creating common queries:
|
||||
* <ul>
|
||||
* <li>{@link #newExactQuery newExactQuery()} for matching an exact 1D point.
|
||||
* <li>{@link #newRangeQuery newRangeQuery()} for matching a 1D range.
|
||||
* <li>{@link #newMultiRangeQuery newMultiRangeQuery()} for matching points/ranges in n-dimensional space.
|
||||
* </ul>
|
||||
*/
|
||||
public final class IntPoint extends Field {
|
||||
|
||||
private static FieldType getType(int numDims) {
|
||||
|
@ -93,7 +102,128 @@ public final class IntPoint extends Field {
|
|||
super(name, pack(point), getType(point.length));
|
||||
}
|
||||
|
||||
/** Returns a query efficiently finding all documents that indexed the provided 1D int values */
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder result = new StringBuilder();
|
||||
result.append(type.toString());
|
||||
result.append('<');
|
||||
result.append(name);
|
||||
result.append(':');
|
||||
|
||||
BytesRef bytes = (BytesRef) fieldsData;
|
||||
for (int dim = 0; dim < type.pointDimensionCount(); dim++) {
|
||||
if (dim > 0) {
|
||||
result.append(',');
|
||||
}
|
||||
result.append(decodeDimension(bytes.bytes, bytes.offset + dim * Integer.BYTES));
|
||||
}
|
||||
|
||||
result.append('>');
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/** Encode n-dimensional integer values into binary encoding */
|
||||
private static byte[][] encode(Integer value[]) {
|
||||
byte[][] encoded = new byte[value.length][];
|
||||
for (int i = 0; i < value.length; i++) {
|
||||
if (value[i] != null) {
|
||||
encoded[i] = new byte[Integer.BYTES];
|
||||
encodeDimension(value[i], encoded[i], 0);
|
||||
}
|
||||
}
|
||||
return encoded;
|
||||
}
|
||||
|
||||
// public helper methods (e.g. for queries)
|
||||
|
||||
/** Encode single integer dimension */
|
||||
public static void encodeDimension(Integer value, byte dest[], int offset) {
|
||||
NumericUtils.intToBytes(value, dest, offset);
|
||||
}
|
||||
|
||||
/** Decode single integer dimension */
|
||||
public static Integer decodeDimension(byte value[], int offset) {
|
||||
return NumericUtils.bytesToInt(value, offset);
|
||||
}
|
||||
|
||||
// static methods for generating queries
|
||||
|
||||
/**
|
||||
* Create a query for matching an exact integer value.
|
||||
* <p>
|
||||
* This is for simple one-dimension points, for multidimensional points use
|
||||
* {@link #newMultiRangeQuery newMultiRangeQuery()} instead.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param value exact value
|
||||
* @throws IllegalArgumentException if {@code field} is null.
|
||||
* @return a query matching documents with this exact value
|
||||
*/
|
||||
public static PointRangeQuery newExactQuery(String field, int value) {
|
||||
return newRangeQuery(field, value, true, value, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a range query for integer values.
|
||||
* <p>
|
||||
* This is for simple one-dimension ranges, for multidimensional ranges use
|
||||
* {@link #newMultiRangeQuery newMultiRangeQuery()} instead.
|
||||
* <p>
|
||||
* You can have half-open ranges (which are in fact </≤ or >/≥ queries)
|
||||
* by setting the {@code lowerValue} or {@code upperValue} to {@code null}.
|
||||
* <p>
|
||||
* By setting inclusive ({@code lowerInclusive} or {@code upperInclusive}) to false, it will
|
||||
* match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param lowerValue lower portion of the range. {@code null} means "open".
|
||||
* @param lowerInclusive {@code true} if the lower portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @param upperValue upper portion of the range. {@code null} means "open".
|
||||
* @param upperInclusive {@code true} if the upper portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @throws IllegalArgumentException if {@code field} is null.
|
||||
* @return a query matching documents within this range.
|
||||
*/
|
||||
public static PointRangeQuery newRangeQuery(String field, Integer lowerValue, boolean lowerInclusive, Integer upperValue, boolean upperInclusive) {
|
||||
return newMultiRangeQuery(field,
|
||||
new Integer[] { lowerValue },
|
||||
new boolean[] { lowerInclusive },
|
||||
new Integer[] { upperValue },
|
||||
new boolean[] { upperInclusive });
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a multidimensional range query for integer values.
|
||||
* <p>
|
||||
* You can have half-open ranges (which are in fact </≤ or >/≥ queries)
|
||||
* by setting a {@code lowerValue} element or {@code upperValue} element to {@code null}.
|
||||
* <p>
|
||||
* By setting a dimension's inclusive ({@code lowerInclusive} or {@code upperInclusive}) to false, it will
|
||||
* match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param lowerValue lower portion of the range. {@code null} values mean "open" for that dimension.
|
||||
* @param lowerInclusive {@code true} if the lower portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @param upperValue upper portion of the range. {@code null} values mean "open" for that dimension.
|
||||
* @param upperInclusive {@code true} if the upper portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @throws IllegalArgumentException if {@code field} is null, or if {@code lowerValue.length != upperValue.length}
|
||||
* @return a query matching documents within this range.
|
||||
*/
|
||||
public static PointRangeQuery newMultiRangeQuery(String field, Integer[] lowerValue, boolean lowerInclusive[], Integer[] upperValue, boolean upperInclusive[]) {
|
||||
PointRangeQuery.checkArgs(field, lowerValue, upperValue);
|
||||
return new PointRangeQuery(field, IntPoint.encode(lowerValue), lowerInclusive, IntPoint.encode(upperValue), upperInclusive) {
|
||||
@Override
|
||||
protected String toString(byte[] value) {
|
||||
return IntPoint.decodeDimension(value, 0).toString();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a query efficiently finding all documents indexed with any of the specified 1D values.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param valuesIn all int values to search for
|
||||
*/
|
||||
public static PointInSetQuery newSetQuery(String field, int... valuesIn) throws IOException {
|
||||
|
||||
// Don't unexpectedly change the user's incoming array:
|
||||
|
@ -127,48 +257,4 @@ public final class IntPoint extends Field {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder result = new StringBuilder();
|
||||
result.append(type.toString());
|
||||
result.append('<');
|
||||
result.append(name);
|
||||
result.append(':');
|
||||
|
||||
BytesRef bytes = (BytesRef) fieldsData;
|
||||
for (int dim = 0; dim < type.pointDimensionCount(); dim++) {
|
||||
if (dim > 0) {
|
||||
result.append(',');
|
||||
}
|
||||
result.append(decodeDimension(bytes.bytes, bytes.offset + dim * Integer.BYTES));
|
||||
}
|
||||
|
||||
result.append('>');
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
// public helper methods (e.g. for queries)
|
||||
|
||||
/** Encode n-dimensional integer values into binary encoding */
|
||||
public static byte[][] encode(Integer value[]) {
|
||||
byte[][] encoded = new byte[value.length][];
|
||||
for (int i = 0; i < value.length; i++) {
|
||||
if (value[i] != null) {
|
||||
encoded[i] = new byte[Integer.BYTES];
|
||||
encodeDimension(value[i], encoded[i], 0);
|
||||
}
|
||||
}
|
||||
return encoded;
|
||||
}
|
||||
|
||||
/** Encode single integer dimension */
|
||||
public static void encodeDimension(Integer value, byte dest[], int offset) {
|
||||
NumericUtils.intToBytes(value, dest, offset);
|
||||
}
|
||||
|
||||
/** Decode single integer dimension */
|
||||
public static Integer decodeDimension(byte value[], int offset) {
|
||||
return NumericUtils.bytesToInt(value, offset);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,14 +16,23 @@
|
|||
*/
|
||||
package org.apache.lucene.document;
|
||||
|
||||
import org.apache.lucene.search.PointRangeQuery;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.apache.lucene.util.NumericUtils;
|
||||
|
||||
/** A long field that is indexed dimensionally such that finding
|
||||
* all documents within an N-dimensional shape or range at search time is
|
||||
* efficient. Multiple values for the same field in one documents
|
||||
* is allowed. */
|
||||
|
||||
/**
|
||||
* A long field that is indexed dimensionally such that finding
|
||||
* all documents within an N-dimensional shape or range at search time is
|
||||
* efficient. Multiple values for the same field in one documents
|
||||
* is allowed.
|
||||
* <p>
|
||||
* This field defines static factory methods for creating common queries:
|
||||
* <ul>
|
||||
* <li>{@link #newExactQuery newExactQuery()} for matching an exact 1D point.
|
||||
* <li>{@link #newRangeQuery newRangeQuery()} for matching a 1D range.
|
||||
* <li>{@link #newMultiRangeQuery newMultiRangeQuery()} for matching points/ranges in n-dimensional space.
|
||||
* </ul>
|
||||
*/
|
||||
public final class LongPoint extends Field {
|
||||
|
||||
private static FieldType getType(int numDims) {
|
||||
|
@ -78,10 +87,10 @@ public final class LongPoint extends Field {
|
|||
}
|
||||
|
||||
/** Creates a new LongPoint, indexing the
|
||||
* provided N-dimensional int point.
|
||||
* provided N-dimensional long point.
|
||||
*
|
||||
* @param name field name
|
||||
* @param point int[] value
|
||||
* @param point long[] value
|
||||
* @throws IllegalArgumentException if the field name or value is null.
|
||||
*/
|
||||
public LongPoint(String name, long... point) {
|
||||
|
@ -108,10 +117,8 @@ public final class LongPoint extends Field {
|
|||
return result.toString();
|
||||
}
|
||||
|
||||
// public helper methods (e.g. for queries)
|
||||
|
||||
/** Encode n-dimensional long values into binary encoding */
|
||||
public static byte[][] encode(Long value[]) {
|
||||
private static byte[][] encode(Long value[]) {
|
||||
byte[][] encoded = new byte[value.length][];
|
||||
for (int i = 0; i < value.length; i++) {
|
||||
if (value[i] != null) {
|
||||
|
@ -122,6 +129,8 @@ public final class LongPoint extends Field {
|
|||
return encoded;
|
||||
}
|
||||
|
||||
// public helper methods (e.g. for queries)
|
||||
|
||||
/** Encode single long dimension */
|
||||
public static void encodeDimension(Long value, byte dest[], int offset) {
|
||||
NumericUtils.longToBytes(value, dest, offset);
|
||||
|
@ -131,4 +140,76 @@ public final class LongPoint extends Field {
|
|||
public static Long decodeDimension(byte value[], int offset) {
|
||||
return NumericUtils.bytesToLong(value, offset);
|
||||
}
|
||||
|
||||
// static methods for generating queries
|
||||
|
||||
/**
|
||||
* Create a query for matching an exact long value.
|
||||
* <p>
|
||||
* This is for simple one-dimension points, for multidimensional points use
|
||||
* {@link #newMultiRangeQuery newMultiRangeQuery()} instead.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param value exact value
|
||||
* @throws IllegalArgumentException if {@code field} is null.
|
||||
* @return a query matching documents with this exact value
|
||||
*/
|
||||
public static PointRangeQuery newExactQuery(String field, long value) {
|
||||
return newRangeQuery(field, value, true, value, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a range query for long values.
|
||||
* <p>
|
||||
* This is for simple one-dimension ranges, for multidimensional ranges use
|
||||
* {@link #newMultiRangeQuery newMultiRangeQuery()} instead.
|
||||
* <p>
|
||||
* You can have half-open ranges (which are in fact </≤ or >/≥ queries)
|
||||
* by setting the {@code lowerValue} or {@code upperValue} to {@code null}.
|
||||
* <p>
|
||||
* By setting inclusive ({@code lowerInclusive} or {@code upperInclusive}) to false, it will
|
||||
* match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param lowerValue lower portion of the range. {@code null} means "open".
|
||||
* @param lowerInclusive {@code true} if the lower portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @param upperValue upper portion of the range. {@code null} means "open".
|
||||
* @param upperInclusive {@code true} if the upper portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @throws IllegalArgumentException if {@code field} is null.
|
||||
* @return a query matching documents within this range.
|
||||
*/
|
||||
public static PointRangeQuery newRangeQuery(String field, Long lowerValue, boolean lowerInclusive, Long upperValue, boolean upperInclusive) {
|
||||
return newMultiRangeQuery(field,
|
||||
new Long[] { lowerValue },
|
||||
new boolean[] { lowerInclusive },
|
||||
new Long[] { upperValue },
|
||||
new boolean[] { upperInclusive });
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a multidimensional range query for long values.
|
||||
* <p>
|
||||
* You can have half-open ranges (which are in fact </≤ or >/≥ queries)
|
||||
* by setting a {@code lowerValue} element or {@code upperValue} element to {@code null}.
|
||||
* <p>
|
||||
* By setting a dimension's inclusive ({@code lowerInclusive} or {@code upperInclusive}) to false, it will
|
||||
* match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param lowerValue lower portion of the range. {@code null} values mean "open" for that dimension.
|
||||
* @param lowerInclusive {@code true} if the lower portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @param upperValue upper portion of the range. {@code null} values mean "open" for that dimension.
|
||||
* @param upperInclusive {@code true} if the upper portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @throws IllegalArgumentException if {@code field} is null, or if {@code lowerValue.length != upperValue.length}
|
||||
* @return a query matching documents within this range.
|
||||
*/
|
||||
public static PointRangeQuery newMultiRangeQuery(String field, Long[] lowerValue, boolean lowerInclusive[], Long[] upperValue, boolean upperInclusive[]) {
|
||||
PointRangeQuery.checkArgs(field, lowerValue, upperValue);
|
||||
return new PointRangeQuery(field, LongPoint.encode(lowerValue), lowerInclusive, LongPoint.encode(upperValue), upperInclusive) {
|
||||
@Override
|
||||
protected String toString(byte[] value) {
|
||||
return LongPoint.decodeDimension(value, 0).toString();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,11 +24,11 @@ import java.util.Objects;
|
|||
import org.apache.lucene.index.PointValues;
|
||||
import org.apache.lucene.index.PointValues.IntersectVisitor;
|
||||
import org.apache.lucene.index.PointValues.Relation;
|
||||
import org.apache.lucene.document.BinaryPoint;
|
||||
import org.apache.lucene.document.DoublePoint;
|
||||
import org.apache.lucene.document.FloatPoint;
|
||||
import org.apache.lucene.document.IntPoint;
|
||||
import org.apache.lucene.document.LongPoint;
|
||||
import org.apache.lucene.document.BinaryPoint; // javadocs
|
||||
import org.apache.lucene.document.DoublePoint; // javadocs
|
||||
import org.apache.lucene.document.FloatPoint; // javadocs
|
||||
import org.apache.lucene.document.IntPoint; // javadocs
|
||||
import org.apache.lucene.document.LongPoint; // javadocs
|
||||
import org.apache.lucene.index.FieldInfo;
|
||||
import org.apache.lucene.index.LeafReader;
|
||||
import org.apache.lucene.index.LeafReaderContext;
|
||||
|
@ -36,11 +36,23 @@ import org.apache.lucene.util.DocIdSetBuilder;
|
|||
import org.apache.lucene.util.NumericUtils;
|
||||
import org.apache.lucene.util.StringHelper;
|
||||
|
||||
/** Searches for ranges in fields previously indexed using points e.g.
|
||||
* {@link org.apache.lucene.document.LongPoint}. In a 1D field this is
|
||||
* a simple range query; in a multi-dimensional field it's a box shape. */
|
||||
// TODO: enhance this and add simple example
|
||||
public class PointRangeQuery extends Query {
|
||||
/**
|
||||
* Abstract class for range queries against single or multidimensional points such as
|
||||
* {@link IntPoint}.
|
||||
* <p>
|
||||
* This is for subclasses and works on the underlying binary encoding: to
|
||||
* create range queries for lucene's standard {@code Point} types, refer to factory
|
||||
* methods on those classes, e.g. {@link IntPoint#newRangeQuery IntPoint.newRangeQuery()} for
|
||||
* fields indexed with {@link IntPoint}.
|
||||
* <p>
|
||||
* For a single-dimensional field this query is a simple range query; in a multi-dimensional field it's a box shape.
|
||||
* @see IntPoint
|
||||
* @see LongPoint
|
||||
* @see FloatPoint
|
||||
* @see DoublePoint
|
||||
* @see BinaryPoint
|
||||
*/
|
||||
public abstract class PointRangeQuery extends Query {
|
||||
final String field;
|
||||
final int numDims;
|
||||
final byte[][] lowerPoint;
|
||||
|
@ -53,16 +65,6 @@ public class PointRangeQuery extends Query {
|
|||
/**
|
||||
* Expert: create a multidimensional range query for point values.
|
||||
* <p>
|
||||
* This is for subclasses and works on the underlying binary encoding: to
|
||||
* create range queries for lucene's standard {@code Point} types, refer to these factory methods:
|
||||
* <ul>
|
||||
* <li>{@link #newIntRange newIntRange()}/{@link #newMultiIntRange newMultiIntRange()} for fields indexed with {@link IntPoint}
|
||||
* <li>{@link #newIntRange newLongRange()}/{@link #newMultiIntRange newMultiLongRange()} for fields indexed with {@link LongPoint}
|
||||
* <li>{@link #newIntRange newFloatRange()}/{@link #newMultiIntRange newMultiFloatRange()} for fields indexed with {@link FloatPoint}
|
||||
* <li>{@link #newIntRange newDoubleRange()}/{@link #newMultiIntRange newMultiDoubleRange()} for fields indexed with {@link DoublePoint}
|
||||
* <li>{@link #newIntRange newBinaryRange()}/{@link #newMultiIntRange newMultiBinaryRange()} for fields indexed with {@link BinaryPoint}
|
||||
* </ul>
|
||||
* <p>
|
||||
* You can have half-open ranges (which are in fact </≤ or >/≥ queries)
|
||||
* by setting a {@code lowerValue} element or {@code upperValue} element to {@code null}.
|
||||
* <p>
|
||||
|
@ -132,350 +134,6 @@ public class PointRangeQuery extends Query {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a range query for matching an exact integer value.
|
||||
* <p>
|
||||
* This is for simple one-dimension points, for multidimensional points use
|
||||
* {@link #newMultiIntRange newMultiIntRange()} instead.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param value exact value
|
||||
* @throws IllegalArgumentException if {@code field} is null.
|
||||
* @return a query matching documents with this exact value
|
||||
*/
|
||||
public static PointRangeQuery newIntExact(String field, int value) {
|
||||
return newIntRange(field, value, true, value, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a range query for integer values indexed with {@link IntPoint}.
|
||||
* <p>
|
||||
* This is for simple one-dimension ranges, for multidimensional ranges use
|
||||
* {@link #newMultiIntRange newMultiIntRange()} instead.
|
||||
* <p>
|
||||
* You can have half-open ranges (which are in fact </≤ or >/≥ queries)
|
||||
* by setting the {@code lowerValue} or {@code upperValue} to {@code null}.
|
||||
* <p>
|
||||
* By setting inclusive ({@code lowerInclusive} or {@code upperInclusive}) to false, it will
|
||||
* match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param lowerValue lower portion of the range. {@code null} means "open".
|
||||
* @param lowerInclusive {@code true} if the lower portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @param upperValue upper portion of the range. {@code null} means "open".
|
||||
* @param upperInclusive {@code true} if the upper portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @throws IllegalArgumentException if {@code field} is null.
|
||||
* @return a query matching documents within this range.
|
||||
*/
|
||||
public static PointRangeQuery newIntRange(String field, Integer lowerValue, boolean lowerInclusive, Integer upperValue, boolean upperInclusive) {
|
||||
return newMultiIntRange(field,
|
||||
new Integer[] { lowerValue },
|
||||
new boolean[] { lowerInclusive },
|
||||
new Integer[] { upperValue },
|
||||
new boolean[] { upperInclusive });
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a multidimensional range query for integer values indexed with {@link IntPoint}.
|
||||
* <p>
|
||||
* You can have half-open ranges (which are in fact </≤ or >/≥ queries)
|
||||
* by setting a {@code lowerValue} element or {@code upperValue} element to {@code null}.
|
||||
* <p>
|
||||
* By setting a dimension's inclusive ({@code lowerInclusive} or {@code upperInclusive}) to false, it will
|
||||
* match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param lowerValue lower portion of the range. {@code null} values mean "open" for that dimension.
|
||||
* @param lowerInclusive {@code true} if the lower portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @param upperValue upper portion of the range. {@code null} values mean "open" for that dimension.
|
||||
* @param upperInclusive {@code true} if the upper portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @throws IllegalArgumentException if {@code field} is null, or if {@code lowerValue.length != upperValue.length}
|
||||
* @return a query matching documents within this range.
|
||||
*/
|
||||
public static PointRangeQuery newMultiIntRange(String field, Integer[] lowerValue, boolean lowerInclusive[], Integer[] upperValue, boolean upperInclusive[]) {
|
||||
checkArgs(field, lowerValue, upperValue);
|
||||
return new PointRangeQuery(field, IntPoint.encode(lowerValue), lowerInclusive, IntPoint.encode(upperValue), upperInclusive) {
|
||||
@Override
|
||||
protected String toString(byte[] value) {
|
||||
return IntPoint.decodeDimension(value, 0).toString();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a range query for matching an exact long value.
|
||||
* <p>
|
||||
* This is for simple one-dimension points, for multidimensional points use
|
||||
* {@link #newMultiLongRange newMultiLongRange()} instead.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param value exact value
|
||||
* @throws IllegalArgumentException if {@code field} is null.
|
||||
* @return a query matching documents with this exact value
|
||||
*/
|
||||
public static PointRangeQuery newLongExact(String field, long value) {
|
||||
return newLongRange(field, value, true, value, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a range query for long values indexed with {@link LongPoint}.
|
||||
* <p>
|
||||
* This is for simple one-dimension ranges, for multidimensional ranges use
|
||||
* {@link #newMultiLongRange newMultiLongRange()} instead.
|
||||
* <p>
|
||||
* You can have half-open ranges (which are in fact </≤ or >/≥ queries)
|
||||
* by setting the {@code lowerValue} or {@code upperValue} to {@code null}.
|
||||
* <p>
|
||||
* By setting inclusive ({@code lowerInclusive} or {@code upperInclusive}) to false, it will
|
||||
* match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param lowerValue lower portion of the range. {@code null} means "open".
|
||||
* @param lowerInclusive {@code true} if the lower portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @param upperValue upper portion of the range. {@code null} means "open".
|
||||
* @param upperInclusive {@code true} if the upper portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @throws IllegalArgumentException if {@code field} is null.
|
||||
* @return a query matching documents within this range.
|
||||
*/
|
||||
public static PointRangeQuery newLongRange(String field, Long lowerValue, boolean lowerInclusive, Long upperValue, boolean upperInclusive) {
|
||||
return newMultiLongRange(field,
|
||||
new Long[] { lowerValue },
|
||||
new boolean[] { lowerInclusive },
|
||||
new Long[] { upperValue },
|
||||
new boolean[] { upperInclusive });
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a multidimensional range query for long values indexed with {@link LongPoint}.
|
||||
* <p>
|
||||
* You can have half-open ranges (which are in fact </≤ or >/≥ queries)
|
||||
* by setting a {@code lowerValue} element or {@code upperValue} element to {@code null}.
|
||||
* <p>
|
||||
* By setting a dimension's inclusive ({@code lowerInclusive} or {@code upperInclusive}) to false, it will
|
||||
* match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param lowerValue lower portion of the range. {@code null} values mean "open" for that dimension.
|
||||
* @param lowerInclusive {@code true} if the lower portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @param upperValue upper portion of the range. {@code null} values mean "open" for that dimension.
|
||||
* @param upperInclusive {@code true} if the upper portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @throws IllegalArgumentException if {@code field} is null, or if {@code lowerValue.length != upperValue.length}
|
||||
* @return a query matching documents within this range.
|
||||
*/
|
||||
public static PointRangeQuery newMultiLongRange(String field, Long[] lowerValue, boolean lowerInclusive[], Long[] upperValue, boolean upperInclusive[]) {
|
||||
checkArgs(field, lowerValue, upperValue);
|
||||
return new PointRangeQuery(field, LongPoint.encode(lowerValue), lowerInclusive, LongPoint.encode(upperValue), upperInclusive) {
|
||||
@Override
|
||||
protected String toString(byte[] value) {
|
||||
return LongPoint.decodeDimension(value, 0).toString();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a range query for matching an exact float value.
|
||||
* <p>
|
||||
* This is for simple one-dimension points, for multidimensional points use
|
||||
* {@link #newMultiFloatRange newMultiFloatRange()} instead.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param value float value
|
||||
* @throws IllegalArgumentException if {@code field} is null.
|
||||
* @return a query matching documents with this exact value
|
||||
*/
|
||||
public static PointRangeQuery newFloatExact(String field, float value) {
|
||||
return newFloatRange(field, value, true, value, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a range query for float values indexed with {@link FloatPoint}.
|
||||
* <p>
|
||||
* This is for simple one-dimension ranges, for multidimensional ranges use
|
||||
* {@link #newMultiFloatRange newMultiFloatRange()} instead.
|
||||
* <p>
|
||||
* You can have half-open ranges (which are in fact </≤ or >/≥ queries)
|
||||
* by setting the {@code lowerValue} or {@code upperValue} to {@code null}.
|
||||
* <p>
|
||||
* By setting inclusive ({@code lowerInclusive} or {@code upperInclusive}) to false, it will
|
||||
* match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param lowerValue lower portion of the range. {@code null} means "open".
|
||||
* @param lowerInclusive {@code true} if the lower portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @param upperValue upper portion of the range. {@code null} means "open".
|
||||
* @param upperInclusive {@code true} if the upper portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @throws IllegalArgumentException if {@code field} is null.
|
||||
* @return a query matching documents within this range.
|
||||
*/
|
||||
public static PointRangeQuery newFloatRange(String field, Float lowerValue, boolean lowerInclusive, Float upperValue, boolean upperInclusive) {
|
||||
return newMultiFloatRange(field,
|
||||
new Float[] { lowerValue },
|
||||
new boolean[] { lowerInclusive },
|
||||
new Float[] { upperValue },
|
||||
new boolean[] { upperInclusive });
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a multidimensional range query for float values indexed with {@link FloatPoint}.
|
||||
* <p>
|
||||
* You can have half-open ranges (which are in fact </≤ or >/≥ queries)
|
||||
* by setting a {@code lowerValue} element or {@code upperValue} element to {@code null}.
|
||||
* <p>
|
||||
* By setting a dimension's inclusive ({@code lowerInclusive} or {@code upperInclusive}) to false, it will
|
||||
* match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param lowerValue lower portion of the range. {@code null} values mean "open" for that dimension.
|
||||
* @param lowerInclusive {@code true} if the lower portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @param upperValue upper portion of the range. {@code null} values mean "open" for that dimension.
|
||||
* @param upperInclusive {@code true} if the upper portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @throws IllegalArgumentException if {@code field} is null, or if {@code lowerValue.length != upperValue.length}
|
||||
* @return a query matching documents within this range.
|
||||
*/
|
||||
public static PointRangeQuery newMultiFloatRange(String field, Float[] lowerValue, boolean lowerInclusive[], Float[] upperValue, boolean upperInclusive[]) {
|
||||
checkArgs(field, lowerValue, upperValue);
|
||||
return new PointRangeQuery(field, FloatPoint.encode(lowerValue), lowerInclusive, FloatPoint.encode(upperValue), upperInclusive) {
|
||||
@Override
|
||||
protected String toString(byte[] value) {
|
||||
return FloatPoint.decodeDimension(value, 0).toString();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a range query for matching an exact double value.
|
||||
* <p>
|
||||
* This is for simple one-dimension points, for multidimensional points use
|
||||
* {@link #newMultiDoubleRange newMultiDoubleRange()} instead.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param value double value
|
||||
* @throws IllegalArgumentException if {@code field} is null.
|
||||
* @return a query matching documents with this exact value
|
||||
*/
|
||||
public static PointRangeQuery newDoubleExact(String field, double value) {
|
||||
return newDoubleRange(field, value, true, value, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a range query for double values indexed with {@link DoublePoint}.
|
||||
* <p>
|
||||
* This is for simple one-dimension ranges, for multidimensional ranges use
|
||||
* {@link #newMultiDoubleRange newMultiDoubleRange()} instead.
|
||||
* <p>
|
||||
* You can have half-open ranges (which are in fact </≤ or >/≥ queries)
|
||||
* by setting the {@code lowerValue} or {@code upperValue} to {@code null}.
|
||||
* <p>
|
||||
* By setting inclusive ({@code lowerInclusive} or {@code upperInclusive}) to false, it will
|
||||
* match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param lowerValue lower portion of the range. {@code null} means "open".
|
||||
* @param lowerInclusive {@code true} if the lower portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @param upperValue upper portion of the range. {@code null} means "open".
|
||||
* @param upperInclusive {@code true} if the upper portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @throws IllegalArgumentException if {@code field} is null.
|
||||
* @return a query matching documents within this range.
|
||||
*/
|
||||
public static PointRangeQuery newDoubleRange(String field, Double lowerValue, boolean lowerInclusive, Double upperValue, boolean upperInclusive) {
|
||||
return newMultiDoubleRange(field,
|
||||
new Double[] { lowerValue },
|
||||
new boolean[] { lowerInclusive },
|
||||
new Double[] { upperValue },
|
||||
new boolean[] { upperInclusive });
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a multidimensional range query for double values indexed with {@link DoublePoint}.
|
||||
* <p>
|
||||
* You can have half-open ranges (which are in fact </≤ or >/≥ queries)
|
||||
* by setting a {@code lowerValue} element or {@code upperValue} element to {@code null}.
|
||||
* <p>
|
||||
* By setting a dimension's inclusive ({@code lowerInclusive} or {@code upperInclusive}) to false, it will
|
||||
* match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param lowerValue lower portion of the range. {@code null} values mean "open" for that dimension.
|
||||
* @param lowerInclusive {@code true} if the lower portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @param upperValue upper portion of the range. {@code null} values mean "open" for that dimension.
|
||||
* @param upperInclusive {@code true} if the upper portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @throws IllegalArgumentException if {@code field} is null, or if {@code lowerValue.length != upperValue.length}
|
||||
* @return a query matching documents within this range.
|
||||
*/
|
||||
public static PointRangeQuery newMultiDoubleRange(String field, Double[] lowerValue, boolean lowerInclusive[], Double[] upperValue, boolean upperInclusive[]) {
|
||||
checkArgs(field, lowerValue, upperValue);
|
||||
return new PointRangeQuery(field, DoublePoint.encode(lowerValue), lowerInclusive, DoublePoint.encode(upperValue), upperInclusive) {
|
||||
@Override
|
||||
protected String toString(byte[] value) {
|
||||
return DoublePoint.decodeDimension(value, 0).toString();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a range query for matching an exact binary value.
|
||||
* <p>
|
||||
* This is for simple one-dimension points, for multidimensional points use
|
||||
* {@link #newMultiBinaryRange newMultiBinaryRange()} instead.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param value binary value
|
||||
* @throws IllegalArgumentException if {@code field} is null or {@code value} is null
|
||||
* @return a query matching documents with this exact value
|
||||
*/
|
||||
public static PointRangeQuery newBinaryExact(String field, byte[] value) {
|
||||
if (value == null) {
|
||||
throw new IllegalArgumentException("value cannot be null");
|
||||
}
|
||||
return newBinaryRange(field, value, true, value, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a range query for binary values indexed with {@link BinaryPoint}.
|
||||
* <p>
|
||||
* This is for simple one-dimension ranges, for multidimensional ranges use
|
||||
* {@link #newMultiBinaryRange newMultiBinaryRange()} instead.
|
||||
* <p>
|
||||
* You can have half-open ranges (which are in fact </≤ or >/≥ queries)
|
||||
* by setting the {@code lowerValue} or {@code upperValue} to {@code null}.
|
||||
* <p>
|
||||
* By setting inclusive ({@code lowerInclusive} or {@code upperInclusive}) to false, it will
|
||||
* match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param lowerValue lower portion of the range. {@code null} means "open".
|
||||
* @param lowerInclusive {@code true} if the lower portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @param upperValue upper portion of the range. {@code null} means "open".
|
||||
* @param upperInclusive {@code true} if the upper portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @throws IllegalArgumentException if {@code field} is null.
|
||||
* @return a query matching documents within this range.
|
||||
*/
|
||||
public static PointRangeQuery newBinaryRange(String field, byte[] lowerValue, boolean lowerInclusive, byte[] upperValue, boolean upperInclusive) {
|
||||
return newMultiBinaryRange(field, new byte[][] {lowerValue}, new boolean[] {lowerInclusive}, new byte[][] {upperValue}, new boolean[] {upperInclusive});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a multidimensional range query for binary values indexed with {@link BinaryPoint}.
|
||||
* <p>
|
||||
* You can have half-open ranges (which are in fact </≤ or >/≥ queries)
|
||||
* by setting a {@code lowerValue} element or {@code upperValue} element to {@code null}.
|
||||
* <p>
|
||||
* By setting a dimension's inclusive ({@code lowerInclusive} or {@code upperInclusive}) to false, it will
|
||||
* match all documents excluding the bounds, with inclusive on, the boundaries are hits, too.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param lowerValue lower portion of the range. {@code null} values mean "open" for that dimension.
|
||||
* @param lowerInclusive {@code true} if the lower portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @param upperValue upper portion of the range. {@code null} values mean "open" for that dimension.
|
||||
* @param upperInclusive {@code true} if the upper portion of the range is inclusive, {@code false} if it should be excluded.
|
||||
* @throws IllegalArgumentException if {@code field} is null, or if {@code lowerValue.length != upperValue.length}
|
||||
* @return a query matching documents within this range.
|
||||
*/
|
||||
public static PointRangeQuery newMultiBinaryRange(String field, byte[][] lowerValue, boolean[] lowerInclusive, byte[][] upperValue, boolean[] upperInclusive) {
|
||||
checkArgs(field, lowerValue, upperValue);
|
||||
return new PointRangeQuery(field, lowerValue, lowerInclusive, upperValue, upperInclusive);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Weight createWeight(IndexSearcher searcher, boolean needsScores) throws IOException {
|
||||
|
||||
|
@ -695,22 +353,8 @@ public class PointRangeQuery extends Query {
|
|||
* Returns a string of a single value in a human-readable format for debugging.
|
||||
* This is used by {@link #toString()}.
|
||||
*
|
||||
* The default implementation encodes the individual byte values.
|
||||
*
|
||||
* @param value single value, never null
|
||||
* @return human readable value for debugging
|
||||
*/
|
||||
protected String toString(byte[] value) {
|
||||
assert value != null;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("binary(");
|
||||
for (int i = 0; i < value.length; i++) {
|
||||
if (i > 0) {
|
||||
sb.append(' ');
|
||||
}
|
||||
sb.append(Integer.toHexString(value[i] & 0xFF));
|
||||
}
|
||||
sb.append(')');
|
||||
return sb.toString();
|
||||
}
|
||||
protected abstract String toString(byte[] value);
|
||||
}
|
||||
|
|
|
@ -36,7 +36,6 @@ import org.apache.lucene.document.LongPoint;
|
|||
import org.apache.lucene.document.Document;
|
||||
import org.apache.lucene.document.Field;
|
||||
import org.apache.lucene.document.NumericDocValuesField;
|
||||
import org.apache.lucene.search.PointRangeQuery;
|
||||
import org.apache.lucene.search.IndexSearcher;
|
||||
import org.apache.lucene.search.MatchAllDocsQuery;
|
||||
import org.apache.lucene.search.ScoreDoc;
|
||||
|
@ -1352,7 +1351,7 @@ public class TestDemoParallelLeafReader extends LuceneTestCase {
|
|||
max = x;
|
||||
}
|
||||
|
||||
TopDocs hits = s.search(PointRangeQuery.newLongRange("number", min, true, max, true), 100);
|
||||
TopDocs hits = s.search(LongPoint.newRangeQuery("number", min, true, max, true), 100);
|
||||
for(ScoreDoc scoreDoc : hits.scoreDocs) {
|
||||
long value = Long.parseLong(s.doc(scoreDoc.doc).get("text").split(" ")[1]);
|
||||
assertTrue(value >= min);
|
||||
|
|
|
@ -304,7 +304,7 @@ public class TestPointQueries extends LuceneTestCase {
|
|||
}
|
||||
|
||||
if (random().nextBoolean()) {
|
||||
query = PointRangeQuery.newLongRange("sn_value", lower, includeLower, upper, includeUpper);
|
||||
query = LongPoint.newRangeQuery("sn_value", lower, includeLower, upper, includeUpper);
|
||||
} else {
|
||||
byte[] lowerBytes;
|
||||
if (lower == null) {
|
||||
|
@ -320,7 +320,7 @@ public class TestPointQueries extends LuceneTestCase {
|
|||
upperBytes = new byte[8];
|
||||
NumericUtils.longToBytes(upper, upperBytes, 0);
|
||||
}
|
||||
query = PointRangeQuery.newBinaryRange("ss_value", lowerBytes, includeLower, upperBytes, includeUpper);
|
||||
query = BinaryPoint.newRangeQuery("ss_value", lowerBytes, includeLower, upperBytes, includeUpper);
|
||||
}
|
||||
|
||||
if (VERBOSE) {
|
||||
|
@ -586,7 +586,7 @@ public class TestPointQueries extends LuceneTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
Query query = new PointRangeQuery("value", lower, includeLower, upper, includeUpper);
|
||||
Query query = BinaryPoint.newMultiRangeQuery("value", lower, includeLower, upper, includeUpper);
|
||||
|
||||
if (VERBOSE) {
|
||||
System.out.println(Thread.currentThread().getName() + ": using query: " + query);
|
||||
|
@ -736,9 +736,9 @@ public class TestPointQueries extends LuceneTestCase {
|
|||
|
||||
IndexSearcher s = newSearcher(r);
|
||||
|
||||
assertEquals(1, s.count(PointRangeQuery.newLongRange("value", Long.MIN_VALUE, true, 0L, true)));
|
||||
assertEquals(1, s.count(PointRangeQuery.newLongRange("value", 0L, true, Long.MAX_VALUE, true)));
|
||||
assertEquals(2, s.count(PointRangeQuery.newLongRange("value", Long.MIN_VALUE, true, Long.MAX_VALUE, true)));
|
||||
assertEquals(1, s.count(LongPoint.newRangeQuery("value", Long.MIN_VALUE, true, 0L, true)));
|
||||
assertEquals(1, s.count(LongPoint.newRangeQuery("value", 0L, true, Long.MAX_VALUE, true)));
|
||||
assertEquals(2, s.count(LongPoint.newRangeQuery("value", Long.MIN_VALUE, true, Long.MAX_VALUE, true)));
|
||||
|
||||
IOUtils.close(r, w, dir);
|
||||
}
|
||||
|
@ -774,47 +774,47 @@ public class TestPointQueries extends LuceneTestCase {
|
|||
|
||||
IndexSearcher s = newSearcher(r);
|
||||
|
||||
assertEquals(1, s.count(PointRangeQuery.newBinaryRange("value",
|
||||
assertEquals(1, s.count(BinaryPoint.newRangeQuery("value",
|
||||
toUTF8("aaa"),
|
||||
true,
|
||||
toUTF8("bbb"),
|
||||
true)));
|
||||
assertEquals(1, s.count(PointRangeQuery.newBinaryRange("value",
|
||||
assertEquals(1, s.count(BinaryPoint.newRangeQuery("value",
|
||||
toUTF8("c", 3),
|
||||
true,
|
||||
toUTF8("e", 3),
|
||||
true)));
|
||||
assertEquals(2, s.count(PointRangeQuery.newBinaryRange("value",
|
||||
assertEquals(2, s.count(BinaryPoint.newRangeQuery("value",
|
||||
toUTF8("a", 3),
|
||||
true,
|
||||
toUTF8("z", 3),
|
||||
true)));
|
||||
assertEquals(1, s.count(PointRangeQuery.newBinaryRange("value",
|
||||
assertEquals(1, s.count(BinaryPoint.newRangeQuery("value",
|
||||
null,
|
||||
true,
|
||||
toUTF8("abc"),
|
||||
true)));
|
||||
assertEquals(1, s.count(PointRangeQuery.newBinaryRange("value",
|
||||
assertEquals(1, s.count(BinaryPoint.newRangeQuery("value",
|
||||
toUTF8("a", 3),
|
||||
true,
|
||||
toUTF8("abc"),
|
||||
true)));
|
||||
assertEquals(0, s.count(PointRangeQuery.newBinaryRange("value",
|
||||
assertEquals(0, s.count(BinaryPoint.newRangeQuery("value",
|
||||
toUTF8("a", 3),
|
||||
true,
|
||||
toUTF8("abc"),
|
||||
false)));
|
||||
assertEquals(1, s.count(PointRangeQuery.newBinaryRange("value",
|
||||
assertEquals(1, s.count(BinaryPoint.newRangeQuery("value",
|
||||
toUTF8("def"),
|
||||
true,
|
||||
null,
|
||||
false)));
|
||||
assertEquals(1, s.count(PointRangeQuery.newBinaryRange("value",
|
||||
assertEquals(1, s.count(BinaryPoint.newRangeQuery("value",
|
||||
toUTF8(("def")),
|
||||
true,
|
||||
toUTF8("z", 3),
|
||||
true)));
|
||||
assertEquals(0, s.count(PointRangeQuery.newBinaryRange("value",
|
||||
assertEquals(0, s.count(BinaryPoint.newRangeQuery("value",
|
||||
toUTF8("def"),
|
||||
false,
|
||||
toUTF8("z", 3),
|
||||
|
@ -839,12 +839,12 @@ public class TestPointQueries extends LuceneTestCase {
|
|||
|
||||
IndexSearcher s = newSearcher(r);
|
||||
|
||||
assertEquals(2, s.count(PointRangeQuery.newLongRange("value", Long.MIN_VALUE, true, Long.MAX_VALUE, true)));
|
||||
assertEquals(1, s.count(PointRangeQuery.newLongRange("value", Long.MIN_VALUE, true, Long.MAX_VALUE, false)));
|
||||
assertEquals(1, s.count(PointRangeQuery.newLongRange("value", Long.MIN_VALUE, false, Long.MAX_VALUE, true)));
|
||||
assertEquals(0, s.count(PointRangeQuery.newLongRange("value", Long.MIN_VALUE, false, Long.MAX_VALUE, false)));
|
||||
assertEquals(2, s.count(LongPoint.newRangeQuery("value", Long.MIN_VALUE, true, Long.MAX_VALUE, true)));
|
||||
assertEquals(1, s.count(LongPoint.newRangeQuery("value", Long.MIN_VALUE, true, Long.MAX_VALUE, false)));
|
||||
assertEquals(1, s.count(LongPoint.newRangeQuery("value", Long.MIN_VALUE, false, Long.MAX_VALUE, true)));
|
||||
assertEquals(0, s.count(LongPoint.newRangeQuery("value", Long.MIN_VALUE, false, Long.MAX_VALUE, false)));
|
||||
|
||||
assertEquals(2, s.count(PointRangeQuery.newBinaryRange("value", (byte[]) null, true, null, true)));
|
||||
assertEquals(2, s.count(BinaryPoint.newRangeQuery("value", (byte[]) null, true, null, true)));
|
||||
|
||||
IOUtils.close(r, w, dir);
|
||||
}
|
||||
|
@ -866,12 +866,12 @@ public class TestPointQueries extends LuceneTestCase {
|
|||
// We can't wrap with "exotic" readers because the query must see the RangeTreeDVFormat:
|
||||
IndexSearcher s = newSearcher(r, false);
|
||||
|
||||
assertEquals(2, s.count(PointRangeQuery.newLongRange("value", Long.MIN_VALUE, true, Long.MAX_VALUE, true)));
|
||||
assertEquals(1, s.count(PointRangeQuery.newLongRange("value", Long.MIN_VALUE, true, Long.MAX_VALUE, false)));
|
||||
assertEquals(1, s.count(PointRangeQuery.newLongRange("value", Long.MIN_VALUE, false, Long.MAX_VALUE, true)));
|
||||
assertEquals(0, s.count(PointRangeQuery.newLongRange("value", Long.MIN_VALUE, false, Long.MAX_VALUE, false)));
|
||||
assertEquals(2, s.count(LongPoint.newRangeQuery("value", Long.MIN_VALUE, true, Long.MAX_VALUE, true)));
|
||||
assertEquals(1, s.count(LongPoint.newRangeQuery("value", Long.MIN_VALUE, true, Long.MAX_VALUE, false)));
|
||||
assertEquals(1, s.count(LongPoint.newRangeQuery("value", Long.MIN_VALUE, false, Long.MAX_VALUE, true)));
|
||||
assertEquals(0, s.count(LongPoint.newRangeQuery("value", Long.MIN_VALUE, false, Long.MAX_VALUE, false)));
|
||||
|
||||
assertEquals(2, s.count(PointRangeQuery.newLongRange("value", (Long) null, true, null, true)));
|
||||
assertEquals(2, s.count(LongPoint.newRangeQuery("value", (Long) null, true, null, true)));
|
||||
|
||||
IOUtils.close(r, w, dir);
|
||||
}
|
||||
|
@ -891,9 +891,9 @@ public class TestPointQueries extends LuceneTestCase {
|
|||
IndexReader r = w.getReader();
|
||||
|
||||
IndexSearcher s = newSearcher(r);
|
||||
assertEquals(0, s.count(PointRangeQuery.newBinaryRange("value", toUTF8("m"), true, toUTF8("n"), false)));
|
||||
assertEquals(0, s.count(BinaryPoint.newRangeQuery("value", toUTF8("m"), true, toUTF8("n"), false)));
|
||||
|
||||
assertEquals(2, s.count(PointRangeQuery.newBinaryRange("value", (byte[]) null, true, null, true)));
|
||||
assertEquals(2, s.count(BinaryPoint.newRangeQuery("value", (byte[]) null, true, null, true)));
|
||||
|
||||
IOUtils.close(r, w, dir);
|
||||
}
|
||||
|
@ -913,7 +913,7 @@ public class TestPointQueries extends LuceneTestCase {
|
|||
IndexReader r = w.getReader();
|
||||
|
||||
IndexSearcher s = new IndexSearcher(r);
|
||||
assertEquals(0, s.count(PointRangeQuery.newLongRange("value", 17L, true, 13L, false)));
|
||||
assertEquals(0, s.count(LongPoint.newRangeQuery("value", 17L, true, 13L, false)));
|
||||
|
||||
IOUtils.close(r, w, dir);
|
||||
}
|
||||
|
@ -928,7 +928,7 @@ public class TestPointQueries extends LuceneTestCase {
|
|||
IndexReader r = w.getReader();
|
||||
|
||||
IndexSearcher s = newSearcher(r);
|
||||
assertEquals(0, s.count(PointRangeQuery.newLongRange("value", 17L, true, 13L, false)));
|
||||
assertEquals(0, s.count(LongPoint.newRangeQuery("value", 17L, true, 13L, false)));
|
||||
|
||||
IOUtils.close(r, w, dir);
|
||||
}
|
||||
|
@ -948,7 +948,7 @@ public class TestPointQueries extends LuceneTestCase {
|
|||
IndexSearcher s = new IndexSearcher(r);
|
||||
byte[][] point = new byte[2][];
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
s.count(new PointRangeQuery("value", point, new boolean[] {true, true}, point, new boolean[] {true, true}));
|
||||
s.count(BinaryPoint.newMultiRangeQuery("value", point, new boolean[] {true, true}, point, new boolean[] {true, true}));
|
||||
});
|
||||
assertEquals("field=\"value\" was indexed with numDims=1 but this query has numDims=2", expected.getMessage());
|
||||
|
||||
|
@ -971,7 +971,7 @@ public class TestPointQueries extends LuceneTestCase {
|
|||
byte[][] point = new byte[1][];
|
||||
point[0] = new byte[10];
|
||||
IllegalArgumentException expected = expectThrows(IllegalArgumentException.class, () -> {
|
||||
s.count(new PointRangeQuery("value", point, new boolean[] {true}, point, new boolean[] {true}));
|
||||
s.count(BinaryPoint.newMultiRangeQuery("value", point, new boolean[] {true}, point, new boolean[] {true}));
|
||||
});
|
||||
assertEquals("field=\"value\" was indexed with bytesPerDim=8 but this query has bytesPerDim=10", expected.getMessage());
|
||||
|
||||
|
@ -1068,17 +1068,17 @@ public class TestPointQueries extends LuceneTestCase {
|
|||
|
||||
IndexReader r = DirectoryReader.open(w);
|
||||
IndexSearcher s = newSearcher(r);
|
||||
assertEquals(1, s.count(PointRangeQuery.newIntExact("int", 42)));
|
||||
assertEquals(0, s.count(PointRangeQuery.newIntExact("int", 41)));
|
||||
assertEquals(1, s.count(IntPoint.newExactQuery("int", 42)));
|
||||
assertEquals(0, s.count(IntPoint.newExactQuery("int", 41)));
|
||||
|
||||
assertEquals(1, s.count(PointRangeQuery.newLongExact("long", 5L)));
|
||||
assertEquals(0, s.count(PointRangeQuery.newLongExact("long", -1L)));
|
||||
assertEquals(1, s.count(LongPoint.newExactQuery("long", 5L)));
|
||||
assertEquals(0, s.count(LongPoint.newExactQuery("long", -1L)));
|
||||
|
||||
assertEquals(1, s.count(PointRangeQuery.newFloatExact("float", 2.0f)));
|
||||
assertEquals(0, s.count(PointRangeQuery.newFloatExact("float", 1.0f)));
|
||||
assertEquals(1, s.count(FloatPoint.newExactQuery("float", 2.0f)));
|
||||
assertEquals(0, s.count(FloatPoint.newExactQuery("float", 1.0f)));
|
||||
|
||||
assertEquals(1, s.count(PointRangeQuery.newDoubleExact("double", 1.0)));
|
||||
assertEquals(0, s.count(PointRangeQuery.newDoubleExact("double", 2.0)));
|
||||
assertEquals(1, s.count(DoublePoint.newExactQuery("double", 1.0)));
|
||||
assertEquals(0, s.count(DoublePoint.newExactQuery("double", 2.0)));
|
||||
w.close();
|
||||
r.close();
|
||||
dir.close();
|
||||
|
@ -1087,27 +1087,27 @@ public class TestPointQueries extends LuceneTestCase {
|
|||
public void testToString() throws Exception {
|
||||
|
||||
// ints
|
||||
assertEquals("field:[1 TO 2}", PointRangeQuery.newIntRange("field", 1, true, 2, false).toString());
|
||||
assertEquals("field:{-2 TO 1]", PointRangeQuery.newIntRange("field", -2, false, 1, true).toString());
|
||||
assertEquals("field:[* TO 2}", PointRangeQuery.newIntRange("field", null, true, 2, false).toString());
|
||||
assertEquals("field:[1 TO 2}", IntPoint.newRangeQuery("field", 1, true, 2, false).toString());
|
||||
assertEquals("field:{-2 TO 1]", IntPoint.newRangeQuery("field", -2, false, 1, true).toString());
|
||||
assertEquals("field:[* TO 2}", IntPoint.newRangeQuery("field", null, true, 2, false).toString());
|
||||
|
||||
// longs
|
||||
assertEquals("field:[1099511627776 TO 2199023255552}", PointRangeQuery.newLongRange("field", 1L<<40, true, 1L<<41, false).toString());
|
||||
assertEquals("field:{-5 TO 6]", PointRangeQuery.newLongRange("field", -5L, false, 6L, true).toString());
|
||||
assertEquals("field:[* TO 2}", PointRangeQuery.newLongRange("field", null, true, 2L, false).toString());
|
||||
assertEquals("field:[1099511627776 TO 2199023255552}", LongPoint.newRangeQuery("field", 1L<<40, true, 1L<<41, false).toString());
|
||||
assertEquals("field:{-5 TO 6]", LongPoint.newRangeQuery("field", -5L, false, 6L, true).toString());
|
||||
assertEquals("field:[* TO 2}", LongPoint.newRangeQuery("field", null, true, 2L, false).toString());
|
||||
|
||||
// floats
|
||||
assertEquals("field:[1.3 TO 2.5}", PointRangeQuery.newFloatRange("field", 1.3F, true, 2.5F, false).toString());
|
||||
assertEquals("field:{-2.9 TO 1.0]", PointRangeQuery.newFloatRange("field", -2.9F, false, 1.0F, true).toString());
|
||||
assertEquals("field:{-2.9 TO *]", PointRangeQuery.newFloatRange("field", -2.9F, false, null, true).toString());
|
||||
assertEquals("field:[1.3 TO 2.5}", FloatPoint.newRangeQuery("field", 1.3F, true, 2.5F, false).toString());
|
||||
assertEquals("field:{-2.9 TO 1.0]", FloatPoint.newRangeQuery("field", -2.9F, false, 1.0F, true).toString());
|
||||
assertEquals("field:{-2.9 TO *]", FloatPoint.newRangeQuery("field", -2.9F, false, null, true).toString());
|
||||
|
||||
// doubles
|
||||
assertEquals("field:[1.3 TO 2.5}", PointRangeQuery.newDoubleRange("field", 1.3, true, 2.5, false).toString());
|
||||
assertEquals("field:{-2.9 TO 1.0]", PointRangeQuery.newDoubleRange("field", -2.9, false, 1.0, true).toString());
|
||||
assertEquals("field:{-2.9 TO *]", PointRangeQuery.newDoubleRange("field", -2.9, false, null, true).toString());
|
||||
assertEquals("field:[1.3 TO 2.5}", DoublePoint.newRangeQuery("field", 1.3, true, 2.5, false).toString());
|
||||
assertEquals("field:{-2.9 TO 1.0]", DoublePoint.newRangeQuery("field", -2.9, false, 1.0, true).toString());
|
||||
assertEquals("field:{-2.9 TO *]", DoublePoint.newRangeQuery("field", -2.9, false, null, true).toString());
|
||||
|
||||
// n-dimensional double
|
||||
assertEquals("field:[1.3 TO 2.5},{-2.9 TO 1.0]", PointRangeQuery.newMultiDoubleRange("field",
|
||||
assertEquals("field:[1.3 TO 2.5},{-2.9 TO 1.0]", DoublePoint.newMultiRangeQuery("field",
|
||||
new Double[] { 1.3, -2.9 },
|
||||
new boolean[] { true, false },
|
||||
new Double[] { 2.5, 1.0 },
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
*/
|
||||
package org.apache.lucene.search;
|
||||
|
||||
|
||||
import org.apache.lucene.document.IntPoint;
|
||||
import org.apache.lucene.index.MultiReader;
|
||||
import org.apache.lucene.index.SlowCompositeReaderWrapper;
|
||||
import org.apache.lucene.index.Term;
|
||||
|
@ -26,7 +26,7 @@ public class TestUsageTrackingFilterCachingPolicy extends LuceneTestCase {
|
|||
|
||||
public void testCostlyFilter() {
|
||||
assertTrue(UsageTrackingQueryCachingPolicy.isCostly(new PrefixQuery(new Term("field", "prefix"))));
|
||||
assertTrue(UsageTrackingQueryCachingPolicy.isCostly(PointRangeQuery.newIntRange("intField", 1, true, 1000, true)));
|
||||
assertTrue(UsageTrackingQueryCachingPolicy.isCostly(IntPoint.newRangeQuery("intField", 1, true, 1000, true)));
|
||||
assertFalse(UsageTrackingQueryCachingPolicy.isCostly(new TermQuery(new Term("field", "value"))));
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
*/
|
||||
package org.apache.lucene.demo.facet;
|
||||
|
||||
|
||||
import org.apache.lucene.analysis.core.WhitespaceAnalyzer;
|
||||
import org.apache.lucene.document.DoublePoint;
|
||||
import org.apache.lucene.document.Document;
|
||||
|
@ -40,7 +39,6 @@ import org.apache.lucene.index.IndexWriterConfig.OpenMode;
|
|||
import org.apache.lucene.queries.function.ValueSource;
|
||||
import org.apache.lucene.search.BooleanClause;
|
||||
import org.apache.lucene.search.BooleanQuery;
|
||||
import org.apache.lucene.search.PointRangeQuery;
|
||||
import org.apache.lucene.search.IndexSearcher;
|
||||
import org.apache.lucene.search.MatchAllDocsQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
|
@ -181,7 +179,7 @@ public class DistanceFacetsExample implements Closeable {
|
|||
BooleanQuery.Builder f = new BooleanQuery.Builder();
|
||||
|
||||
// Add latitude range filter:
|
||||
f.add(PointRangeQuery.newDoubleRange("latitude", Math.toDegrees(minLat), true, Math.toDegrees(maxLat), true),
|
||||
f.add(DoublePoint.newRangeQuery("latitude", Math.toDegrees(minLat), true, Math.toDegrees(maxLat), true),
|
||||
BooleanClause.Occur.FILTER);
|
||||
|
||||
// Add longitude range filter:
|
||||
|
@ -189,13 +187,13 @@ public class DistanceFacetsExample implements Closeable {
|
|||
// The bounding box crosses the international date
|
||||
// line:
|
||||
BooleanQuery.Builder lonF = new BooleanQuery.Builder();
|
||||
lonF.add(PointRangeQuery.newDoubleRange("longitude", Math.toDegrees(minLng), true, null, true),
|
||||
lonF.add(DoublePoint.newRangeQuery("longitude", Math.toDegrees(minLng), true, null, true),
|
||||
BooleanClause.Occur.SHOULD);
|
||||
lonF.add(PointRangeQuery.newDoubleRange("longitude", null, true, Math.toDegrees(maxLng), true),
|
||||
lonF.add(DoublePoint.newRangeQuery("longitude", null, true, Math.toDegrees(maxLng), true),
|
||||
BooleanClause.Occur.SHOULD);
|
||||
f.add(lonF.build(), BooleanClause.Occur.MUST);
|
||||
} else {
|
||||
f.add(PointRangeQuery.newDoubleRange("longitude", Math.toDegrees(minLng), true, Math.toDegrees(maxLng), true),
|
||||
f.add(DoublePoint.newRangeQuery("longitude", Math.toDegrees(minLng), true, Math.toDegrees(maxLng), true),
|
||||
BooleanClause.Occur.FILTER);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
*/
|
||||
package org.apache.lucene.demo.facet;
|
||||
|
||||
|
||||
import org.apache.lucene.analysis.core.WhitespaceAnalyzer;
|
||||
import org.apache.lucene.document.LongPoint;
|
||||
import org.apache.lucene.document.Document;
|
||||
|
@ -32,7 +31,6 @@ import org.apache.lucene.index.DirectoryReader;
|
|||
import org.apache.lucene.index.IndexWriter;
|
||||
import org.apache.lucene.index.IndexWriterConfig;
|
||||
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
|
||||
import org.apache.lucene.search.PointRangeQuery;
|
||||
import org.apache.lucene.search.IndexSearcher;
|
||||
import org.apache.lucene.search.MatchAllDocsQuery;
|
||||
import org.apache.lucene.search.TopDocs;
|
||||
|
@ -107,7 +105,7 @@ public class RangeFacetsExample implements Closeable {
|
|||
// documents ("browse only"):
|
||||
DrillDownQuery q = new DrillDownQuery(getConfig());
|
||||
|
||||
q.add("timestamp", PointRangeQuery.newLongRange("timestamp", range.min, range.minInclusive, range.max, range.maxInclusive));
|
||||
q.add("timestamp", LongPoint.newRangeQuery("timestamp", range.min, range.minInclusive, range.max, range.maxInclusive));
|
||||
|
||||
return searcher.search(q, 10);
|
||||
}
|
||||
|
|
|
@ -54,7 +54,6 @@ import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
|
|||
import org.apache.lucene.queries.function.valuesource.DoubleFieldSource;
|
||||
import org.apache.lucene.queries.function.valuesource.FloatFieldSource;
|
||||
import org.apache.lucene.queries.function.valuesource.LongFieldSource;
|
||||
import org.apache.lucene.search.PointRangeQuery;
|
||||
import org.apache.lucene.search.Explanation;
|
||||
import org.apache.lucene.search.IndexSearcher;
|
||||
import org.apache.lucene.search.MatchAllDocsQuery;
|
||||
|
@ -281,7 +280,7 @@ public class TestRangeFacetCounts extends FacetTestCase {
|
|||
|
||||
// Third search, drill down on "less than or equal to 10":
|
||||
ddq = new DrillDownQuery(config);
|
||||
ddq.add("field", PointRangeQuery.newLongRange("field", 0L, true, 10L, true));
|
||||
ddq.add("field", LongPoint.newRangeQuery("field", 0L, true, 10L, true));
|
||||
dsr = ds.search(null, ddq, 10);
|
||||
|
||||
assertEquals(11, dsr.hits.totalHits);
|
||||
|
@ -461,9 +460,9 @@ public class TestRangeFacetCounts extends FacetTestCase {
|
|||
Query fastMatchQuery;
|
||||
if (random().nextBoolean()) {
|
||||
if (random().nextBoolean()) {
|
||||
fastMatchQuery = PointRangeQuery.newLongRange("field", minValue, true, maxValue, true);
|
||||
fastMatchQuery = LongPoint.newRangeQuery("field", minValue, true, maxValue, true);
|
||||
} else {
|
||||
fastMatchQuery = PointRangeQuery.newLongRange("field", minAcceptedValue, true, maxAcceptedValue, true);
|
||||
fastMatchQuery = LongPoint.newRangeQuery("field", minAcceptedValue, true, maxAcceptedValue, true);
|
||||
}
|
||||
} else {
|
||||
fastMatchQuery = null;
|
||||
|
@ -485,7 +484,7 @@ public class TestRangeFacetCounts extends FacetTestCase {
|
|||
// Test drill-down:
|
||||
DrillDownQuery ddq = new DrillDownQuery(config);
|
||||
if (random().nextBoolean()) {
|
||||
ddq.add("field", PointRangeQuery.newLongRange("field", range.min, range.minInclusive, range.max, range.maxInclusive));
|
||||
ddq.add("field", LongPoint.newRangeQuery("field", range.min, range.minInclusive, range.max, range.maxInclusive));
|
||||
} else {
|
||||
ddq.add("field", range.getQuery(fastMatchQuery, vs));
|
||||
}
|
||||
|
@ -616,9 +615,9 @@ public class TestRangeFacetCounts extends FacetTestCase {
|
|||
Query fastMatchQuery;
|
||||
if (random().nextBoolean()) {
|
||||
if (random().nextBoolean()) {
|
||||
fastMatchQuery = PointRangeQuery.newFloatRange("field", minValue, true, maxValue, true);
|
||||
fastMatchQuery = FloatPoint.newRangeQuery("field", minValue, true, maxValue, true);
|
||||
} else {
|
||||
fastMatchQuery = PointRangeQuery.newFloatRange("field", minAcceptedValue, true, maxAcceptedValue, true);
|
||||
fastMatchQuery = FloatPoint.newRangeQuery("field", minAcceptedValue, true, maxAcceptedValue, true);
|
||||
}
|
||||
} else {
|
||||
fastMatchQuery = null;
|
||||
|
@ -640,7 +639,7 @@ public class TestRangeFacetCounts extends FacetTestCase {
|
|||
// Test drill-down:
|
||||
DrillDownQuery ddq = new DrillDownQuery(config);
|
||||
if (random().nextBoolean()) {
|
||||
ddq.add("field", PointRangeQuery.newFloatRange("field", (float) range.min, range.minInclusive, (float) range.max, range.maxInclusive));
|
||||
ddq.add("field", FloatPoint.newRangeQuery("field", (float) range.min, range.minInclusive, (float) range.max, range.maxInclusive));
|
||||
} else {
|
||||
ddq.add("field", range.getQuery(fastMatchQuery, vs));
|
||||
}
|
||||
|
@ -755,9 +754,9 @@ public class TestRangeFacetCounts extends FacetTestCase {
|
|||
Query fastMatchFilter;
|
||||
if (random().nextBoolean()) {
|
||||
if (random().nextBoolean()) {
|
||||
fastMatchFilter = PointRangeQuery.newDoubleRange("field", minValue, true, maxValue, true);
|
||||
fastMatchFilter = DoublePoint.newRangeQuery("field", minValue, true, maxValue, true);
|
||||
} else {
|
||||
fastMatchFilter = PointRangeQuery.newDoubleRange("field", minAcceptedValue, true, maxAcceptedValue, true);
|
||||
fastMatchFilter = DoublePoint.newRangeQuery("field", minAcceptedValue, true, maxAcceptedValue, true);
|
||||
}
|
||||
} else {
|
||||
fastMatchFilter = null;
|
||||
|
@ -779,7 +778,7 @@ public class TestRangeFacetCounts extends FacetTestCase {
|
|||
// Test drill-down:
|
||||
DrillDownQuery ddq = new DrillDownQuery(config);
|
||||
if (random().nextBoolean()) {
|
||||
ddq.add("field", PointRangeQuery.newDoubleRange("field", range.min, range.minInclusive, range.max, range.maxInclusive));
|
||||
ddq.add("field", DoublePoint.newRangeQuery("field", range.min, range.minInclusive, range.max, range.maxInclusive));
|
||||
} else {
|
||||
ddq.add("field", range.getQuery(fastMatchFilter, vs));
|
||||
}
|
||||
|
|
|
@ -62,7 +62,6 @@ import org.apache.lucene.queries.payloads.SpanPayloadCheckQuery;
|
|||
import org.apache.lucene.search.BooleanClause.Occur;
|
||||
import org.apache.lucene.search.BooleanQuery;
|
||||
import org.apache.lucene.search.ConstantScoreQuery;
|
||||
import org.apache.lucene.search.PointRangeQuery;
|
||||
import org.apache.lucene.search.FuzzyQuery;
|
||||
import org.apache.lucene.search.IndexSearcher;
|
||||
import org.apache.lucene.search.MultiPhraseQuery;
|
||||
|
@ -584,7 +583,7 @@ public class HighlighterTest extends BaseTokenStreamTestCase implements Formatte
|
|||
|
||||
public void testDimensionalRangeQuery() throws Exception {
|
||||
// doesn't currently highlight, but make sure it doesn't cause exception either
|
||||
query = PointRangeQuery.newIntRange(NUMERIC_FIELD_NAME, 2, true, 6, true);
|
||||
query = IntPoint.newRangeQuery(NUMERIC_FIELD_NAME, 2, true, 6, true);
|
||||
searcher = newSearcher(reader);
|
||||
hits = searcher.search(query, 100);
|
||||
int maxNumFragmentsRequired = 2;
|
||||
|
|
|
@ -22,13 +22,23 @@ import org.apache.lucene.search.PointRangeQuery;
|
|||
import org.apache.lucene.util.BytesRef;
|
||||
import org.apache.lucene.util.NumericUtils;
|
||||
|
||||
/** A 128-bit integer field that is indexed dimensionally such that finding
|
||||
* all documents within an N-dimensional shape or range at search time is
|
||||
* efficient. Multiple values for the same field in one documents
|
||||
* is allowed. */
|
||||
/**
|
||||
* A 128-bit integer field that is indexed dimensionally such that finding
|
||||
* all documents within an N-dimensional shape or range at search time is
|
||||
* efficient. Multiple values for the same field in one documents
|
||||
* is allowed.
|
||||
* <p>
|
||||
* This field defines static factory methods for creating common queries:
|
||||
* <ul>
|
||||
* <li>{@link #newExactQuery newExactQuery()} for matching an exact 1D point.
|
||||
* <li>{@link #newRangeQuery newRangeQuery()} for matching a 1D range.
|
||||
* <li>{@link #newMultiRangeQuery newMultiRangeQuery()} for matching points/ranges in n-dimensional space.
|
||||
* </ul>
|
||||
*/
|
||||
public class BigIntegerPoint extends Field {
|
||||
|
||||
static final int BYTES = 16;
|
||||
/** The number of bytes per dimension: 128 bits. */
|
||||
public static final int BYTES = 16;
|
||||
|
||||
private static FieldType getType(int numDims) {
|
||||
FieldType type = new FieldType();
|
||||
|
@ -107,10 +117,8 @@ public class BigIntegerPoint extends Field {
|
|||
return result.toString();
|
||||
}
|
||||
|
||||
// public helper methods (e.g. for queries)
|
||||
|
||||
/** Encode n-dimensional BigInteger values into binary encoding */
|
||||
public static byte[][] encode(BigInteger value[]) {
|
||||
/** 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++) {
|
||||
if (value[i] != null) {
|
||||
|
@ -120,6 +128,8 @@ public class BigIntegerPoint extends Field {
|
|||
}
|
||||
return encoded;
|
||||
}
|
||||
|
||||
// public helper methods (e.g. for queries)
|
||||
|
||||
/** Encode single BigInteger dimension */
|
||||
public static void encodeDimension(BigInteger value, byte dest[], int offset) {
|
||||
|
@ -134,25 +144,25 @@ public class BigIntegerPoint extends Field {
|
|||
// static methods for generating queries
|
||||
|
||||
/**
|
||||
* Create a range query for matching an exact big integer value.
|
||||
* Create a query for matching an exact big integer value.
|
||||
* <p>
|
||||
* This is for simple one-dimension points, for multidimensional points use
|
||||
* {@link #newMultiBigIntegerRange newMultiBigIntegerRange()} instead.
|
||||
* {@link #newMultiRangeQuery newMultiRangeQuery()} instead.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param value exact value
|
||||
* @throws IllegalArgumentException if {@code field} is null.
|
||||
* @return a query matching documents with this exact value
|
||||
*/
|
||||
public static PointRangeQuery newBigIntegerExact(String field, BigInteger value) {
|
||||
return newBigIntegerRange(field, value, true, value, true);
|
||||
public static PointRangeQuery newExactQuery(String field, BigInteger value) {
|
||||
return newRangeQuery(field, value, true, value, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a range query for big integer values indexed with {@link BigIntegerPoint}.
|
||||
* Create a range query for big integer values.
|
||||
* <p>
|
||||
* This is for simple one-dimension ranges, for multidimensional ranges use
|
||||
* {@link #newMultiBigIntegerRange newMultiBigIntegerRange()} instead.
|
||||
* {@link #newMultiRangeQuery newMultiRangeQuery()} instead.
|
||||
* <p>
|
||||
* You can have half-open ranges (which are in fact </≤ or >/≥ queries)
|
||||
* by setting the {@code lowerValue} or {@code upperValue} to {@code null}.
|
||||
|
@ -168,16 +178,16 @@ public class BigIntegerPoint extends Field {
|
|||
* @throws IllegalArgumentException if {@code field} is null.
|
||||
* @return a query matching documents within this range.
|
||||
*/
|
||||
public static PointRangeQuery newBigIntegerRange(String field, BigInteger lowerValue, boolean lowerInclusive, BigInteger upperValue, boolean upperInclusive) {
|
||||
return newMultiBigIntegerRange(field,
|
||||
new BigInteger[] { lowerValue },
|
||||
new boolean[] { lowerInclusive },
|
||||
new BigInteger[] { upperValue },
|
||||
new boolean[] { upperInclusive });
|
||||
public static PointRangeQuery newRangeQuery(String field, BigInteger lowerValue, boolean lowerInclusive, BigInteger upperValue, boolean upperInclusive) {
|
||||
return newMultiRangeQuery(field,
|
||||
new BigInteger[] { lowerValue },
|
||||
new boolean[] { lowerInclusive },
|
||||
new BigInteger[] { upperValue },
|
||||
new boolean[] { upperInclusive });
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a multidimensional range query for big integer values indexed with {@link BigIntegerPoint}.
|
||||
* Create a multidimensional range query for big integer values.
|
||||
* <p>
|
||||
* You can have half-open ranges (which are in fact </≤ or >/≥ queries)
|
||||
* by setting a {@code lowerValue} element or {@code upperValue} element to {@code null}.
|
||||
|
@ -193,7 +203,7 @@ public class BigIntegerPoint extends Field {
|
|||
* @throws IllegalArgumentException if {@code field} is null, or if {@code lowerValue.length != upperValue.length}
|
||||
* @return a query matching documents within this range.
|
||||
*/
|
||||
public static PointRangeQuery newMultiBigIntegerRange(String field, BigInteger[] lowerValue, boolean lowerInclusive[], BigInteger[] upperValue, boolean upperInclusive[]) {
|
||||
public static PointRangeQuery newMultiRangeQuery(String field, BigInteger[] lowerValue, boolean lowerInclusive[], BigInteger[] upperValue, boolean upperInclusive[]) {
|
||||
PointRangeQuery.checkArgs(field, lowerValue, upperValue);
|
||||
return new PointRangeQuery(field, BigIntegerPoint.encode(lowerValue), lowerInclusive, BigIntegerPoint.encode(upperValue), upperInclusive) {
|
||||
@Override
|
||||
|
|
|
@ -22,20 +22,29 @@ import java.net.UnknownHostException;
|
|||
import org.apache.lucene.search.PointRangeQuery;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
|
||||
/** A field indexing {@link InetAddress} dimensionally such that finding
|
||||
* all documents within a range at search time is
|
||||
* efficient. Multiple values for the same field in one document
|
||||
* is allowed.
|
||||
* <p>
|
||||
* This field supports both IPv4 and IPv6 addresses: IPv4 addresses are converted
|
||||
* to <a href="https://tools.ietf.org/html/rfc4291#section-2.5.5">IPv4-Mapped IPv6 Addresses</a>:
|
||||
* indexing {@code 1.2.3.4} is the same as indexing {@code ::FFFF:1.2.3.4}.
|
||||
/**
|
||||
* A field indexing {@link InetAddress} dimensionally such that finding
|
||||
* all documents within a range at search time is
|
||||
* efficient. Multiple values for the same field in one document
|
||||
* is allowed.
|
||||
* <p>
|
||||
* This field defines static factory methods for creating common queries:
|
||||
* <ul>
|
||||
* <li>{@link #newExactQuery newExactQuery()} for matching an exact network address.
|
||||
* <li>{@link #newPrefixQuery newPrefixQuery()} for matching a network based on CIDR prefix.
|
||||
* <li>{@link #newRangeQuery newRangeQuery()} for matching arbitrary network address ranges.
|
||||
* </ul>
|
||||
* <p>
|
||||
* This field supports both IPv4 and IPv6 addresses: IPv4 addresses are converted
|
||||
* to <a href="https://tools.ietf.org/html/rfc4291#section-2.5.5">IPv4-Mapped IPv6 Addresses</a>:
|
||||
* indexing {@code 1.2.3.4} is the same as indexing {@code ::FFFF:1.2.3.4}.
|
||||
*/
|
||||
public class InetAddressPoint extends Field {
|
||||
|
||||
// implementation note: we convert all addresses to IPv6: we expect prefix compression of values,
|
||||
// so its not wasteful, but allows one field to handle both IPv4 and IPv6.
|
||||
static final int BYTES = 16;
|
||||
/** The number of bytes per dimension: 128 bits */
|
||||
public static final int BYTES = 16;
|
||||
|
||||
// rfc4291 prefix
|
||||
static final byte[] IPV4_PREFIX = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1 };
|
||||
|
@ -80,8 +89,16 @@ public class InetAddressPoint extends Field {
|
|||
result.append(name);
|
||||
result.append(':');
|
||||
|
||||
// IPv6 addresses are bracketed, to not cause confusion with historic field:value representation
|
||||
BytesRef bytes = (BytesRef) fieldsData;
|
||||
result.append(decodeToString(BytesRef.deepCopyOf(bytes).bytes));
|
||||
InetAddress address = decode(BytesRef.deepCopyOf(bytes).bytes);
|
||||
if (address.getAddress().length == 16) {
|
||||
result.append('[');
|
||||
result.append(address.getHostAddress());
|
||||
result.append(']');
|
||||
} else {
|
||||
result.append(address.getHostAddress());
|
||||
}
|
||||
|
||||
result.append('>');
|
||||
return result.toString();
|
||||
|
@ -113,34 +130,23 @@ public class InetAddressPoint extends Field {
|
|||
throw new IllegalArgumentException("encoded bytes are of incorrect length", e);
|
||||
}
|
||||
}
|
||||
|
||||
/** decodes from binary encoding to a friendly format: IPv6 addresses are bracketed,
|
||||
* to not cause confusion with historic field:value representation, etc */
|
||||
public static String decodeToString(byte value[]) {
|
||||
InetAddress address = decode(value);
|
||||
if (address.getAddress().length == 16) {
|
||||
return "[" + address.getHostAddress() + "]";
|
||||
} else {
|
||||
return address.getHostAddress();
|
||||
}
|
||||
}
|
||||
|
||||
// static methods for generating queries
|
||||
|
||||
/**
|
||||
* Create a range query for matching an address.
|
||||
* Create a query for matching a network address.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param value exact value
|
||||
* @throws IllegalArgumentException if {@code field} is null.
|
||||
* @return a query matching documents with this exact value
|
||||
*/
|
||||
public static PointRangeQuery newInetAddressExact(String field, InetAddress value) {
|
||||
return newInetAddressRange(field, value, true, value, true);
|
||||
public static PointRangeQuery newExactQuery(String field, InetAddress value) {
|
||||
return newRangeQuery(field, value, true, value, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a range query for matching a CIDR network range.
|
||||
* Create a prefix query for matching a CIDR network range.
|
||||
*
|
||||
* @param field field name. must not be {@code null}.
|
||||
* @param value any host address
|
||||
|
@ -148,7 +154,7 @@ public class InetAddressPoint extends Field {
|
|||
* @throws IllegalArgumentException if {@code field} is null, or prefixLength is invalid.
|
||||
* @return a query matching documents with addresses contained within this network
|
||||
*/
|
||||
public static PointRangeQuery newInetAddressPrefix(String field, InetAddress value, int prefixLength) {
|
||||
public static PointRangeQuery newPrefixQuery(String field, InetAddress value, int prefixLength) {
|
||||
if (prefixLength < 0 || prefixLength > 8 * value.getAddress().length) {
|
||||
throw new IllegalArgumentException("illegal prefixLength '" + prefixLength + "'. Must be 0-32 for IPv4 ranges, 0-128 for IPv6 ranges");
|
||||
}
|
||||
|
@ -160,14 +166,14 @@ public class InetAddressPoint extends Field {
|
|||
upper[i >> 3] |= 1 << (i & 7);
|
||||
}
|
||||
try {
|
||||
return newInetAddressRange(field, InetAddress.getByAddress(lower), true, InetAddress.getByAddress(upper), true);
|
||||
return newRangeQuery(field, InetAddress.getByAddress(lower), true, InetAddress.getByAddress(upper), true);
|
||||
} catch (UnknownHostException e) {
|
||||
throw new AssertionError(e); // values are coming from InetAddress
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a range query for addresses indexed with {@link InetAddressPoint}.
|
||||
* Create a range query for network addresses.
|
||||
* <p>
|
||||
* You can have half-open ranges (which are in fact </≤ or >/≥ queries)
|
||||
* by setting the {@code lowerValue} or {@code upperValue} to {@code null}.
|
||||
|
@ -183,7 +189,7 @@ public class InetAddressPoint extends Field {
|
|||
* @throws IllegalArgumentException if {@code field} is null.
|
||||
* @return a query matching documents within this range.
|
||||
*/
|
||||
public static PointRangeQuery newInetAddressRange(String field, InetAddress lowerValue, boolean lowerInclusive, InetAddress upperValue, boolean upperInclusive) {
|
||||
public static PointRangeQuery newRangeQuery(String field, InetAddress lowerValue, boolean lowerInclusive, InetAddress upperValue, boolean upperInclusive) {
|
||||
byte[][] lowerBytes = new byte[1][];
|
||||
if (lowerValue != null) {
|
||||
lowerBytes[0] = InetAddressPoint.encode(lowerValue);
|
||||
|
|
|
@ -41,8 +41,8 @@ public class TestBigIntegerPoint extends LuceneTestCase {
|
|||
// search and verify we found our doc
|
||||
IndexReader reader = writer.getReader();
|
||||
IndexSearcher searcher = newSearcher(reader);
|
||||
assertEquals(1, searcher.count(BigIntegerPoint.newBigIntegerExact("field", large)));
|
||||
assertEquals(1, searcher.count(BigIntegerPoint.newBigIntegerRange("field", large.subtract(BigInteger.ONE), false, large.add(BigInteger.ONE), false)));
|
||||
assertEquals(1, searcher.count(BigIntegerPoint.newExactQuery("field", large)));
|
||||
assertEquals(1, searcher.count(BigIntegerPoint.newRangeQuery("field", large.subtract(BigInteger.ONE), false, large.add(BigInteger.ONE), false)));
|
||||
|
||||
reader.close();
|
||||
writer.close();
|
||||
|
@ -63,8 +63,8 @@ public class TestBigIntegerPoint extends LuceneTestCase {
|
|||
// search and verify we found our doc
|
||||
IndexReader reader = writer.getReader();
|
||||
IndexSearcher searcher = newSearcher(reader);
|
||||
assertEquals(1, searcher.count(BigIntegerPoint.newBigIntegerExact("field", negative)));
|
||||
assertEquals(1, searcher.count(BigIntegerPoint.newBigIntegerRange("field", negative.subtract(BigInteger.ONE), false, negative.add(BigInteger.ONE), false)));
|
||||
assertEquals(1, searcher.count(BigIntegerPoint.newExactQuery("field", negative)));
|
||||
assertEquals(1, searcher.count(BigIntegerPoint.newRangeQuery("field", negative.subtract(BigInteger.ONE), false, negative.add(BigInteger.ONE), false)));
|
||||
|
||||
reader.close();
|
||||
writer.close();
|
||||
|
|
|
@ -41,9 +41,9 @@ public class TestInetAddressPoint extends LuceneTestCase {
|
|||
// search and verify we found our doc
|
||||
IndexReader reader = writer.getReader();
|
||||
IndexSearcher searcher = newSearcher(reader);
|
||||
assertEquals(1, searcher.count(InetAddressPoint.newInetAddressExact("field", address)));
|
||||
assertEquals(1, searcher.count(InetAddressPoint.newInetAddressPrefix("field", address, 24)));
|
||||
assertEquals(1, searcher.count(InetAddressPoint.newInetAddressRange("field", InetAddress.getByName("1.2.3.3"), false, InetAddress.getByName("1.2.3.5"), false)));
|
||||
assertEquals(1, searcher.count(InetAddressPoint.newExactQuery("field", address)));
|
||||
assertEquals(1, searcher.count(InetAddressPoint.newPrefixQuery("field", address, 24)));
|
||||
assertEquals(1, searcher.count(InetAddressPoint.newRangeQuery("field", InetAddress.getByName("1.2.3.3"), false, InetAddress.getByName("1.2.3.5"), false)));
|
||||
|
||||
reader.close();
|
||||
writer.close();
|
||||
|
@ -64,9 +64,9 @@ public class TestInetAddressPoint extends LuceneTestCase {
|
|||
// search and verify we found our doc
|
||||
IndexReader reader = writer.getReader();
|
||||
IndexSearcher searcher = newSearcher(reader);
|
||||
assertEquals(1, searcher.count(InetAddressPoint.newInetAddressExact("field", address)));
|
||||
assertEquals(1, searcher.count(InetAddressPoint.newInetAddressPrefix("field", address, 64)));
|
||||
assertEquals(1, searcher.count(InetAddressPoint.newInetAddressRange("field", InetAddress.getByName("fec0::f66c"), false, InetAddress.getByName("fec0::f66e"), false)));
|
||||
assertEquals(1, searcher.count(InetAddressPoint.newExactQuery("field", address)));
|
||||
assertEquals(1, searcher.count(InetAddressPoint.newPrefixQuery("field", address, 64)));
|
||||
assertEquals(1, searcher.count(InetAddressPoint.newRangeQuery("field", InetAddress.getByName("fec0::f66c"), false, InetAddress.getByName("fec0::f66e"), false)));
|
||||
|
||||
reader.close();
|
||||
writer.close();
|
||||
|
@ -78,10 +78,10 @@ public class TestInetAddressPoint extends LuceneTestCase {
|
|||
assertEquals("<field:1.2.3.4>", new InetAddressPoint("field", InetAddress.getByName("::FFFF:1.2.3.4")).toString());
|
||||
assertEquals("<field:[fdc8:57ed:f042:ad1:f66d:4ff:fe90:ce0c]>", new InetAddressPoint("field", InetAddress.getByName("fdc8:57ed:f042:0ad1:f66d:4ff:fe90:ce0c")).toString());
|
||||
|
||||
assertEquals("field:[1.2.3.4 TO 1.2.3.4]", InetAddressPoint.newInetAddressExact("field", InetAddress.getByName("1.2.3.4")).toString());
|
||||
assertEquals("field:[0:0:0:0:0:0:0:1 TO 0:0:0:0:0:0:0:1]", InetAddressPoint.newInetAddressExact("field", InetAddress.getByName("::1")).toString());
|
||||
assertEquals("field:[1.2.3.4 TO 1.2.3.4]", InetAddressPoint.newExactQuery("field", InetAddress.getByName("1.2.3.4")).toString());
|
||||
assertEquals("field:[0:0:0:0:0:0:0:1 TO 0:0:0:0:0:0:0:1]", InetAddressPoint.newExactQuery("field", InetAddress.getByName("::1")).toString());
|
||||
|
||||
assertEquals("field:[1.2.3.0 TO 1.2.3.255]", InetAddressPoint.newInetAddressPrefix("field", InetAddress.getByName("1.2.3.4"), 24).toString());
|
||||
assertEquals("field:[fdc8:57ed:f042:ad1:0:0:0:0 TO fdc8:57ed:f042:ad1:ffff:ffff:ffff:ffff]", InetAddressPoint.newInetAddressPrefix("field", InetAddress.getByName("fdc8:57ed:f042:0ad1:f66d:4ff:fe90:ce0c"), 64).toString());
|
||||
assertEquals("field:[1.2.3.0 TO 1.2.3.255]", InetAddressPoint.newPrefixQuery("field", InetAddress.getByName("1.2.3.4"), 24).toString());
|
||||
assertEquals("field:[fdc8:57ed:f042:ad1:0:0:0:0 TO fdc8:57ed:f042:ad1:ffff:ffff:ffff:ffff]", InetAddressPoint.newPrefixQuery("field", InetAddress.getByName("fdc8:57ed:f042:0ad1:f66d:4ff:fe90:ce0c"), 64).toString());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,6 @@ import org.apache.lucene.store.Directory;
|
|||
import org.apache.lucene.util.BytesRef;
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
import org.apache.lucene.util.NumericUtils;
|
||||
import org.apache.lucene.util.RamUsageEstimator;
|
||||
import org.apache.lucene.util.TestUtil;
|
||||
|
||||
public class TestDocValuesRangeQuery extends LuceneTestCase {
|
||||
|
@ -57,7 +56,7 @@ public class TestDocValuesRangeQuery extends LuceneTestCase {
|
|||
iw.addDocument(doc);
|
||||
}
|
||||
if (random().nextBoolean()) {
|
||||
iw.deleteDocuments(PointRangeQuery.newLongRange("idx", 0L, true, 10L, true));
|
||||
iw.deleteDocuments(LongPoint.newRangeQuery("idx", 0L, true, 10L, true));
|
||||
}
|
||||
iw.commit();
|
||||
final IndexReader reader = iw.getReader();
|
||||
|
@ -69,7 +68,7 @@ public class TestDocValuesRangeQuery extends LuceneTestCase {
|
|||
final Long max = random().nextBoolean() ? null : TestUtil.nextLong(random(), -100, 1000);
|
||||
final boolean minInclusive = random().nextBoolean();
|
||||
final boolean maxInclusive = random().nextBoolean();
|
||||
final Query q1 = PointRangeQuery.newLongRange("idx", min, minInclusive, max, maxInclusive);
|
||||
final Query q1 = LongPoint.newRangeQuery("idx", min, minInclusive, max, maxInclusive);
|
||||
final Query q2 = DocValuesRangeQuery.newLongRange("dv", min, max, minInclusive, maxInclusive);
|
||||
assertSameMatches(searcher, q1, q2, false);
|
||||
}
|
||||
|
@ -185,7 +184,7 @@ public class TestDocValuesRangeQuery extends LuceneTestCase {
|
|||
iw.addDocument(doc);
|
||||
}
|
||||
if (random().nextBoolean()) {
|
||||
iw.deleteDocuments(PointRangeQuery.newLongRange("idx", 0L, true, 10L, true));
|
||||
iw.deleteDocuments(LongPoint.newRangeQuery("idx", 0L, true, 10L, true));
|
||||
}
|
||||
iw.commit();
|
||||
final IndexReader reader = iw.getReader();
|
||||
|
@ -199,7 +198,7 @@ public class TestDocValuesRangeQuery extends LuceneTestCase {
|
|||
final boolean maxInclusive = random().nextBoolean();
|
||||
|
||||
BooleanQuery.Builder ref = new BooleanQuery.Builder();
|
||||
ref.add(PointRangeQuery.newLongRange("idx", min, minInclusive, max, maxInclusive), Occur.FILTER);
|
||||
ref.add(LongPoint.newRangeQuery("idx", min, minInclusive, max, maxInclusive), Occur.FILTER);
|
||||
ref.add(new TermQuery(new Term("f", "a")), Occur.MUST);
|
||||
|
||||
BooleanQuery.Builder bq1 = new BooleanQuery.Builder();
|
||||
|
|
|
@ -43,7 +43,6 @@ import org.apache.lucene.index.IndexWriterConfig;
|
|||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.apache.lucene.index.RandomIndexWriter;
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.search.PointRangeQuery;
|
||||
import org.apache.lucene.search.ScoreDoc;
|
||||
import org.apache.lucene.search.TopDocs;
|
||||
import org.apache.lucene.search.suggest.BitsProducer;
|
||||
|
@ -302,7 +301,7 @@ public class TestSuggestField extends LuceneTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
iw.deleteDocuments(PointRangeQuery.newIntRange("weight_fld", 2, true, null, false));
|
||||
iw.deleteDocuments(IntPoint.newRangeQuery("weight_fld", 2, true, null, false));
|
||||
|
||||
DirectoryReader reader = DirectoryReader.open(iw);
|
||||
SuggestIndexSearcher indexSearcher = new SuggestIndexSearcher(reader);
|
||||
|
|
|
@ -34,7 +34,6 @@ import org.apache.lucene.document.StringField;
|
|||
import org.apache.lucene.index.PointValues.IntersectVisitor;
|
||||
import org.apache.lucene.index.PointValues.Relation;
|
||||
import org.apache.lucene.search.IndexSearcher;
|
||||
import org.apache.lucene.search.PointRangeQuery;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.store.MockDirectoryWrapper;
|
||||
import org.apache.lucene.util.Bits;
|
||||
|
@ -847,8 +846,8 @@ public abstract class BasePointFormatTestCase extends BaseIndexFileFormatTestCas
|
|||
|
||||
DirectoryReader r = w.getReader();
|
||||
IndexSearcher s = newSearcher(r);
|
||||
assertEquals(2, s.count(PointRangeQuery.newIntExact("int1", 17)));
|
||||
assertEquals(2, s.count(PointRangeQuery.newIntExact("int2", 42)));
|
||||
assertEquals(2, s.count(IntPoint.newExactQuery("int1", 17)));
|
||||
assertEquals(2, s.count(IntPoint.newExactQuery("int2", 42)));
|
||||
r.close();
|
||||
w.close();
|
||||
dir.close();
|
||||
|
|
Loading…
Reference in New Issue