diff --git a/lucene/core/src/java/org/apache/lucene/document/BinaryPoint.java b/lucene/core/src/java/org/apache/lucene/document/BinaryPoint.java index f80e1c0a1c7..8dd39252e0a 100644 --- a/lucene/core/src/java/org/apache/lucene/document/BinaryPoint.java +++ b/lucene/core/src/java/org/apache/lucene/document/BinaryPoint.java @@ -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. + *

+ * This field defines static factory methods for creating common queries: + *

+ */ 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. + *

+ * 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. + *

+ * This is for simple one-dimension ranges, for multidimensional ranges use + * {@link #newMultiRangeQuery newMultiRangeQuery()} instead. + *

+ * You can have half-open ranges (which are in fact </≤ or >/≥ queries) + * by setting the {@code lowerValue} or {@code upperValue} to {@code null}. + *

+ * 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. + *

+ * 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}. + *

+ * 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(); + } + }; + } } diff --git a/lucene/core/src/java/org/apache/lucene/document/DoublePoint.java b/lucene/core/src/java/org/apache/lucene/document/DoublePoint.java index e21c639e267..ee0d6f23b1e 100644 --- a/lucene/core/src/java/org/apache/lucene/document/DoublePoint.java +++ b/lucene/core/src/java/org/apache/lucene/document/DoublePoint.java @@ -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. + *

+ * This field defines static factory methods for creating common queries: + *

+ */ 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. + *

+ * 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. + *

+ * This is for simple one-dimension ranges, for multidimensional ranges use + * {@link #newMultiRangeQuery newMultiRangeQuery()} instead. + *

+ * You can have half-open ranges (which are in fact </≤ or >/≥ queries) + * by setting the {@code lowerValue} or {@code upperValue} to {@code null}. + *

+ * 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. + *

+ * 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}. + *

+ * 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(); + } + }; + } } diff --git a/lucene/core/src/java/org/apache/lucene/document/FloatPoint.java b/lucene/core/src/java/org/apache/lucene/document/FloatPoint.java index c51160314c7..34216b46c80 100644 --- a/lucene/core/src/java/org/apache/lucene/document/FloatPoint.java +++ b/lucene/core/src/java/org/apache/lucene/document/FloatPoint.java @@ -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. + *

+ * This field defines static factory methods for creating common queries: + *

+ */ 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. + *

+ * 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. + *

+ * This is for simple one-dimension ranges, for multidimensional ranges use + * {@link #newMultiRangeQuery newMultiRangeQuery()} instead. + *

+ * You can have half-open ranges (which are in fact </≤ or >/≥ queries) + * by setting the {@code lowerValue} or {@code upperValue} to {@code null}. + *

+ * 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. + *

+ * 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}. + *

+ * 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(); + } + }; + } } diff --git a/lucene/core/src/java/org/apache/lucene/document/IntPoint.java b/lucene/core/src/java/org/apache/lucene/document/IntPoint.java index be91bfdea07..177ae9955d6 100644 --- a/lucene/core/src/java/org/apache/lucene/document/IntPoint.java +++ b/lucene/core/src/java/org/apache/lucene/document/IntPoint.java @@ -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; -/** 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. + *

+ * This field defines static factory methods for creating common queries: + *

+ */ public final class IntPoint extends Field { private static FieldType getType(int numDims) { @@ -108,10 +117,8 @@ public final class IntPoint extends Field { return result.toString(); } - // public helper methods (e.g. for queries) - /** Encode n-dimensional integer values into binary encoding */ - public static byte[][] encode(Integer value[]) { + private static byte[][] encode(Integer 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 IntPoint extends Field { 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); @@ -131,4 +140,76 @@ public final class IntPoint extends Field { 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. + *

+ * 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. + *

+ * This is for simple one-dimension ranges, for multidimensional ranges use + * {@link #newMultiRangeQuery newMultiRangeQuery()} instead. + *

+ * You can have half-open ranges (which are in fact </≤ or >/≥ queries) + * by setting the {@code lowerValue} or {@code upperValue} to {@code null}. + *

+ * 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. + *

+ * 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}. + *

+ * 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(); + } + }; + } } diff --git a/lucene/core/src/java/org/apache/lucene/document/LongPoint.java b/lucene/core/src/java/org/apache/lucene/document/LongPoint.java index 38ff72071ed..d3f8c171d66 100644 --- a/lucene/core/src/java/org/apache/lucene/document/LongPoint.java +++ b/lucene/core/src/java/org/apache/lucene/document/LongPoint.java @@ -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. + *

+ * This field defines static factory methods for creating common queries: + *

+ */ 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. + *

+ * 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. + *

+ * This is for simple one-dimension ranges, for multidimensional ranges use + * {@link #newMultiRangeQuery newMultiRangeQuery()} instead. + *

+ * You can have half-open ranges (which are in fact </≤ or >/≥ queries) + * by setting the {@code lowerValue} or {@code upperValue} to {@code null}. + *

+ * 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. + *

+ * 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}. + *

+ * 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(); + } + }; + } } diff --git a/lucene/core/src/java/org/apache/lucene/search/PointRangeQuery.java b/lucene/core/src/java/org/apache/lucene/search/PointRangeQuery.java index bf2b2ef2ddf..9db80fc5598 100644 --- a/lucene/core/src/java/org/apache/lucene/search/PointRangeQuery.java +++ b/lucene/core/src/java/org/apache/lucene/search/PointRangeQuery.java @@ -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}. + *

+ * 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}. + *

+ * 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. *

- * 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: - *

- *

* 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}. *

@@ -132,350 +134,6 @@ public class PointRangeQuery extends Query { } } - /** - * Create a range query for matching an exact integer value. - *

- * 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}. - *

- * This is for simple one-dimension ranges, for multidimensional ranges use - * {@link #newMultiIntRange newMultiIntRange()} instead. - *

- * You can have half-open ranges (which are in fact </≤ or >/≥ queries) - * by setting the {@code lowerValue} or {@code upperValue} to {@code null}. - *

- * 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}. - *

- * 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}. - *

- * 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. - *

- * 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}. - *

- * This is for simple one-dimension ranges, for multidimensional ranges use - * {@link #newMultiLongRange newMultiLongRange()} instead. - *

- * You can have half-open ranges (which are in fact </≤ or >/≥ queries) - * by setting the {@code lowerValue} or {@code upperValue} to {@code null}. - *

- * 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}. - *

- * 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}. - *

- * 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. - *

- * 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}. - *

- * This is for simple one-dimension ranges, for multidimensional ranges use - * {@link #newMultiFloatRange newMultiFloatRange()} instead. - *

- * You can have half-open ranges (which are in fact </≤ or >/≥ queries) - * by setting the {@code lowerValue} or {@code upperValue} to {@code null}. - *

- * 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}. - *

- * 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}. - *

- * 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. - *

- * 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}. - *

- * This is for simple one-dimension ranges, for multidimensional ranges use - * {@link #newMultiDoubleRange newMultiDoubleRange()} instead. - *

- * You can have half-open ranges (which are in fact </≤ or >/≥ queries) - * by setting the {@code lowerValue} or {@code upperValue} to {@code null}. - *

- * 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}. - *

- * 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}. - *

- * 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. - *

- * 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}. - *

- * This is for simple one-dimension ranges, for multidimensional ranges use - * {@link #newMultiBinaryRange newMultiBinaryRange()} instead. - *

- * You can have half-open ranges (which are in fact </≤ or >/≥ queries) - * by setting the {@code lowerValue} or {@code upperValue} to {@code null}. - *

- * 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}. - *

- * 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}. - *

- * 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); } diff --git a/lucene/core/src/test/org/apache/lucene/index/TestDemoParallelLeafReader.java b/lucene/core/src/test/org/apache/lucene/index/TestDemoParallelLeafReader.java index 9a74231a525..0f265512632 100644 --- a/lucene/core/src/test/org/apache/lucene/index/TestDemoParallelLeafReader.java +++ b/lucene/core/src/test/org/apache/lucene/index/TestDemoParallelLeafReader.java @@ -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); diff --git a/lucene/core/src/test/org/apache/lucene/search/TestPointQueries.java b/lucene/core/src/test/org/apache/lucene/search/TestPointQueries.java index cfab5fbea09..bb93f2fd5df 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestPointQueries.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestPointQueries.java @@ -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 }, diff --git a/lucene/core/src/test/org/apache/lucene/search/TestUsageTrackingFilterCachingPolicy.java b/lucene/core/src/test/org/apache/lucene/search/TestUsageTrackingFilterCachingPolicy.java index 323351e007f..2edebb3d724 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestUsageTrackingFilterCachingPolicy.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestUsageTrackingFilterCachingPolicy.java @@ -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")))); } diff --git a/lucene/demo/src/java/org/apache/lucene/demo/facet/DistanceFacetsExample.java b/lucene/demo/src/java/org/apache/lucene/demo/facet/DistanceFacetsExample.java index 083e41c99cc..d9e944179ce 100644 --- a/lucene/demo/src/java/org/apache/lucene/demo/facet/DistanceFacetsExample.java +++ b/lucene/demo/src/java/org/apache/lucene/demo/facet/DistanceFacetsExample.java @@ -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); } diff --git a/lucene/demo/src/java/org/apache/lucene/demo/facet/RangeFacetsExample.java b/lucene/demo/src/java/org/apache/lucene/demo/facet/RangeFacetsExample.java index 1a7a984fff6..96d7c17cf9f 100644 --- a/lucene/demo/src/java/org/apache/lucene/demo/facet/RangeFacetsExample.java +++ b/lucene/demo/src/java/org/apache/lucene/demo/facet/RangeFacetsExample.java @@ -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); } diff --git a/lucene/facet/src/test/org/apache/lucene/facet/range/TestRangeFacetCounts.java b/lucene/facet/src/test/org/apache/lucene/facet/range/TestRangeFacetCounts.java index 87f0579e73f..f7a1970ca42 100644 --- a/lucene/facet/src/test/org/apache/lucene/facet/range/TestRangeFacetCounts.java +++ b/lucene/facet/src/test/org/apache/lucene/facet/range/TestRangeFacetCounts.java @@ -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)); } diff --git a/lucene/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterTest.java b/lucene/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterTest.java index 58f1eb9cae3..edc91f6e9d3 100644 --- a/lucene/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterTest.java +++ b/lucene/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterTest.java @@ -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; diff --git a/lucene/sandbox/src/java/org/apache/lucene/document/BigIntegerPoint.java b/lucene/sandbox/src/java/org/apache/lucene/document/BigIntegerPoint.java index f2e9f1dd858..f88c85a9c19 100644 --- a/lucene/sandbox/src/java/org/apache/lucene/document/BigIntegerPoint.java +++ b/lucene/sandbox/src/java/org/apache/lucene/document/BigIntegerPoint.java @@ -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. + *

+ * This field defines static factory methods for creating common queries: + *

+ */ 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. *

* 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. *

* This is for simple one-dimension ranges, for multidimensional ranges use - * {@link #newMultiBigIntegerRange newMultiBigIntegerRange()} instead. + * {@link #newMultiRangeQuery newMultiRangeQuery()} instead. *

* 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. *

* 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 diff --git a/lucene/sandbox/src/java/org/apache/lucene/document/InetAddressPoint.java b/lucene/sandbox/src/java/org/apache/lucene/document/InetAddressPoint.java index 06a3ce40903..51ada8f3ab3 100644 --- a/lucene/sandbox/src/java/org/apache/lucene/document/InetAddressPoint.java +++ b/lucene/sandbox/src/java/org/apache/lucene/document/InetAddressPoint.java @@ -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. - *

- * This field supports both IPv4 and IPv6 addresses: IPv4 addresses are converted - * to IPv4-Mapped IPv6 Addresses: - * 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. + *

+ * This field defines static factory methods for creating common queries: + *

+ *

+ * This field supports both IPv4 and IPv6 addresses: IPv4 addresses are converted + * to IPv4-Mapped IPv6 Addresses: + * 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. *

* 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); diff --git a/lucene/sandbox/src/test/org/apache/lucene/document/TestBigIntegerPoint.java b/lucene/sandbox/src/test/org/apache/lucene/document/TestBigIntegerPoint.java index 9009b53cf0f..aeb15e6a0aa 100644 --- a/lucene/sandbox/src/test/org/apache/lucene/document/TestBigIntegerPoint.java +++ b/lucene/sandbox/src/test/org/apache/lucene/document/TestBigIntegerPoint.java @@ -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(); diff --git a/lucene/sandbox/src/test/org/apache/lucene/document/TestInetAddressPoint.java b/lucene/sandbox/src/test/org/apache/lucene/document/TestInetAddressPoint.java index f25619664a7..19b02b2542d 100644 --- a/lucene/sandbox/src/test/org/apache/lucene/document/TestInetAddressPoint.java +++ b/lucene/sandbox/src/test/org/apache/lucene/document/TestInetAddressPoint.java @@ -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("", new InetAddressPoint("field", InetAddress.getByName("::FFFF:1.2.3.4")).toString()); assertEquals("", 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()); } } diff --git a/lucene/sandbox/src/test/org/apache/lucene/search/TestDocValuesRangeQuery.java b/lucene/sandbox/src/test/org/apache/lucene/search/TestDocValuesRangeQuery.java index f57c1e1c3c2..1bcadd6b930 100644 --- a/lucene/sandbox/src/test/org/apache/lucene/search/TestDocValuesRangeQuery.java +++ b/lucene/sandbox/src/test/org/apache/lucene/search/TestDocValuesRangeQuery.java @@ -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(); diff --git a/lucene/suggest/src/test/org/apache/lucene/search/suggest/document/TestSuggestField.java b/lucene/suggest/src/test/org/apache/lucene/search/suggest/document/TestSuggestField.java index 05f38bbad28..384b98b394d 100644 --- a/lucene/suggest/src/test/org/apache/lucene/search/suggest/document/TestSuggestField.java +++ b/lucene/suggest/src/test/org/apache/lucene/search/suggest/document/TestSuggestField.java @@ -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); diff --git a/lucene/test-framework/src/java/org/apache/lucene/index/BasePointFormatTestCase.java b/lucene/test-framework/src/java/org/apache/lucene/index/BasePointFormatTestCase.java index 4b8eac29f64..3f61bd1aa52 100644 --- a/lucene/test-framework/src/java/org/apache/lucene/index/BasePointFormatTestCase.java +++ b/lucene/test-framework/src/java/org/apache/lucene/index/BasePointFormatTestCase.java @@ -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();