diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index 0f88d62de2e8..e921e15af353 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -158,7 +158,10 @@ API Changes * GITHUB#15422: Add a new method in DirectWriter to compute how many bytes are written for encoding a number of values using a number of bits per value. (Ignacio Vera) -* GITHUB##15428: Add support for ExecutorServices to be passed into DirectoryReader.open() and DirectoryReader.openIfChanged() APIs (Bryce Kane) +* GITHUB#15428: Add support for ExecutorServices to be passed into DirectoryReader.open() and DirectoryReader.openIfChanged() APIs (Bryce Kane) + +* GITHUB#15483: Deprecate SortField.setMissingValue() in preparation for making SortField immutable + in Lucene 11.0. Missing values can be set as constructor parameters. (Alan Woodward) New Features --------------------- diff --git a/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene70/Lucene70SegmentInfoFormat.java b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene70/Lucene70SegmentInfoFormat.java index 7f9fac4deede..50176c83ab33 100644 --- a/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene70/Lucene70SegmentInfoFormat.java +++ b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene70/Lucene70SegmentInfoFormat.java @@ -231,15 +231,6 @@ private SegmentInfo parseSegmentInfo( throw new CorruptIndexException("invalid index sort reverse: " + b, input); } - if (sortedSetSelector != null) { - sortFields[i] = new SortedSetSortField(fieldName, reverse, sortedSetSelector); - } else if (sortedNumericSelector != null) { - sortFields[i] = - new SortedNumericSortField(fieldName, sortType, reverse, sortedNumericSelector); - } else { - sortFields[i] = new SortField(fieldName, sortType, reverse); - } - Object missingValue; b = input.readByte(); if (b == 0) { @@ -288,8 +279,16 @@ private SegmentInfo parseSegmentInfo( throw new AssertionError("unhandled sortType=" + sortType); } } - if (missingValue != null) { - sortFields[i].setMissingValue(missingValue); + + if (sortedSetSelector != null) { + sortFields[i] = + new SortedSetSortField(fieldName, reverse, sortedSetSelector, missingValue); + } else if (sortedNumericSelector != null) { + sortFields[i] = + new SortedNumericSortField( + fieldName, sortType, reverse, sortedNumericSelector, missingValue); + } else { + sortFields[i] = new SortField(fieldName, sortType, reverse); } } indexSort = new Sort(sortFields); diff --git a/lucene/core/src/java/org/apache/lucene/document/DoubleField.java b/lucene/core/src/java/org/apache/lucene/document/DoubleField.java index 8eaf88524631..4771e5c150e1 100644 --- a/lucene/core/src/java/org/apache/lucene/document/DoubleField.java +++ b/lucene/core/src/java/org/apache/lucene/document/DoubleField.java @@ -179,6 +179,20 @@ public static Query newSetQuery(String field, double... values) { */ public static SortField newSortField( String field, boolean reverse, SortedNumericSelector.Type selector) { - return new SortedNumericSortField(field, SortField.Type.DOUBLE, reverse, selector); + return new SortedNumericSortField(field, SortField.Type.DOUBLE, reverse, selector, null); + } + + /** + * Create a new {@link SortField} for double values. + * + * @param field field name. must not be {@code null}. + * @param reverse true if natural order should be reversed. + * @param selector custom selector type for choosing the sort value from the set. + * @param missingValue a sort value to use for documents with no value in the field + */ + public static SortField newSortField( + String field, boolean reverse, SortedNumericSelector.Type selector, double missingValue) { + return new SortedNumericSortField( + field, SortField.Type.DOUBLE, reverse, selector, missingValue); } } diff --git a/lucene/core/src/java/org/apache/lucene/document/FloatField.java b/lucene/core/src/java/org/apache/lucene/document/FloatField.java index 12eb131cb0fb..e7b475eb0ec0 100644 --- a/lucene/core/src/java/org/apache/lucene/document/FloatField.java +++ b/lucene/core/src/java/org/apache/lucene/document/FloatField.java @@ -179,6 +179,19 @@ public static Query newSetQuery(String field, float... values) { */ public static SortField newSortField( String field, boolean reverse, SortedNumericSelector.Type selector) { - return new SortedNumericSortField(field, SortField.Type.FLOAT, reverse, selector); + return new SortedNumericSortField(field, SortField.Type.FLOAT, reverse, selector, null); + } + + /** + * Create a new {@link SortField} for float values. + * + * @param field field name. must not be {@code null}. + * @param reverse true if natural order should be reversed. + * @param selector custom selector type for choosing the sort value from the set. + * @param missingValue a sort value to use for documents with no value in the field + */ + public static SortField newSortField( + String field, boolean reverse, SortedNumericSelector.Type selector, float missingValue) { + return new SortedNumericSortField(field, SortField.Type.FLOAT, reverse, selector, missingValue); } } diff --git a/lucene/core/src/java/org/apache/lucene/document/IntField.java b/lucene/core/src/java/org/apache/lucene/document/IntField.java index b6a3493e1040..fc03d1a6de5c 100644 --- a/lucene/core/src/java/org/apache/lucene/document/IntField.java +++ b/lucene/core/src/java/org/apache/lucene/document/IntField.java @@ -172,6 +172,19 @@ public static Query newSetQuery(String field, int... values) { */ public static SortField newSortField( String field, boolean reverse, SortedNumericSelector.Type selector) { - return new SortedNumericSortField(field, SortField.Type.INT, reverse, selector); + return new SortedNumericSortField(field, SortField.Type.INT, reverse, selector, null); + } + + /** + * Create a new {@link SortField} for int values. + * + * @param field field name. must not be {@code null}. + * @param reverse true if natural order should be reversed. + * @param selector custom selector type for choosing the sort value from the set. + * @param missingValue a sort value to use for documents with no value in the field + */ + public static SortField newSortField( + String field, boolean reverse, SortedNumericSelector.Type selector, int missingValue) { + return new SortedNumericSortField(field, SortField.Type.INT, reverse, selector, missingValue); } } diff --git a/lucene/core/src/java/org/apache/lucene/document/KeywordField.java b/lucene/core/src/java/org/apache/lucene/document/KeywordField.java index 2ed22b2e1413..bc61550bd399 100644 --- a/lucene/core/src/java/org/apache/lucene/document/KeywordField.java +++ b/lucene/core/src/java/org/apache/lucene/document/KeywordField.java @@ -178,6 +178,20 @@ public static Query newSetQuery(String field, Collection values) { MultiTermQuery.CONSTANT_SCORE_BLENDED_REWRITE, field, values); } + /** + * Create a new {@link SortField} for {@link BytesRef} values. + * + * @param field field name. must not be {@code null}. + * @param reverse true if natural order should be reversed. + * @param selector custom selector type for choosing the sort value from the set. + */ + public static SortField newSortField( + String field, boolean reverse, SortedSetSelector.Type selector, Object missingValue) { + Objects.requireNonNull(field, "field must not be null"); + Objects.requireNonNull(selector, "selector must not be null"); + return new SortedSetSortField(field, reverse, selector, missingValue); + } + /** * Create a new {@link SortField} for {@link BytesRef} values. * @@ -189,6 +203,6 @@ public static SortField newSortField( String field, boolean reverse, SortedSetSelector.Type selector) { Objects.requireNonNull(field, "field must not be null"); Objects.requireNonNull(selector, "selector must not be null"); - return new SortedSetSortField(field, reverse, selector); + return new SortedSetSortField(field, reverse, selector, null); } } diff --git a/lucene/core/src/java/org/apache/lucene/document/LatLonPointSortField.java b/lucene/core/src/java/org/apache/lucene/document/LatLonPointSortField.java index 9c4c0e8f8613..e8e0ee36a451 100644 --- a/lucene/core/src/java/org/apache/lucene/document/LatLonPointSortField.java +++ b/lucene/core/src/java/org/apache/lucene/document/LatLonPointSortField.java @@ -27,7 +27,7 @@ final class LatLonPointSortField extends SortField { final double longitude; LatLonPointSortField(String field, double latitude, double longitude) { - super(field, SortField.Type.CUSTOM); + super(field, SortField.Type.CUSTOM, false, Double.POSITIVE_INFINITY); if (field == null) { throw new IllegalArgumentException("field must not be null"); } @@ -35,7 +35,6 @@ final class LatLonPointSortField extends SortField { GeoUtils.checkLongitude(longitude); this.latitude = latitude; this.longitude = longitude; - setMissingValue(Double.POSITIVE_INFINITY); } @Override diff --git a/lucene/core/src/java/org/apache/lucene/document/LongField.java b/lucene/core/src/java/org/apache/lucene/document/LongField.java index 65fadfd41243..568d9d6bef68 100644 --- a/lucene/core/src/java/org/apache/lucene/document/LongField.java +++ b/lucene/core/src/java/org/apache/lucene/document/LongField.java @@ -172,7 +172,20 @@ public static Query newSetQuery(String field, long... values) { */ public static SortField newSortField( String field, boolean reverse, SortedNumericSelector.Type selector) { - return new SortedNumericSortField(field, SortField.Type.LONG, reverse, selector); + return new SortedNumericSortField(field, SortField.Type.LONG, reverse, selector, null); + } + + /** + * Create a new {@link SortField} for long values. + * + * @param field field name. must not be {@code null}. + * @param reverse true if natural order should be reversed. + * @param selector custom selector type for choosing the sort value from the set. + * @param missingValue a sort value to use for documents with no value in the field + */ + public static SortField newSortField( + String field, boolean reverse, SortedNumericSelector.Type selector, long missingValue) { + return new SortedNumericSortField(field, SortField.Type.LONG, reverse, selector, missingValue); } /** diff --git a/lucene/core/src/java/org/apache/lucene/document/XYPointSortField.java b/lucene/core/src/java/org/apache/lucene/document/XYPointSortField.java index f5727888ab80..2c8c8b4a005e 100644 --- a/lucene/core/src/java/org/apache/lucene/document/XYPointSortField.java +++ b/lucene/core/src/java/org/apache/lucene/document/XYPointSortField.java @@ -26,13 +26,12 @@ final class XYPointSortField extends SortField { final float y; XYPointSortField(String field, float x, float y) { - super(field, Type.CUSTOM); + super(field, Type.CUSTOM, false, Double.POSITIVE_INFINITY); if (field == null) { throw new IllegalArgumentException("field must not be null"); } this.x = x; this.y = y; - setMissingValue(Double.POSITIVE_INFINITY); } @Override diff --git a/lucene/core/src/java/org/apache/lucene/search/DoubleValuesSource.java b/lucene/core/src/java/org/apache/lucene/search/DoubleValuesSource.java index 903c1e9a8b6b..e6a55316f00d 100644 --- a/lucene/core/src/java/org/apache/lucene/search/DoubleValuesSource.java +++ b/lucene/core/src/java/org/apache/lucene/search/DoubleValuesSource.java @@ -98,7 +98,17 @@ public Explanation explain(LeafReaderContext ctx, int docId, Explanation scoreEx * @param reverse true if the sort should be decreasing */ public SortField getSortField(boolean reverse) { - return new DoubleValuesSortField(this, reverse); + return new DoubleValuesSortField(this, reverse, 0); + } + + /** + * Create a sort field based on the value of this producer + * + * @param reverse true if the sort should be decreasing + * @param missingValue a placeholder to use for documents with no value + */ + public SortField getSortField(boolean reverse, double missingValue) { + return new DoubleValuesSortField(this, reverse, missingValue); } @Override @@ -514,8 +524,8 @@ private static class DoubleValuesSortField extends SortField { final DoubleValuesSource producer; - DoubleValuesSortField(DoubleValuesSource producer, boolean reverse) { - super(producer.toString(), new DoubleValuesComparatorSource(producer), reverse); + DoubleValuesSortField(DoubleValuesSource producer, boolean reverse, double missingValue) { + super(producer.toString(), new DoubleValuesComparatorSource(producer, missingValue), reverse); this.producer = producer; } @@ -549,11 +559,10 @@ public SortField rewrite(IndexSearcher searcher) throws IOException { if (rewrittenSource == producer) { return this; } - DoubleValuesSortField rewritten = new DoubleValuesSortField(rewrittenSource, reverse); - if (missingValue != null) { - rewritten.setMissingValue(missingValue); - } - return rewritten; + return new DoubleValuesSortField( + rewrittenSource, + reverse, + ((DoubleValuesComparatorSource) getComparatorSource()).missingValue); } } @@ -565,9 +574,9 @@ private static class DoubleValuesComparatorSource extends FieldComparatorSource private final DoubleValuesSource producer; private double missingValue; - DoubleValuesComparatorSource(DoubleValuesSource producer) { + DoubleValuesComparatorSource(DoubleValuesSource producer, double missingValue) { this.producer = producer; - this.missingValue = 0d; + this.missingValue = missingValue; } void setMissingValue(double missingValue) { diff --git a/lucene/core/src/java/org/apache/lucene/search/LongValuesSource.java b/lucene/core/src/java/org/apache/lucene/search/LongValuesSource.java index c6756ff67637..86f4f4daff65 100644 --- a/lucene/core/src/java/org/apache/lucene/search/LongValuesSource.java +++ b/lucene/core/src/java/org/apache/lucene/search/LongValuesSource.java @@ -75,7 +75,17 @@ public abstract LongValues getValues(LeafReaderContext ctx, DoubleValues scores) * @param reverse true if the sort should be decreasing */ public SortField getSortField(boolean reverse) { - return new LongValuesSortField(this, reverse); + return new LongValuesSortField(this, reverse, 0); + } + + /** + * Create a sort field based on the value of this producer + * + * @param reverse true if the sort should be decreasing + * @param missingValue a placeholder to use for documents with no value + */ + public SortField getSortField(boolean reverse, long missingValue) { + return new LongValuesSortField(this, reverse, missingValue); } /** Convert to a DoubleValuesSource by casting long values to doubles */ @@ -275,8 +285,8 @@ private static class LongValuesSortField extends SortField { final LongValuesSource producer; - public LongValuesSortField(LongValuesSource producer, boolean reverse) { - super(producer.toString(), new LongValuesComparatorSource(producer), reverse); + public LongValuesSortField(LongValuesSource producer, boolean reverse, long missingValue) { + super(producer.toString(), new LongValuesComparatorSource(producer, missingValue), reverse); this.producer = producer; } @@ -310,11 +320,10 @@ public SortField rewrite(IndexSearcher searcher) throws IOException { if (producer == rewrittenSource) { return this; } - LongValuesSortField rewritten = new LongValuesSortField(rewrittenSource, reverse); - if (missingValue != null) { - rewritten.setMissingValue(missingValue); - } - return rewritten; + return new LongValuesSortField( + rewrittenSource, + reverse, + ((LongValuesComparatorSource) getComparatorSource()).missingValue); } } @@ -326,9 +335,9 @@ private static class LongValuesComparatorSource extends FieldComparatorSource { private final LongValuesSource producer; private long missingValue; - public LongValuesComparatorSource(LongValuesSource producer) { + public LongValuesComparatorSource(LongValuesSource producer, long missingValue) { this.producer = producer; - this.missingValue = 0L; + this.missingValue = missingValue; } void setMissingValue(long missingValue) { diff --git a/lucene/core/src/java/org/apache/lucene/search/SortField.java b/lucene/core/src/java/org/apache/lucene/search/SortField.java index 4f35429f3c7f..9cb7f89c155e 100644 --- a/lucene/core/src/java/org/apache/lucene/search/SortField.java +++ b/lucene/core/src/java/org/apache/lucene/search/SortField.java @@ -146,7 +146,18 @@ public enum Type { * @param type Type of values in the terms. */ public SortField(String field, Type type) { - this(field, type, false); + this(field, type, false, null); + } + + /** + * Creates a sort by terms in the given field with the type of term values explicitly given. + * + * @param field Name of field to sort by. Can be null if type is SCORE + * or DOC. + * @param type Type of values in the terms. + */ + public SortField(String field, Type type, boolean reverse) { + this(field, type, reverse, null); } /** @@ -158,11 +169,12 @@ public SortField(String field, Type type) { * @param type Type of values in the terms. * @param reverse True if natural order should be reversed. */ - public SortField(String field, Type type, boolean reverse) { + public SortField(String field, Type type, boolean reverse, Object missingValue) { this.field = field; this.type = type; this.reverse = reverse; - validateField(field, type); + this.missingValue = missingValue; + validateField(field, type, missingValue); } /** @@ -187,7 +199,8 @@ public SortField(String field, FieldComparatorSource comparator, boolean reverse this.type = Type.CUSTOM; this.reverse = reverse; this.comparatorSource = comparator; - validateField(field, type); + this.missingValue = null; // missingValue factored into comparator source + validateField(field, type, null); } /** A SortFieldProvider for field sorts */ @@ -203,40 +216,39 @@ public Provider() { @Override public SortField readSortField(DataInput in) throws IOException { - SortField sf = new SortField(in.readString(), readType(in), in.readInt() == 1); + String field = in.readString(); + Type type = readType(in); + boolean reverse = in.readInt() == 1; if (in.readInt() == 1) { // missing object - switch (sf.type) { + switch (type) { case STRING: int missingString = in.readInt(); if (missingString == 1) { - sf.setMissingValue(STRING_FIRST); + return new SortField(field, type, reverse, STRING_FIRST); } else { - sf.setMissingValue(STRING_LAST); + return new SortField(field, type, reverse, STRING_LAST); } - break; case INT: - sf.setMissingValue(in.readInt()); - break; + return new SortField(field, type, reverse, in.readInt()); case LONG: - sf.setMissingValue(in.readLong()); - break; + return new SortField(field, type, reverse, in.readLong()); case FLOAT: - sf.setMissingValue(NumericUtils.sortableIntToFloat(in.readInt())); - break; + return new SortField( + field, type, reverse, NumericUtils.sortableIntToFloat(in.readInt())); case DOUBLE: - sf.setMissingValue(NumericUtils.sortableLongToDouble(in.readLong())); - break; + return new SortField( + field, type, reverse, NumericUtils.sortableLongToDouble(in.readLong())); case CUSTOM: case DOC: case REWRITEABLE: case STRING_VAL: case SCORE: default: - throw new IllegalArgumentException("Cannot deserialize sort of type " + sf.type); + throw new IllegalArgumentException("Cannot deserialize sort of type " + type); } } - return sf; + return new SortField(field, type, reverse, null); } @Override @@ -323,6 +335,7 @@ public Object getMissingValue() { } /** Set the value to use for documents that don't have a value. */ + @Deprecated public void setMissingValue(Object missingValue) { if (type == Type.STRING || type == Type.STRING_VAL) { if (missingValue != STRING_FIRST && missingValue != STRING_LAST) { @@ -357,12 +370,18 @@ public void setMissingValue(Object missingValue) { // Sets field & type, and ensures field is not NULL unless // type is SCORE or DOC - private void validateField(String field, Type type) { + private void validateField(String field, Type type, Object missingValue) { if (field == null) { if (type != Type.SCORE && type != Type.DOC) { throw new IllegalArgumentException("field can only be null when type is SCORE or DOC"); } } + if (type == Type.STRING) { + if (missingValue != null && missingValue != STRING_FIRST && missingValue != STRING_LAST) { + throw new IllegalArgumentException( + "For Type.STRING, missing value must be either STRING_FIRST or STRING_LAST"); + } + } } /** diff --git a/lucene/core/src/java/org/apache/lucene/search/SortedNumericSortField.java b/lucene/core/src/java/org/apache/lucene/search/SortedNumericSortField.java index 614df387d985..345a16805105 100644 --- a/lucene/core/src/java/org/apache/lucene/search/SortedNumericSortField.java +++ b/lucene/core/src/java/org/apache/lucene/search/SortedNumericSortField.java @@ -69,7 +69,7 @@ public SortedNumericSortField(String field, SortField.Type type) { * @param reverse True if natural order should be reversed. */ public SortedNumericSortField(String field, SortField.Type type, boolean reverse) { - this(field, type, reverse, SortedNumericSelector.Type.MIN); + this(field, type, reverse, SortedNumericSelector.Type.MIN, null); } /** @@ -83,7 +83,26 @@ public SortedNumericSortField(String field, SortField.Type type, boolean reverse */ public SortedNumericSortField( String field, SortField.Type type, boolean reverse, SortedNumericSelector.Type selector) { - super(field, SortField.Type.CUSTOM, reverse); + this(field, type, reverse, selector, null); + } + + /** + * Creates a sort, possibly in reverse, specifying how the sort value from the document's set is + * selected. + * + * @param field Name of field to sort by. Must not be null. + * @param type Type of values + * @param reverse True if natural order should be reversed. + * @param selector custom selector type for choosing the sort value from the set. + * @param missingValue the sort value to use for documents with no value in the field + */ + public SortedNumericSortField( + String field, + SortField.Type type, + boolean reverse, + SortedNumericSelector.Type selector, + Object missingValue) { + super(field, SortField.Type.CUSTOM, reverse, missingValue); if (selector == null) { throw new NullPointerException(); } @@ -107,34 +126,34 @@ public Provider() { @Override public SortField readSortField(DataInput in) throws IOException { - SortedNumericSortField sf = - new SortedNumericSortField( - in.readString(), readType(in), in.readInt() == 1, readSelectorType(in)); + String field = in.readString(); + Type type = readType(in); + boolean reverse = in.readInt() == 1; + SortedNumericSelector.Type selectorType = readSelectorType(in); if (in.readInt() == 1) { - switch (sf.type) { - case INT: - sf.setMissingValue(in.readInt()); - break; - case LONG: - sf.setMissingValue(in.readLong()); - break; - case FLOAT: - sf.setMissingValue(NumericUtils.sortableIntToFloat(in.readInt())); - break; - case DOUBLE: - sf.setMissingValue(NumericUtils.sortableLongToDouble(in.readLong())); - break; - case CUSTOM: - case DOC: - case REWRITEABLE: - case STRING_VAL: - case SCORE: - case STRING: - default: - throw new AssertionError(); - } + return switch (type) { + case INT -> new SortedNumericSortField(field, type, reverse, selectorType, in.readInt()); + case LONG -> + new SortedNumericSortField(field, type, reverse, selectorType, in.readLong()); + case FLOAT -> + new SortedNumericSortField( + field, + type, + reverse, + selectorType, + NumericUtils.sortableIntToFloat(in.readInt())); + case DOUBLE -> + new SortedNumericSortField( + field, + type, + reverse, + selectorType, + NumericUtils.sortableLongToDouble(in.readLong())); + // $CASES-OMITTED$ + default -> throw new AssertionError(); + }; } - return sf; + return new SortedNumericSortField(field, type, reverse, selectorType, null); } @Override diff --git a/lucene/core/src/java/org/apache/lucene/search/SortedSetSortField.java b/lucene/core/src/java/org/apache/lucene/search/SortedSetSortField.java index f170d94a62cd..3a2acbcd5718 100644 --- a/lucene/core/src/java/org/apache/lucene/search/SortedSetSortField.java +++ b/lucene/core/src/java/org/apache/lucene/search/SortedSetSortField.java @@ -54,7 +54,11 @@ public class SortedSetSortField extends SortField { * @param reverse True if natural order should be reversed. */ public SortedSetSortField(String field, boolean reverse) { - this(field, reverse, SortedSetSelector.Type.MIN); + this(field, reverse, SortedSetSelector.Type.MIN, null); + } + + public SortedSetSortField(String field, boolean reverse, SortedSetSelector.Type selector) { + this(field, reverse, selector, null); } /** @@ -67,8 +71,9 @@ public SortedSetSortField(String field, boolean reverse) { *

NOTE: selectors other than {@link SortedSetSelector.Type#MIN} require optional codec * support. */ - public SortedSetSortField(String field, boolean reverse, SortedSetSelector.Type selector) { - super(field, SortField.Type.CUSTOM, reverse); + public SortedSetSortField( + String field, boolean reverse, SortedSetSelector.Type selector, Object missingValue) { + super(field, SortField.Type.CUSTOM, reverse, missingValue); if (selector == null) { throw new NullPointerException(); } @@ -88,15 +93,16 @@ public Provider() { @Override public SortField readSortField(DataInput in) throws IOException { - SortField sf = - new SortedSetSortField(in.readString(), in.readInt() == 1, readSelectorType(in)); + String field = in.readString(); + boolean reverse = in.readInt() == 1; + SortedSetSelector.Type type = readSelectorType(in); int missingValue = in.readInt(); if (missingValue == 1) { - sf.setMissingValue(SortField.STRING_FIRST); + return new SortedSetSortField(field, reverse, type, SortField.STRING_FIRST); } else if (missingValue == 2) { - sf.setMissingValue(SortField.STRING_LAST); + return new SortedSetSortField(field, reverse, type, SortField.STRING_LAST); } - return sf; + return new SortedSetSortField(field, reverse, type, null); } @Override diff --git a/lucene/core/src/test/org/apache/lucene/document/TestLatLonPointDistanceSort.java b/lucene/core/src/test/org/apache/lucene/document/TestLatLonPointDistanceSort.java index f114aac85949..0cd0d58208b3 100644 --- a/lucene/core/src/test/org/apache/lucene/document/TestLatLonPointDistanceSort.java +++ b/lucene/core/src/test/org/apache/lucene/document/TestLatLonPointDistanceSort.java @@ -238,7 +238,6 @@ private void doRandomTest(int numDocs, int numQueries) throws IOException { int topN = TestUtil.nextInt(random(), 1, reader.maxDoc()); // sort by distance, then ID SortField distanceSort = LatLonDocValuesField.newDistanceSort("field", lat, lon); - distanceSort.setMissingValue(missingValue); Sort sort = new Sort(distanceSort, new SortField("id", SortField.Type.INT)); TopDocs topDocs = searcher.search(new MatchAllDocsQuery(), topN, sort); diff --git a/lucene/core/src/test/org/apache/lucene/index/TestIndexSorting.java b/lucene/core/src/test/org/apache/lucene/index/TestIndexSorting.java index 4b1b2ccda8c3..2a06ebfcc73c 100644 --- a/lucene/core/src/test/org/apache/lucene/index/TestIndexSorting.java +++ b/lucene/core/src/test/org/apache/lucene/index/TestIndexSorting.java @@ -72,7 +72,9 @@ import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.Sort; import org.apache.lucene.search.SortField; +import org.apache.lucene.search.SortedNumericSelector; import org.apache.lucene.search.SortedNumericSortField; +import org.apache.lucene.search.SortedSetSelector; import org.apache.lucene.search.SortedSetSortField; import org.apache.lucene.search.TermQuery; import org.apache.lucene.search.TermStatistics; @@ -373,8 +375,8 @@ public void testMissingStringFirst() throws Exception { for (boolean reverse : new boolean[] {true, false}) { Directory dir = newDirectory(); IndexWriterConfig iwc = new IndexWriterConfig(new MockAnalyzer(random())); - SortField sortField = new SortField("foo", SortField.Type.STRING, reverse); - sortField.setMissingValue(SortField.STRING_FIRST); + SortField sortField = + new SortField("foo", SortField.Type.STRING, reverse, SortField.STRING_FIRST); Sort indexSort = new Sort(sortField); iwc.setIndexSort(indexSort); IndexWriter w = new IndexWriter(dir, iwc); @@ -420,8 +422,9 @@ public void testMissingMultiValuedStringFirst() throws Exception { for (boolean reverse : new boolean[] {true, false}) { Directory dir = newDirectory(); IndexWriterConfig iwc = new IndexWriterConfig(new MockAnalyzer(random())); - SortField sortField = new SortedSetSortField("foo", reverse); - sortField.setMissingValue(SortField.STRING_FIRST); + SortField sortField = + new SortedSetSortField( + "foo", reverse, SortedSetSelector.Type.MIN, SortField.STRING_FIRST); Sort indexSort = new Sort(sortField); iwc.setIndexSort(indexSort); IndexWriter w = new IndexWriter(dir, iwc); @@ -477,8 +480,8 @@ public void testMissingStringLast() throws Exception { for (boolean reverse : new boolean[] {true, false}) { Directory dir = newDirectory(); IndexWriterConfig iwc = new IndexWriterConfig(new MockAnalyzer(random())); - SortField sortField = new SortField("foo", SortField.Type.STRING, reverse); - sortField.setMissingValue(SortField.STRING_LAST); + SortField sortField = + new SortField("foo", SortField.Type.STRING, reverse, SortField.STRING_LAST); Sort indexSort = new Sort(sortField); iwc.setIndexSort(indexSort); IndexWriter w = new IndexWriter(dir, iwc); @@ -524,8 +527,8 @@ public void testMissingMultiValuedStringLast() throws Exception { for (boolean reverse : new boolean[] {true, false}) { Directory dir = newDirectory(); IndexWriterConfig iwc = new IndexWriterConfig(new MockAnalyzer(random())); - SortField sortField = new SortedSetSortField("foo", reverse); - sortField.setMissingValue(SortField.STRING_LAST); + SortField sortField = + new SortedSetSortField("foo", reverse, SortedSetSelector.Type.MIN, SortField.STRING_LAST); Sort indexSort = new Sort(sortField); iwc.setIndexSort(indexSort); IndexWriter w = new IndexWriter(dir, iwc); @@ -661,8 +664,7 @@ public void testMissingLongFirst() throws Exception { for (boolean reverse : new boolean[] {true, false}) { Directory dir = newDirectory(); IndexWriterConfig iwc = new IndexWriterConfig(new MockAnalyzer(random())); - SortField sortField = new SortField("foo", SortField.Type.LONG, reverse); - sortField.setMissingValue(Long.MIN_VALUE); + SortField sortField = new SortField("foo", SortField.Type.LONG, reverse, Long.MIN_VALUE); Sort indexSort = new Sort(sortField); iwc.setIndexSort(indexSort); IndexWriter w = new IndexWriter(dir, iwc); @@ -708,8 +710,9 @@ public void testMissingMultiValuedLongFirst() throws Exception { for (boolean reverse : new boolean[] {true, false}) { Directory dir = newDirectory(); IndexWriterConfig iwc = new IndexWriterConfig(new MockAnalyzer(random())); - SortField sortField = new SortedNumericSortField("foo", SortField.Type.LONG, reverse); - sortField.setMissingValue(Long.MIN_VALUE); + SortField sortField = + new SortedNumericSortField( + "foo", SortField.Type.LONG, reverse, SortedNumericSelector.Type.MIN, Long.MIN_VALUE); Sort indexSort = new Sort(sortField); iwc.setIndexSort(indexSort); IndexWriter w = new IndexWriter(dir, iwc); @@ -764,8 +767,7 @@ public void testMissingLongLast() throws Exception { for (boolean reverse : new boolean[] {true, false}) { Directory dir = newDirectory(); IndexWriterConfig iwc = new IndexWriterConfig(new MockAnalyzer(random())); - SortField sortField = new SortField("foo", SortField.Type.LONG, reverse); - sortField.setMissingValue(Long.MAX_VALUE); + SortField sortField = new SortField("foo", SortField.Type.LONG, reverse, Long.MAX_VALUE); Sort indexSort = new Sort(sortField); iwc.setIndexSort(indexSort); IndexWriter w = new IndexWriter(dir, iwc); @@ -812,8 +814,9 @@ public void testMissingMultiValuedLongLast() throws Exception { for (boolean reverse : new boolean[] {true, false}) { Directory dir = newDirectory(); IndexWriterConfig iwc = new IndexWriterConfig(new MockAnalyzer(random())); - SortField sortField = new SortedNumericSortField("foo", SortField.Type.LONG, reverse); - sortField.setMissingValue(Long.MAX_VALUE); + SortField sortField = + new SortedNumericSortField( + "foo", SortField.Type.LONG, reverse, SortedNumericSelector.Type.MIN, Long.MAX_VALUE); Sort indexSort = new Sort(sortField); iwc.setIndexSort(indexSort); IndexWriter w = new IndexWriter(dir, iwc); @@ -952,8 +955,7 @@ public void testMissingIntFirst() throws Exception { for (boolean reverse : new boolean[] {true, false}) { Directory dir = newDirectory(); IndexWriterConfig iwc = new IndexWriterConfig(new MockAnalyzer(random())); - SortField sortField = new SortField("foo", SortField.Type.INT, reverse); - sortField.setMissingValue(Integer.MIN_VALUE); + SortField sortField = new SortField("foo", SortField.Type.INT, reverse, Integer.MIN_VALUE); Sort indexSort = new Sort(sortField); iwc.setIndexSort(indexSort); IndexWriter w = new IndexWriter(dir, iwc); @@ -998,8 +1000,13 @@ public void testMissingMultiValuedIntFirst() throws Exception { for (boolean reverse : new boolean[] {true, false}) { Directory dir = newDirectory(); IndexWriterConfig iwc = new IndexWriterConfig(new MockAnalyzer(random())); - SortField sortField = new SortedNumericSortField("foo", SortField.Type.INT, reverse); - sortField.setMissingValue(Integer.MIN_VALUE); + SortField sortField = + new SortedNumericSortField( + "foo", + SortField.Type.INT, + reverse, + SortedNumericSelector.Type.MIN, + Integer.MIN_VALUE); Sort indexSort = new Sort(sortField); iwc.setIndexSort(indexSort); IndexWriter w = new IndexWriter(dir, iwc); @@ -1054,8 +1061,7 @@ public void testMissingIntLast() throws Exception { for (boolean reverse : new boolean[] {true, false}) { Directory dir = newDirectory(); IndexWriterConfig iwc = new IndexWriterConfig(new MockAnalyzer(random())); - SortField sortField = new SortField("foo", SortField.Type.INT, reverse); - sortField.setMissingValue(Integer.MAX_VALUE); + SortField sortField = new SortField("foo", SortField.Type.INT, reverse, Integer.MAX_VALUE); Sort indexSort = new Sort(sortField); iwc.setIndexSort(indexSort); IndexWriter w = new IndexWriter(dir, iwc); @@ -1102,8 +1108,13 @@ public void testMissingMultiValuedIntLast() throws Exception { for (boolean reverse : new boolean[] {true, false}) { Directory dir = newDirectory(); IndexWriterConfig iwc = new IndexWriterConfig(new MockAnalyzer(random())); - SortField sortField = new SortedNumericSortField("foo", SortField.Type.INT, reverse); - sortField.setMissingValue(Integer.MAX_VALUE); + SortField sortField = + new SortedNumericSortField( + "foo", + SortField.Type.INT, + reverse, + SortedNumericSelector.Type.MIN, + Integer.MAX_VALUE); Sort indexSort = new Sort(sortField); iwc.setIndexSort(indexSort); IndexWriter w = new IndexWriter(dir, iwc); @@ -1240,8 +1251,8 @@ public void testMissingDoubleFirst() throws Exception { for (boolean reverse : new boolean[] {true, false}) { Directory dir = newDirectory(); IndexWriterConfig iwc = new IndexWriterConfig(new MockAnalyzer(random())); - SortField sortField = new SortField("foo", SortField.Type.DOUBLE, reverse); - sortField.setMissingValue(Double.NEGATIVE_INFINITY); + SortField sortField = + new SortField("foo", SortField.Type.DOUBLE, reverse, Double.NEGATIVE_INFINITY); Sort indexSort = new Sort(sortField); iwc.setIndexSort(indexSort); IndexWriter w = new IndexWriter(dir, iwc); @@ -1286,8 +1297,13 @@ public void testMissingMultiValuedDoubleFirst() throws Exception { for (boolean reverse : new boolean[] {true, false}) { Directory dir = newDirectory(); IndexWriterConfig iwc = new IndexWriterConfig(new MockAnalyzer(random())); - SortField sortField = new SortedNumericSortField("foo", SortField.Type.DOUBLE, reverse); - sortField.setMissingValue(Double.NEGATIVE_INFINITY); + SortField sortField = + new SortedNumericSortField( + "foo", + SortField.Type.DOUBLE, + reverse, + SortedNumericSelector.Type.MIN, + Double.NEGATIVE_INFINITY); Sort indexSort = new Sort(sortField); iwc.setIndexSort(indexSort); IndexWriter w = new IndexWriter(dir, iwc); @@ -1342,8 +1358,8 @@ public void testMissingDoubleLast() throws Exception { for (boolean reverse : new boolean[] {true, false}) { Directory dir = newDirectory(); IndexWriterConfig iwc = new IndexWriterConfig(new MockAnalyzer(random())); - SortField sortField = new SortField("foo", SortField.Type.DOUBLE, reverse); - sortField.setMissingValue(Double.POSITIVE_INFINITY); + SortField sortField = + new SortField("foo", SortField.Type.DOUBLE, reverse, Double.POSITIVE_INFINITY); Sort indexSort = new Sort(sortField); iwc.setIndexSort(indexSort); IndexWriter w = new IndexWriter(dir, iwc); @@ -1389,8 +1405,13 @@ public void testMissingMultiValuedDoubleLast() throws Exception { for (boolean reverse : new boolean[] {true, false}) { Directory dir = newDirectory(); IndexWriterConfig iwc = new IndexWriterConfig(new MockAnalyzer(random())); - SortField sortField = new SortedNumericSortField("foo", SortField.Type.DOUBLE, reverse); - sortField.setMissingValue(Double.POSITIVE_INFINITY); + SortField sortField = + new SortedNumericSortField( + "foo", + SortField.Type.DOUBLE, + reverse, + SortedNumericSelector.Type.MIN, + Double.POSITIVE_INFINITY); Sort indexSort = new Sort(sortField); iwc.setIndexSort(indexSort); IndexWriter w = new IndexWriter(dir, iwc); @@ -1526,8 +1547,8 @@ public void testMissingFloatFirst() throws Exception { for (boolean reverse : new boolean[] {true, false}) { Directory dir = newDirectory(); IndexWriterConfig iwc = new IndexWriterConfig(new MockAnalyzer(random())); - SortField sortField = new SortField("foo", SortField.Type.FLOAT, reverse); - sortField.setMissingValue(Float.NEGATIVE_INFINITY); + SortField sortField = + new SortField("foo", SortField.Type.FLOAT, reverse, Float.NEGATIVE_INFINITY); Sort indexSort = new Sort(sortField); iwc.setIndexSort(indexSort); IndexWriter w = new IndexWriter(dir, iwc); @@ -1572,8 +1593,13 @@ public void testMissingMultiValuedFloatFirst() throws Exception { for (boolean reverse : new boolean[] {true, false}) { Directory dir = newDirectory(); IndexWriterConfig iwc = new IndexWriterConfig(new MockAnalyzer(random())); - SortField sortField = new SortedNumericSortField("foo", SortField.Type.FLOAT, reverse); - sortField.setMissingValue(Float.NEGATIVE_INFINITY); + SortField sortField = + new SortedNumericSortField( + "foo", + SortField.Type.FLOAT, + reverse, + SortedNumericSelector.Type.MIN, + Float.NEGATIVE_INFINITY); Sort indexSort = new Sort(sortField); iwc.setIndexSort(indexSort); IndexWriter w = new IndexWriter(dir, iwc); @@ -1628,8 +1654,8 @@ public void testMissingFloatLast() throws Exception { for (boolean reverse : new boolean[] {true, false}) { Directory dir = newDirectory(); IndexWriterConfig iwc = new IndexWriterConfig(new MockAnalyzer(random())); - SortField sortField = new SortField("foo", SortField.Type.FLOAT, reverse); - sortField.setMissingValue(Float.POSITIVE_INFINITY); + SortField sortField = + new SortField("foo", SortField.Type.FLOAT, reverse, Float.POSITIVE_INFINITY); Sort indexSort = new Sort(sortField); iwc.setIndexSort(indexSort); IndexWriter w = new IndexWriter(dir, iwc); @@ -1675,8 +1701,13 @@ public void testMissingMultiValuedFloatLast() throws Exception { for (boolean reverse : new boolean[] {true, false}) { Directory dir = newDirectory(); IndexWriterConfig iwc = new IndexWriterConfig(new MockAnalyzer(random())); - SortField sortField = new SortedNumericSortField("foo", SortField.Type.FLOAT, reverse); - sortField.setMissingValue(Float.POSITIVE_INFINITY); + SortField sortField = + new SortedNumericSortField( + "foo", + SortField.Type.FLOAT, + reverse, + SortedNumericSelector.Type.MIN, + Float.POSITIVE_INFINITY); Sort indexSort = new Sort(sortField); iwc.setIndexSort(indexSort); IndexWriter w = new IndexWriter(dir, iwc); @@ -2458,75 +2489,76 @@ public RandomDoc(int id) { private static SortField randomIndexSortField() { boolean reversed = random().nextBoolean(); - SortField sortField; - switch (random().nextInt(10)) { - case 0: - sortField = new SortField("int", SortField.Type.INT, reversed); - if (random().nextBoolean()) { - sortField.setMissingValue(random().nextInt()); - } - break; - case 1: - sortField = new SortedNumericSortField("multi_valued_int", SortField.Type.INT, reversed); - if (random().nextBoolean()) { - sortField.setMissingValue(random().nextInt()); - } - break; - case 2: - sortField = new SortField("long", SortField.Type.LONG, reversed); - if (random().nextBoolean()) { - sortField.setMissingValue(random().nextLong()); - } - break; - case 3: - sortField = new SortedNumericSortField("multi_valued_long", SortField.Type.LONG, reversed); - if (random().nextBoolean()) { - sortField.setMissingValue(random().nextLong()); - } - break; - case 4: - sortField = new SortField("float", SortField.Type.FLOAT, reversed); - if (random().nextBoolean()) { - sortField.setMissingValue(random().nextFloat()); - } - break; - case 5: - sortField = - new SortedNumericSortField("multi_valued_float", SortField.Type.FLOAT, reversed); - if (random().nextBoolean()) { - sortField.setMissingValue(random().nextFloat()); - } - break; - case 6: - sortField = new SortField("double", SortField.Type.DOUBLE, reversed); - if (random().nextBoolean()) { - sortField.setMissingValue(random().nextDouble()); - } - break; - case 7: - sortField = - new SortedNumericSortField("multi_valued_double", SortField.Type.DOUBLE, reversed); - if (random().nextBoolean()) { - sortField.setMissingValue(random().nextDouble()); - } - break; - case 8: - sortField = new SortField("bytes", SortField.Type.STRING, reversed); - if (random().nextBoolean()) { - sortField.setMissingValue(SortField.STRING_LAST); - } - break; - case 9: - sortField = new SortedSetSortField("multi_valued_bytes", reversed); - if (random().nextBoolean()) { - sortField.setMissingValue(SortField.STRING_LAST); - } - break; - default: - sortField = null; + return switch (random().nextInt(10)) { + case 0 -> + new SortField( + "int", + SortField.Type.INT, + reversed, + random().nextBoolean() ? random().nextInt() : null); + case 1 -> + new SortedNumericSortField( + "multi_valued_int", + SortField.Type.INT, + reversed, + SortedNumericSelector.Type.MIN, + random().nextBoolean() ? random().nextInt() : null); + case 2 -> + new SortField( + "long", + SortField.Type.LONG, + reversed, + random().nextBoolean() ? random().nextLong() : null); + case 3 -> + new SortedNumericSortField( + "multi_valued_long", + SortField.Type.LONG, + reversed, + SortedNumericSelector.Type.MIN, + random().nextBoolean() ? random().nextLong() : null); + case 4 -> + new SortField( + "float", + SortField.Type.FLOAT, + reversed, + random().nextBoolean() ? random().nextFloat() : null); + case 5 -> + new SortedNumericSortField( + "multi_valued_float", + SortField.Type.FLOAT, + reversed, + SortedNumericSelector.Type.MIN, + random().nextBoolean() ? random().nextFloat() : null); + case 6 -> + new SortField( + "double", + SortField.Type.DOUBLE, + reversed, + random().nextBoolean() ? random().nextDouble() : null); + case 7 -> + new SortedNumericSortField( + "multi_valued_double", + SortField.Type.DOUBLE, + reversed, + SortedNumericSelector.Type.MIN, + random().nextBoolean() ? random().nextDouble() : null); + case 8 -> + new SortField( + "bytes", + SortField.Type.STRING, + reversed, + random().nextBoolean() ? SortField.STRING_LAST : null); + case 9 -> + new SortedSetSortField( + "multi_valued_bytes", + reversed, + SortedSetSelector.Type.MIN, + random().nextBoolean() ? SortField.STRING_LAST : null); + default -> { fail(); - } - return sortField; + yield null; + } + }; } private static Sort randomSort() { @@ -2775,8 +2807,7 @@ public void testIndexSortWithSparseField() throws Exception { public void testIndexSortOnSparseField() throws Exception { Directory dir = newDirectory(); IndexWriterConfig iwc = new IndexWriterConfig(new MockAnalyzer(random())); - SortField sortField = new SortField("sparse", SortField.Type.INT, false); - sortField.setMissingValue(Integer.MIN_VALUE); + SortField sortField = new SortField("sparse", SortField.Type.INT, false, Integer.MIN_VALUE); Sort indexSort = new Sort(sortField); iwc.setIndexSort(indexSort); IndexWriter w = new IndexWriter(dir, iwc); diff --git a/lucene/core/src/test/org/apache/lucene/search/TestDoubleValuesSource.java b/lucene/core/src/test/org/apache/lucene/search/TestDoubleValuesSource.java index f7242d5cfb23..59eacfd05899 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestDoubleValuesSource.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestDoubleValuesSource.java @@ -105,16 +105,14 @@ public void testSortMissingExplicit() throws Exception { DoubleValuesSource onefield = DoubleValuesSource.fromDoubleField("onefield"); // sort decreasing, missing last - SortField oneFieldSort = onefield.getSortField(true); - oneFieldSort.setMissingValue(Double.MIN_VALUE); + SortField oneFieldSort = onefield.getSortField(true, Double.MIN_VALUE); TopDocs results = searcher.search(new MatchAllDocsQuery(), 1, new Sort(oneFieldSort)); FieldDoc first = (FieldDoc) results.scoreDocs[0]; assertEquals(LEAST_DOUBLE_VALUE, first.fields[0]); // sort increasing, missing last - oneFieldSort = onefield.getSortField(false); - oneFieldSort.setMissingValue(Double.MAX_VALUE); + oneFieldSort = onefield.getSortField(false, Double.MAX_VALUE); results = searcher.search(new MatchAllDocsQuery(), 1, new Sort(oneFieldSort)); first = (FieldDoc) results.scoreDocs[0]; diff --git a/lucene/core/src/test/org/apache/lucene/search/TestIndexSortSortedNumericDocValuesRangeQuery.java b/lucene/core/src/test/org/apache/lucene/search/TestIndexSortSortedNumericDocValuesRangeQuery.java index 631f35abbe28..b69d5b03b1cf 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestIndexSortSortedNumericDocValuesRangeQuery.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestIndexSortSortedNumericDocValuesRangeQuery.java @@ -49,15 +49,17 @@ public void testSameHitsAsPointRangeQuery() throws IOException { IndexWriterConfig iwc = new IndexWriterConfig(new MockAnalyzer(random())); boolean reverse = random().nextBoolean(); - SortField sortField = new SortedNumericSortField("dv", SortField.Type.LONG, reverse); boolean enableMissingValue = random().nextBoolean(); + Long missingValue = null; if (enableMissingValue) { - long missingValue = + missingValue = random().nextBoolean() ? TestUtil.nextLong(random(), -100, 10000) : (random().nextBoolean() ? Long.MIN_VALUE : Long.MAX_VALUE); - sortField.setMissingValue(missingValue); } + SortField sortField = + new SortedNumericSortField( + "dv", SortField.Type.LONG, reverse, SortedNumericSelector.Type.MIN, missingValue); iwc.setIndexSort(new Sort(sortField)); RandomIndexWriter iw = new RandomIndexWriter(random(), dir, iwc); @@ -102,15 +104,17 @@ public void testSameHitsAsPointRangeQueryIntSort() throws IOException { IndexWriterConfig iwc = new IndexWriterConfig(new MockAnalyzer(random())); boolean reverse = random().nextBoolean(); - SortField sortField = new SortedNumericSortField("dv", SortField.Type.INT, reverse); boolean enableMissingValue = random().nextBoolean(); + Integer missingValue = null; if (enableMissingValue) { - int missingValue = + missingValue = random().nextBoolean() ? TestUtil.nextInt(random(), -100, 10000) : (random().nextBoolean() ? Integer.MIN_VALUE : Integer.MAX_VALUE); - sortField.setMissingValue(missingValue); } + SortField sortField = + new SortedNumericSortField( + "dv", SortField.Type.INT, reverse, SortedNumericSelector.Type.MIN, missingValue); iwc.setIndexSort(new Sort(sortField)); RandomIndexWriter iw = new RandomIndexWriter(random(), dir, iwc); @@ -344,8 +348,13 @@ public void testIndexSortMissingValues() throws Exception { Directory dir = newDirectory(); IndexWriterConfig iwc = new IndexWriterConfig(new MockAnalyzer(random())); - SortField sortField = new SortedNumericSortField("field", SortField.Type.LONG); - sortField.setMissingValue(random().nextLong()); + SortField sortField = + new SortedNumericSortField( + "field", + SortField.Type.LONG, + false, + SortedNumericSelector.Type.MIN, + random().nextLong()); iwc.setIndexSort(new Sort(sortField)); RandomIndexWriter writer = new RandomIndexWriter(random(), dir, iwc); @@ -545,15 +554,17 @@ public void testCompareCount() throws IOException { for (int iter = 0; iter < iters; ++iter) { Directory dir = newDirectory(); IndexWriterConfig iwc = new IndexWriterConfig(new MockAnalyzer(random())); - SortField sortField = new SortedNumericSortField("field", SortField.Type.LONG); boolean enableMissingValue = random().nextBoolean(); + Long missingValue = null; if (enableMissingValue) { - long missingValue = + missingValue = random().nextBoolean() ? TestUtil.nextLong(random(), -100, 10000) : (random().nextBoolean() ? Long.MIN_VALUE : Long.MAX_VALUE); - sortField.setMissingValue(missingValue); } + SortField sortField = + new SortedNumericSortField( + "field", SortField.Type.LONG, false, SortedNumericSelector.Type.MIN, missingValue); iwc.setIndexSort(new Sort(sortField)); RandomIndexWriter writer = new RandomIndexWriter(random(), dir, iwc); @@ -607,11 +618,16 @@ private void assertSameCount(Weight weight1, Weight weight2, IndexSearcher searc public void testCountBoundary() throws IOException { Directory dir = newDirectory(); IndexWriterConfig iwc = new IndexWriterConfig(new MockAnalyzer(random())); - SortField sortField = new SortedNumericSortField("field", SortField.Type.LONG); boolean useLower = random().nextBoolean(); long lowerValue = 1; long upperValue = 100; - sortField.setMissingValue(useLower ? lowerValue : upperValue); + SortField sortField = + new SortedNumericSortField( + "field", + SortField.Type.LONG, + false, + SortedNumericSelector.Type.MIN, + useLower ? lowerValue : upperValue); Sort indexSort = new Sort(sortField); iwc.setIndexSort(indexSort); RandomIndexWriter writer = new RandomIndexWriter(random(), dir, iwc); diff --git a/lucene/core/src/test/org/apache/lucene/search/TestLongValuesSource.java b/lucene/core/src/test/org/apache/lucene/search/TestLongValuesSource.java index 5732e61e3f90..53b2fd0b42df 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestLongValuesSource.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestLongValuesSource.java @@ -90,16 +90,14 @@ public void testSortMissingExplicit() throws Exception { LongValuesSource onefield = LongValuesSource.fromLongField("onefield"); // sort decreasing, missing last - SortField oneFieldSort = onefield.getSortField(true); - oneFieldSort.setMissingValue(Long.MIN_VALUE); + SortField oneFieldSort = onefield.getSortField(true, Long.MIN_VALUE); TopDocs results = searcher.search(new MatchAllDocsQuery(), 1, new Sort(oneFieldSort)); FieldDoc first = (FieldDoc) results.scoreDocs[0]; assertEquals(LEAST_LONG_VALUE, first.fields[0]); // sort increasing, missing last - oneFieldSort = onefield.getSortField(false); - oneFieldSort.setMissingValue(Long.MAX_VALUE); + oneFieldSort = onefield.getSortField(false, Long.MAX_VALUE); results = searcher.search(new MatchAllDocsQuery(), 1, new Sort(oneFieldSort)); first = (FieldDoc) results.scoreDocs[0]; diff --git a/lucene/core/src/test/org/apache/lucene/search/TestSearchAfter.java b/lucene/core/src/test/org/apache/lucene/search/TestSearchAfter.java index ecc5727625cf..56cac4c30cd6 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestSearchAfter.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestSearchAfter.java @@ -75,12 +75,11 @@ public void setUp() throws Exception { for (String field : new String[] {"bytes", "sortedbytesdocvalues"}) { for (int rev = 0; rev < 2; rev++) { boolean reversed = rev == 0; - SortField sf = new SortField(field, SortField.Type.STRING, reversed); - sf.setMissingValue(SortField.STRING_FIRST); + SortField sf = + new SortField(field, SortField.Type.STRING, reversed, SortField.STRING_FIRST); allSortFields.add(sf); - sf = new SortField(field, SortField.Type.STRING, reversed); - sf.setMissingValue(SortField.STRING_LAST); + sf = new SortField(field, SortField.Type.STRING, reversed, SortField.STRING_LAST); allSortFields.add(sf); } } @@ -89,12 +88,11 @@ public void setUp() throws Exception { for (String field : new String[] {"sortedbytesdocvaluesval", "straightbytesdocvalues"}) { for (int rev = 0; rev < 2; rev++) { boolean reversed = rev == 0; - SortField sf = new SortField(field, SortField.Type.STRING_VAL, reversed); - sf.setMissingValue(SortField.STRING_FIRST); + SortField sf = + new SortField(field, SortField.Type.STRING_VAL, reversed, SortField.STRING_FIRST); allSortFields.add(sf); - sf = new SortField(field, SortField.Type.STRING_VAL, reversed); - sf.setMissingValue(SortField.STRING_LAST); + sf = new SortField(field, SortField.Type.STRING_VAL, reversed, SortField.STRING_LAST); allSortFields.add(sf); } } @@ -103,20 +101,22 @@ public void setUp() throws Exception { for (int i = 0; i < limit; i++) { SortField sf = allSortFields.get(i); if (sf.getType() == SortField.Type.INT) { - SortField sf2 = new SortField(sf.getField(), SortField.Type.INT, sf.getReverse()); - sf2.setMissingValue(random().nextInt()); + SortField sf2 = + new SortField(sf.getField(), SortField.Type.INT, sf.getReverse(), random().nextInt()); allSortFields.add(sf2); } else if (sf.getType() == SortField.Type.LONG) { - SortField sf2 = new SortField(sf.getField(), SortField.Type.LONG, sf.getReverse()); - sf2.setMissingValue(random().nextLong()); + SortField sf2 = + new SortField(sf.getField(), SortField.Type.LONG, sf.getReverse(), random().nextLong()); allSortFields.add(sf2); } else if (sf.getType() == SortField.Type.FLOAT) { - SortField sf2 = new SortField(sf.getField(), SortField.Type.FLOAT, sf.getReverse()); - sf2.setMissingValue(random().nextFloat()); + SortField sf2 = + new SortField( + sf.getField(), SortField.Type.FLOAT, sf.getReverse(), random().nextFloat()); allSortFields.add(sf2); } else if (sf.getType() == SortField.Type.DOUBLE) { - SortField sf2 = new SortField(sf.getField(), SortField.Type.DOUBLE, sf.getReverse()); - sf2.setMissingValue(random().nextDouble()); + SortField sf2 = + new SortField( + sf.getField(), SortField.Type.DOUBLE, sf.getReverse(), random().nextDouble()); allSortFields.add(sf2); } } diff --git a/lucene/core/src/test/org/apache/lucene/search/TestSort.java b/lucene/core/src/test/org/apache/lucene/search/TestSort.java index db2c7bbe884e..4a60095560ca 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestSort.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestSort.java @@ -16,6 +16,8 @@ */ package org.apache.lucene.search; +import static org.hamcrest.Matchers.equalTo; + import java.io.IOException; import org.apache.lucene.document.BinaryDocValuesField; import org.apache.lucene.document.Document; @@ -79,8 +81,7 @@ public void testEquals() { sortField2 = new SortField("foo", SortField.Type.LONG); assertDifferent(new Sort(sortField1), new Sort(sortField2)); - sortField2 = new SortField("foo", SortField.Type.STRING); - sortField2.setMissingValue(SortField.STRING_FIRST); + sortField2 = new SortField("foo", SortField.Type.STRING, false, SortField.STRING_FIRST); assertDifferent(new Sort(sortField1), new Sort(sortField2)); sortField2 = new SortField("foo", SortField.Type.STRING, false); @@ -90,6 +91,18 @@ public void testEquals() { assertDifferent(new Sort(sortField1), new Sort(sortField2)); } + public void testStringMissingValues() { + Exception e = + expectThrows( + IllegalArgumentException.class, + () -> { + new Sort(new SortField("foo", SortField.Type.STRING, false, "invalid value")); + }); + assertThat( + e.getMessage(), + equalTo("For Type.STRING, missing value must be either STRING_FIRST or STRING_LAST")); + } + /** Tests sorting on type string */ public void testString() throws IOException { Directory dir = newDirectory(); @@ -319,8 +332,7 @@ public void testIntMissingLast() throws IOException { writer.close(); IndexSearcher searcher = newSearcher(ir); - SortField sortField = new SortField("value", SortField.Type.INT); - sortField.setMissingValue(Integer.MAX_VALUE); + SortField sortField = new SortField("value", SortField.Type.INT, false, Integer.MAX_VALUE); Sort sort = new Sort(sortField); TopDocs td = searcher.search(new MatchAllDocsQuery(), 10, sort); @@ -451,8 +463,7 @@ public void testLongMissingLast() throws IOException { writer.close(); IndexSearcher searcher = newSearcher(ir); - SortField sortField = new SortField("value", SortField.Type.LONG); - sortField.setMissingValue(Long.MAX_VALUE); + SortField sortField = new SortField("value", SortField.Type.LONG, false, Long.MAX_VALUE); Sort sort = new Sort(sortField); TopDocs td = searcher.search(new MatchAllDocsQuery(), 10, sort); @@ -583,8 +594,7 @@ public void testFloatMissingLast() throws IOException { writer.close(); IndexSearcher searcher = newSearcher(ir); - SortField sortField = new SortField("value", SortField.Type.FLOAT); - sortField.setMissingValue(Float.MAX_VALUE); + SortField sortField = new SortField("value", SortField.Type.FLOAT, false, Float.MAX_VALUE); Sort sort = new Sort(sortField); TopDocs td = searcher.search(new MatchAllDocsQuery(), 10, sort); @@ -770,8 +780,7 @@ public void testDoubleMissingLast() throws IOException { writer.close(); IndexSearcher searcher = newSearcher(ir); - SortField sortField = new SortField("value", SortField.Type.DOUBLE); - sortField.setMissingValue(Double.MAX_VALUE); + SortField sortField = new SortField("value", SortField.Type.DOUBLE, false, Double.MAX_VALUE); Sort sort = new Sort(sortField); TopDocs td = searcher.search(new MatchAllDocsQuery(), 10, sort); diff --git a/lucene/core/src/test/org/apache/lucene/search/TestSortOptimization.java b/lucene/core/src/test/org/apache/lucene/search/TestSortOptimization.java index 3bc0cc1d0249..becb84e0a5fc 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestSortOptimization.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestSortOptimization.java @@ -221,20 +221,17 @@ private void testSortOptimizationWithMissingValues( final int numHits = 3; { // test that optimization is run when missing value setting of SortField is competitive with - // Puring.GREATER_THAN_OR_EQUAL_TO - final SortField sortField = new SortField("my_field", SortField.Type.LONG); - sortField.setMissingValue(0L); // set a competitive missing value + // Pruning.GREATER_THAN_OR_EQUAL_TO + final SortField sortField = new SortField("my_field", SortField.Type.LONG, false, 0L); final Sort sort = new Sort(sortField); TopDocs topDocs = assertSearchHits(reader, sort, numHits, null); assertEquals(topDocs.scoreDocs.length, numHits); assertNonCompetitiveHitsAreSkipped(topDocs.totalHits.value(), numDocs); } { // test that optimization is not run when missing value setting of SortField is competitive - // with Puring.SKIP - final SortField sortField1 = new SortField("my_field1", SortField.Type.LONG); - final SortField sortField2 = new SortField("my_field2", SortField.Type.LONG); - sortField1.setMissingValue(0L); // set a competitive missing value - sortField2.setMissingValue(0L); // set a competitive missing value + // with Pruning.SKIP + final SortField sortField1 = new SortField("my_field1", SortField.Type.LONG, false, 0L); + final SortField sortField2 = new SortField("my_field2", SortField.Type.LONG, false, 0L); final Sort sort = new Sort(sortField1, sortField2); TopDocs topDocs = assertSearchHits(reader, sort, numHits, null); assertEquals(topDocs.scoreDocs.length, numHits); @@ -243,8 +240,7 @@ private void testSortOptimizationWithMissingValues( numDocs); // assert that all documents were collected => optimization was not run } { // test that optimization is run when missing value setting of SortField is NOT competitive - final SortField sortField = new SortField("my_field", SortField.Type.LONG); - sortField.setMissingValue(100L); // set a NON competitive missing value + final SortField sortField = new SortField("my_field", SortField.Type.LONG, false, 100L); final Sort sort = new Sort(sortField); TopDocs topDocs = assertSearchHits(reader, sort, numHits, null); assertEquals(topDocs.scoreDocs.length, numHits); @@ -256,8 +252,8 @@ private void testSortOptimizationWithMissingValues( final long afterValue = Long.MAX_VALUE; final int afterDocID = 10 + random().nextInt(1000); FieldDoc after = new FieldDoc(afterDocID, Float.NaN, new Long[] {afterValue}); - final SortField sortField = new SortField("my_field", SortField.Type.LONG); - sortField.setMissingValue(Long.MAX_VALUE); // set a competitive missing value + final SortField sortField = + new SortField("my_field", SortField.Type.LONG, false, Long.MAX_VALUE); final Sort sort = new Sort(sortField); TopDocs topDocs = assertSearchHits(reader, sort, numHits, after); assertEquals(topDocs.scoreDocs.length, numHits); @@ -269,8 +265,8 @@ private void testSortOptimizationWithMissingValues( final long afterValue = Long.MAX_VALUE; final int afterDocID = 10 + random().nextInt(1000); FieldDoc after = new FieldDoc(afterDocID, Float.NaN, new Long[] {afterValue}); - final SortField sortField = new SortField("my_field", SortField.Type.LONG, true); - sortField.setMissingValue(Long.MAX_VALUE); // set a competitive missing value + final SortField sortField = + new SortField("my_field", SortField.Type.LONG, true, Long.MAX_VALUE); final Sort sort = new Sort(sortField); TopDocs topDocs = assertSearchHits(reader, sort, numHits, after); assertEquals(topDocs.scoreDocs.length, numHits); @@ -282,8 +278,7 @@ private void testSortOptimizationWithMissingValues( // with after on asc order long afterValue = 3L; FieldDoc after = new FieldDoc(3, Float.NaN, new Long[] {afterValue}); - final SortField sortField = new SortField("my_field", SortField.Type.LONG); - sortField.setMissingValue(2L); + final SortField sortField = new SortField("my_field", SortField.Type.LONG, false, 2L); final Sort sort = new Sort(sortField); TopDocs topDocs = assertSearchHits(reader, sort, numHits, after); assertEquals(topDocs.scoreDocs.length, numHits); @@ -336,16 +331,14 @@ private void testNumericDocValuesOptimizationWithMissingValues( TopDocs topDocs2; { // Test that optimization is run with NumericDocValues when missing value is NOT competitive - final SortField sortField = new SortField("my_field", SortField.Type.LONG, true); - sortField.setMissingValue(0L); // missing value is not competitive + final SortField sortField = new SortField("my_field", SortField.Type.LONG, true, 0L); final Sort sort = new Sort(sortField); topDocs1 = assertSearchHits(reader, sort, numHits, null); assertNonCompetitiveHitsAreSkipped(topDocs1.totalHits.value(), numDocs); } { // Test that sort on sorted numeric field without sort optimization and with sort optimization // produce the same results - final SortField sortField = new SortField("my_field", SortField.Type.LONG, true); - sortField.setMissingValue(0L); // missing value is not competitive + final SortField sortField = new SortField("my_field", SortField.Type.LONG, true, 0L); final Sort sort = new Sort(sortField); sortField.setOptimizeSortWithPoints(false); topDocs2 = assertSearchHits(reader, sort, numHits, null); @@ -364,10 +357,9 @@ private void testNumericDocValuesOptimizationWithMissingValues( } { // Test that we can't do optimization via NumericDocValues when there are multiple comparators - final SortField sortField1 = new SortField("my_field", SortField.Type.LONG, true); - final SortField sortField2 = new SortField("other", SortField.Type.LONG, true); - sortField1.setMissingValue(0L); // missing value is not competitive - sortField2.setMissingValue(0L); // missing value is not competitive + // missing values are not competitive + final SortField sortField1 = new SortField("my_field", SortField.Type.LONG, true, 0L); + final SortField sortField2 = new SortField("other", SortField.Type.LONG, true, 0L); final Sort multiSorts = new Sort(new SortField[] {sortField1, sortField2}); TopDocs topDocs = assertSearchHits(reader, multiSorts, numHits, null); // can't optimization with NumericDocValues when there are multiple comparators @@ -1059,16 +1051,17 @@ private void doTestStringSortOptimization(DirectoryReader reader) throws IOExcep { // simple ascending sort SortField sortField = - KeywordField.newSortField("my_field", false, SortedSetSelector.Type.MIN); - sortField.setMissingValue(SortField.STRING_LAST); + KeywordField.newSortField( + "my_field", false, SortedSetSelector.Type.MIN, SortField.STRING_LAST); Sort sort = new Sort(sortField); TopDocs topDocs = assertSort(reader, sort, numHits, null); assertNonCompetitiveHitsAreSkipped(topDocs.totalHits.value(), numDocs); } { // simple descending sort - SortField sortField = KeywordField.newSortField("my_field", true, SortedSetSelector.Type.MIN); - sortField.setMissingValue(SortField.STRING_FIRST); + SortField sortField = + KeywordField.newSortField( + "my_field", true, SortedSetSelector.Type.MIN, SortField.STRING_FIRST); Sort sort = new Sort(sortField); TopDocs topDocs = assertSort(reader, sort, numHits, null); assertNonCompetitiveHitsAreSkipped(topDocs.totalHits.value(), numDocs); @@ -1076,23 +1069,24 @@ private void doTestStringSortOptimization(DirectoryReader reader) throws IOExcep { // ascending sort that returns missing values first SortField sortField = - KeywordField.newSortField("my_field", false, SortedSetSelector.Type.MIN); - sortField.setMissingValue(SortField.STRING_FIRST); + KeywordField.newSortField( + "my_field", false, SortedSetSelector.Type.MIN, SortField.STRING_FIRST); Sort sort = new Sort(sortField); assertSort(reader, sort, numHits, null); } { // descending sort that returns missing values last - SortField sortField = KeywordField.newSortField("my_field", true, SortedSetSelector.Type.MIN); - sortField.setMissingValue(SortField.STRING_LAST); + SortField sortField = + KeywordField.newSortField( + "my_field", true, SortedSetSelector.Type.MIN, SortField.STRING_LAST); Sort sort = new Sort(sortField); assertSort(reader, sort, numHits, null); } { // paging ascending sort with after SortField sortField = - KeywordField.newSortField("my_field", false, SortedSetSelector.Type.MIN); - sortField.setMissingValue(SortField.STRING_LAST); + KeywordField.newSortField( + "my_field", false, SortedSetSelector.Type.MIN, SortField.STRING_LAST); Sort sort = new Sort(sortField); BytesRef afterValue = new BytesRef(random().nextBoolean() ? "23" : "230000000"); FieldDoc after = new FieldDoc(2, Float.NaN, new Object[] {afterValue}); @@ -1101,8 +1095,9 @@ private void doTestStringSortOptimization(DirectoryReader reader) throws IOExcep } { // paging descending sort with after - SortField sortField = KeywordField.newSortField("my_field", true, SortedSetSelector.Type.MIN); - sortField.setMissingValue(SortField.STRING_FIRST); + SortField sortField = + KeywordField.newSortField( + "my_field", true, SortedSetSelector.Type.MIN, SortField.STRING_FIRST); Sort sort = new Sort(sortField); BytesRef afterValue = new BytesRef(random().nextBoolean() ? "17" : "170000000"); FieldDoc after = new FieldDoc(2, Float.NaN, new Object[] {afterValue}); @@ -1112,8 +1107,8 @@ private void doTestStringSortOptimization(DirectoryReader reader) throws IOExcep { // paging ascending sort with after that returns missing values first SortField sortField = - KeywordField.newSortField("my_field", false, SortedSetSelector.Type.MIN); - sortField.setMissingValue(SortField.STRING_FIRST); + KeywordField.newSortField( + "my_field", false, SortedSetSelector.Type.MIN, SortField.STRING_FIRST); Sort sort = new Sort(sortField); BytesRef afterValue = new BytesRef(random().nextBoolean() ? "23" : "230000000"); FieldDoc after = new FieldDoc(2, Float.NaN, new Object[] {afterValue}); @@ -1122,8 +1117,9 @@ private void doTestStringSortOptimization(DirectoryReader reader) throws IOExcep } { // paging descending sort with after that returns missing values first - SortField sortField = KeywordField.newSortField("my_field", true, SortedSetSelector.Type.MIN); - sortField.setMissingValue(SortField.STRING_LAST); + SortField sortField = + KeywordField.newSortField( + "my_field", true, SortedSetSelector.Type.MIN, SortField.STRING_LAST); Sort sort = new Sort(sortField); BytesRef afterValue = new BytesRef(random().nextBoolean() ? "17" : "170000000"); FieldDoc after = new FieldDoc(2, Float.NaN, new Object[] {afterValue}); @@ -1133,8 +1129,8 @@ private void doTestStringSortOptimization(DirectoryReader reader) throws IOExcep { // test that if there is the secondary sort on _score, hits are still skipped SortField sortField = - KeywordField.newSortField("my_field", false, SortedSetSelector.Type.MIN); - sortField.setMissingValue(SortField.STRING_LAST); + KeywordField.newSortField( + "my_field", false, SortedSetSelector.Type.MIN, SortField.STRING_LAST); Sort sort = new Sort(sortField, FIELD_SCORE); TopDocs topDocs = assertSort(reader, sort, numHits, null); assertNonCompetitiveHitsAreSkipped(topDocs.totalHits.value(), numDocs); @@ -1142,8 +1138,8 @@ private void doTestStringSortOptimization(DirectoryReader reader) throws IOExcep { // test that if string field is a secondary sort, no optimization is run SortField sortField = - KeywordField.newSortField("my_field", false, SortedSetSelector.Type.MIN); - sortField.setMissingValue(SortField.STRING_LAST); + KeywordField.newSortField( + "my_field", false, SortedSetSelector.Type.MIN, SortField.STRING_LAST); Sort sort = new Sort(FIELD_SCORE, sortField); TopDocs topDocs = assertSort(reader, sort, numHits, null); assertEquals( @@ -1153,8 +1149,9 @@ private void doTestStringSortOptimization(DirectoryReader reader) throws IOExcep } public void doTestStringSortOptimizationDisabled(DirectoryReader reader) throws IOException { - SortField sortField = KeywordField.newSortField("my_field", false, SortedSetSelector.Type.MIN); - sortField.setMissingValue(SortField.STRING_LAST); + SortField sortField = + KeywordField.newSortField( + "my_field", false, SortedSetSelector.Type.MIN, SortField.STRING_LAST); sortField.setOptimizeSortWithIndexedData(false); Sort sort = new Sort(sortField); diff --git a/lucene/core/src/test/org/apache/lucene/search/TestSortRandom.java b/lucene/core/src/test/org/apache/lucene/search/TestSortRandom.java index 4ce6521676d9..851fec260cf9 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestSortRandom.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestSortRandom.java @@ -130,12 +130,8 @@ private void testRandomStringSort(SortField.Type type) throws Exception { final TopFieldDocs hits; final SortField sf; final boolean sortMissingLast; - sf = new SortField("stringdv", type, reverse); sortMissingLast = random().nextBoolean(); - - if (sortMissingLast) { - sf.setMissingValue(SortField.STRING_LAST); - } + sf = new SortField("stringdv", type, reverse, sortMissingLast ? SortField.STRING_LAST : null); final Sort sort; if (random.nextBoolean()) { diff --git a/lucene/core/src/test/org/apache/lucene/search/TestSortedNumericSortField.java b/lucene/core/src/test/org/apache/lucene/search/TestSortedNumericSortField.java index e7f765a16f8e..b6a3c91a5e13 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestSortedNumericSortField.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestSortedNumericSortField.java @@ -153,8 +153,9 @@ public void testMissingFirst() throws Exception { writer.close(); IndexSearcher searcher = newSearcher(ir); - SortField sortField = new SortedNumericSortField("value", SortField.Type.INT); - sortField.setMissingValue(Integer.MIN_VALUE); + SortField sortField = + new SortedNumericSortField( + "value", SortField.Type.INT, false, SortedNumericSelector.Type.MIN, Integer.MIN_VALUE); Sort sort = new Sort(sortField); TopDocs td = searcher.search(new MatchAllDocsQuery(), 10, sort); @@ -188,8 +189,9 @@ public void testMissingLast() throws Exception { writer.close(); IndexSearcher searcher = newSearcher(ir); - SortField sortField = new SortedNumericSortField("value", SortField.Type.INT); - sortField.setMissingValue(Integer.MAX_VALUE); + SortField sortField = + new SortedNumericSortField( + "value", SortField.Type.INT, false, SortedNumericSelector.Type.MIN, Integer.MAX_VALUE); Sort sort = new Sort(sortField); TopDocs td = searcher.search(new MatchAllDocsQuery(), 10, sort); diff --git a/lucene/core/src/test/org/apache/lucene/search/TestSortedSetSelector.java b/lucene/core/src/test/org/apache/lucene/search/TestSortedSetSelector.java index 2e41b26f70a4..48b625ea4a29 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestSortedSetSelector.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestSortedSetSelector.java @@ -113,8 +113,8 @@ public void testMaxMissingFirst() throws Exception { // slow wrapper does not support random access ordinals (there is no need for that!) IndexSearcher searcher = newSearcher(ir, false); - SortField sortField = new SortedSetSortField("value", false, SortedSetSelector.Type.MAX); - sortField.setMissingValue(SortField.STRING_FIRST); + SortField sortField = + new SortedSetSortField("value", false, SortedSetSelector.Type.MAX, SortField.STRING_FIRST); Sort sort = new Sort(sortField); TopDocs td = searcher.search(new MatchAllDocsQuery(), 10, sort); @@ -150,8 +150,8 @@ public void testMaxMissingLast() throws Exception { // slow wrapper does not support random access ordinals (there is no need for that!) IndexSearcher searcher = newSearcher(ir, false); - SortField sortField = new SortedSetSortField("value", false, SortedSetSelector.Type.MAX); - sortField.setMissingValue(SortField.STRING_LAST); + SortField sortField = + new SortedSetSortField("value", false, SortedSetSelector.Type.MAX, SortField.STRING_LAST); Sort sort = new Sort(sortField); TopDocs td = searcher.search(new MatchAllDocsQuery(), 10, sort); @@ -278,8 +278,9 @@ public void testMiddleMinMissingFirst() throws Exception { // slow wrapper does not support random access ordinals (there is no need for that!) IndexSearcher searcher = newSearcher(ir, false); - SortField sortField = new SortedSetSortField("value", false, SortedSetSelector.Type.MIDDLE_MIN); - sortField.setMissingValue(SortField.STRING_FIRST); + SortField sortField = + new SortedSetSortField( + "value", false, SortedSetSelector.Type.MIDDLE_MIN, SortField.STRING_FIRST); Sort sort = new Sort(sortField); TopDocs td = searcher.search(new MatchAllDocsQuery(), 10, sort); @@ -316,8 +317,9 @@ public void testMiddleMinMissingLast() throws Exception { // slow wrapper does not support random access ordinals (there is no need for that!) IndexSearcher searcher = newSearcher(ir, false); - SortField sortField = new SortedSetSortField("value", false, SortedSetSelector.Type.MIDDLE_MIN); - sortField.setMissingValue(SortField.STRING_LAST); + SortField sortField = + new SortedSetSortField( + "value", false, SortedSetSelector.Type.MIDDLE_MIN, SortField.STRING_LAST); Sort sort = new Sort(sortField); TopDocs td = searcher.search(new MatchAllDocsQuery(), 10, sort); @@ -444,8 +446,9 @@ public void testMiddleMaxMissingFirst() throws Exception { // slow wrapper does not support random access ordinals (there is no need for that!) IndexSearcher searcher = newSearcher(ir, false); - SortField sortField = new SortedSetSortField("value", false, SortedSetSelector.Type.MIDDLE_MAX); - sortField.setMissingValue(SortField.STRING_FIRST); + SortField sortField = + new SortedSetSortField( + "value", false, SortedSetSelector.Type.MIDDLE_MAX, SortField.STRING_FIRST); Sort sort = new Sort(sortField); TopDocs td = searcher.search(new MatchAllDocsQuery(), 10, sort); @@ -482,8 +485,9 @@ public void testMiddleMaxMissingLast() throws Exception { // slow wrapper does not support random access ordinals (there is no need for that!) IndexSearcher searcher = newSearcher(ir, false); - SortField sortField = new SortedSetSortField("value", false, SortedSetSelector.Type.MIDDLE_MAX); - sortField.setMissingValue(SortField.STRING_LAST); + SortField sortField = + new SortedSetSortField( + "value", false, SortedSetSelector.Type.MIDDLE_MAX, SortField.STRING_LAST); Sort sort = new Sort(sortField); TopDocs td = searcher.search(new MatchAllDocsQuery(), 10, sort); diff --git a/lucene/core/src/test/org/apache/lucene/search/TestSortedSetSortField.java b/lucene/core/src/test/org/apache/lucene/search/TestSortedSetSortField.java index 939580125b22..a90a7c6e1daf 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestSortedSetSortField.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestSortedSetSortField.java @@ -136,8 +136,8 @@ public void testMissingFirst() throws Exception { writer.close(); IndexSearcher searcher = newSearcher(ir); - SortField sortField = new SortedSetSortField("value", false); - sortField.setMissingValue(SortField.STRING_FIRST); + SortField sortField = + new SortedSetSortField("value", false, SortedSetSelector.Type.MIN, SortField.STRING_FIRST); Sort sort = new Sort(sortField); TopDocs td = searcher.search(new MatchAllDocsQuery(), 10, sort); @@ -171,8 +171,8 @@ public void testMissingLast() throws Exception { writer.close(); IndexSearcher searcher = newSearcher(ir); - SortField sortField = new SortedSetSortField("value", false); - sortField.setMissingValue(SortField.STRING_LAST); + SortField sortField = + new SortedSetSortField("value", false, SortedSetSelector.Type.MIN, SortField.STRING_LAST); Sort sort = new Sort(sortField); TopDocs td = searcher.search(new MatchAllDocsQuery(), 10, sort); diff --git a/lucene/core/src/test/org/apache/lucene/search/TestXYPointDistanceSort.java b/lucene/core/src/test/org/apache/lucene/search/TestXYPointDistanceSort.java index d0656d22edd0..27d1aba7528a 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestXYPointDistanceSort.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestXYPointDistanceSort.java @@ -237,7 +237,6 @@ private void doRandomTest(int numDocs, int numQueries) throws IOException { int topN = TestUtil.nextInt(random(), 1, reader.maxDoc()); // sort by distance, then ID SortField distanceSort = XYDocValuesField.newDistanceSort("field", x, y); - distanceSort.setMissingValue(missingValue); Sort sort = new Sort(distanceSort, new SortField("id", SortField.Type.INT)); TopDocs topDocs = searcher.search(new MatchAllDocsQuery(), topN, sort); diff --git a/lucene/core/src/test/org/apache/lucene/search/comparators/TestNumericComparator.java b/lucene/core/src/test/org/apache/lucene/search/comparators/TestNumericComparator.java index 417a76c62311..4080ec81162f 100644 --- a/lucene/core/src/test/org/apache/lucene/search/comparators/TestNumericComparator.java +++ b/lucene/core/src/test/org/apache/lucene/search/comparators/TestNumericComparator.java @@ -139,8 +139,8 @@ public void testEmptyCompetitiveIteratorOptimizationWithMissingValue() throws Ex var indexSearcher = newSearcher(reader); indexSearcher.setQueryCache(null); { - var sortField = new SortField("long_field_1", SortField.Type.LONG, false); - sortField.setMissingValue(Long.MIN_VALUE); + var sortField = + new SortField("long_field_1", SortField.Type.LONG, false, Long.MIN_VALUE); var topDocs = indexSearcher.search(new MatchAllDocsQuery(), 3, new Sort(sortField)); assertEquals(numDocs, topDocs.scoreDocs[0].doc); assertEquals(Long.MIN_VALUE, ((FieldDoc) topDocs.scoreDocs[0]).fields[0]); @@ -150,8 +150,8 @@ public void testEmptyCompetitiveIteratorOptimizationWithMissingValue() throws Ex assertEquals(1L, ((FieldDoc) topDocs.scoreDocs[2]).fields[0]); } { - var sortField = new SortField("long_field_2", SortField.Type.LONG, false); - sortField.setMissingValue(Long.MIN_VALUE); + var sortField = + new SortField("long_field_2", SortField.Type.LONG, false, Long.MIN_VALUE); var topDocs = indexSearcher.search(new MatchAllDocsQuery(), 3, new Sort(sortField)); assertEquals(numDocs, topDocs.scoreDocs[0].doc); assertEquals(Long.MIN_VALUE, ((FieldDoc) topDocs.scoreDocs[0]).fields[0]); diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/MultiValuedDoubleFieldSource.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/MultiValuedDoubleFieldSource.java index f0b8a10adb5d..d8fae27e9828 100644 --- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/MultiValuedDoubleFieldSource.java +++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/MultiValuedDoubleFieldSource.java @@ -37,10 +37,16 @@ public class MultiValuedDoubleFieldSource extends DoubleFieldSource { protected final SortedNumericSelector.Type selector; + private final Double missingValue; public MultiValuedDoubleFieldSource(String field, Type selector) { + this(field, selector, null); + } + + public MultiValuedDoubleFieldSource(String field, Type selector, Double missingValue) { super(field); this.selector = selector; + this.missingValue = missingValue; Objects.requireNonNull(field, "Field is required to create a MultiValuedDoubleFieldSource"); Objects.requireNonNull( selector, "SortedNumericSelector is required to create a MultiValuedDoubleFieldSource"); @@ -48,7 +54,8 @@ public MultiValuedDoubleFieldSource(String field, Type selector) { @Override public SortField getSortField(boolean reverse) { - return new SortedNumericSortField(field, SortField.Type.DOUBLE, reverse, selector); + return new SortedNumericSortField( + field, SortField.Type.DOUBLE, reverse, selector, missingValue); } @Override diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/MultiValuedFloatFieldSource.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/MultiValuedFloatFieldSource.java index b06d0ebe640f..34d76ab083a7 100644 --- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/MultiValuedFloatFieldSource.java +++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/MultiValuedFloatFieldSource.java @@ -37,10 +37,16 @@ public class MultiValuedFloatFieldSource extends FloatFieldSource { protected final SortedNumericSelector.Type selector; + private final Float missingValue; - public MultiValuedFloatFieldSource(String field, Type selector) { + public MultiValuedFloatFieldSource(String field, SortedNumericSelector.Type selector) { + this(field, selector, null); + } + + public MultiValuedFloatFieldSource(String field, Type selector, Float missingValue) { super(field); this.selector = selector; + this.missingValue = missingValue; Objects.requireNonNull(field, "Field is required to create a MultiValuedFloatFieldSource"); Objects.requireNonNull( selector, "SortedNumericSelector is required to create a MultiValuedFloatFieldSource"); @@ -48,7 +54,7 @@ public MultiValuedFloatFieldSource(String field, Type selector) { @Override public SortField getSortField(boolean reverse) { - return new SortedNumericSortField(field, SortField.Type.FLOAT, reverse, selector); + return new SortedNumericSortField(field, SortField.Type.FLOAT, reverse, selector, missingValue); } @Override diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/MultiValuedIntFieldSource.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/MultiValuedIntFieldSource.java index c60f1880cbf0..00fe2690a7b3 100644 --- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/MultiValuedIntFieldSource.java +++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/MultiValuedIntFieldSource.java @@ -37,10 +37,16 @@ public class MultiValuedIntFieldSource extends IntFieldSource { protected final SortedNumericSelector.Type selector; + private final Integer missingValue; - public MultiValuedIntFieldSource(String field, Type selector) { + public MultiValuedIntFieldSource(String field, SortedNumericSelector.Type selector) { + this(field, selector, null); + } + + public MultiValuedIntFieldSource(String field, Type selector, Integer missingValue) { super(field); this.selector = selector; + this.missingValue = missingValue; Objects.requireNonNull(field, "Field is required to create a MultiValuedIntFieldSource"); Objects.requireNonNull( selector, "SortedNumericSelector is required to create a MultiValuedIntFieldSource"); @@ -48,7 +54,7 @@ public MultiValuedIntFieldSource(String field, Type selector) { @Override public SortField getSortField(boolean reverse) { - return new SortedNumericSortField(field, SortField.Type.INT, reverse, selector); + return new SortedNumericSortField(field, SortField.Type.INT, reverse, selector, missingValue); } @Override diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/MultiValuedLongFieldSource.java b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/MultiValuedLongFieldSource.java index 20a5fe9c18a3..3adb66518456 100644 --- a/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/MultiValuedLongFieldSource.java +++ b/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/MultiValuedLongFieldSource.java @@ -37,10 +37,16 @@ public class MultiValuedLongFieldSource extends LongFieldSource { protected final SortedNumericSelector.Type selector; + private final Long missingValue; - public MultiValuedLongFieldSource(String field, Type selector) { + public MultiValuedLongFieldSource(String field, SortedNumericSelector.Type selector) { + this(field, selector, null); + } + + public MultiValuedLongFieldSource(String field, Type selector, Long missingValue) { super(field); this.selector = selector; + this.missingValue = missingValue; Objects.requireNonNull(field, "Field is required to create a MultiValuedLongFieldSource"); Objects.requireNonNull( selector, "SortedNumericSelector is required to create a MultiValuedLongFieldSource"); @@ -48,7 +54,7 @@ public MultiValuedLongFieldSource(String field, Type selector) { @Override public SortField getSortField(boolean reverse) { - return new SortedNumericSortField(field, SortField.Type.LONG, reverse, selector); + return new SortedNumericSortField(field, SortField.Type.LONG, reverse, selector, missingValue); } @Override diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DPointOutsideSortField.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DPointOutsideSortField.java index b0cac135603f..d45dd5a681cb 100644 --- a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DPointOutsideSortField.java +++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DPointOutsideSortField.java @@ -29,7 +29,7 @@ final class Geo3DPointOutsideSortField extends SortField { Geo3DPointOutsideSortField( final String field, final PlanetModel planetModel, final GeoOutsideDistance distanceShape) { - super(field, SortField.Type.CUSTOM); + super(field, SortField.Type.CUSTOM, false, Double.POSITIVE_INFINITY); if (field == null) { throw new IllegalArgumentException("field must not be null"); } @@ -38,7 +38,6 @@ final class Geo3DPointOutsideSortField extends SortField { } this.planetModel = planetModel; this.distanceShape = distanceShape; - setMissingValue(Double.POSITIVE_INFINITY); } @Override diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DPointSortField.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DPointSortField.java index 49caa7250a6c..1873cc94e5a2 100644 --- a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DPointSortField.java +++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DPointSortField.java @@ -29,7 +29,7 @@ final class Geo3DPointSortField extends SortField { Geo3DPointSortField( final String field, final PlanetModel planetModel, final GeoDistanceShape distanceShape) { - super(field, SortField.Type.CUSTOM); + super(field, SortField.Type.CUSTOM, false, Double.POSITIVE_INFINITY); if (field == null) { throw new IllegalArgumentException("field must not be null"); } @@ -38,7 +38,6 @@ final class Geo3DPointSortField extends SortField { } this.distanceShape = distanceShape; this.planetModel = planetModel; - setMissingValue(Double.POSITIVE_INFINITY); } @Override diff --git a/lucene/test-framework/src/java/org/apache/lucene/tests/index/BaseSegmentInfoFormatTestCase.java b/lucene/test-framework/src/java/org/apache/lucene/tests/index/BaseSegmentInfoFormatTestCase.java index 6a827f73a2df..f1d4452b78aa 100644 --- a/lucene/test-framework/src/java/org/apache/lucene/tests/index/BaseSegmentInfoFormatTestCase.java +++ b/lucene/test-framework/src/java/org/apache/lucene/tests/index/BaseSegmentInfoFormatTestCase.java @@ -30,7 +30,9 @@ import org.apache.lucene.index.SegmentInfo; import org.apache.lucene.search.Sort; import org.apache.lucene.search.SortField; +import org.apache.lucene.search.SortedNumericSelector; import org.apache.lucene.search.SortedNumericSortField; +import org.apache.lucene.search.SortedSetSelector; import org.apache.lucene.search.SortedSetSortField; import org.apache.lucene.store.Directory; import org.apache.lucene.store.IOContext; @@ -293,87 +295,76 @@ protected boolean supportsHasBlocks() { private SortField randomIndexSortField() { boolean reversed = random().nextBoolean(); - SortField sortField; - switch (random().nextInt(10)) { - case 0: - sortField = - new SortField(TestUtil.randomSimpleString(random()), SortField.Type.INT, reversed); - if (random().nextBoolean()) { - sortField.setMissingValue(random().nextInt()); - } - break; - case 1: - sortField = - new SortedNumericSortField( - TestUtil.randomSimpleString(random()), SortField.Type.INT, reversed); - if (random().nextBoolean()) { - sortField.setMissingValue(random().nextInt()); - } - break; - - case 2: - sortField = - new SortField(TestUtil.randomSimpleString(random()), SortField.Type.LONG, reversed); - if (random().nextBoolean()) { - sortField.setMissingValue(random().nextLong()); - } - break; - case 3: - sortField = - new SortedNumericSortField( - TestUtil.randomSimpleString(random()), SortField.Type.LONG, reversed); - if (random().nextBoolean()) { - sortField.setMissingValue(random().nextLong()); - } - break; - case 4: - sortField = - new SortField(TestUtil.randomSimpleString(random()), SortField.Type.FLOAT, reversed); - if (random().nextBoolean()) { - sortField.setMissingValue(random().nextFloat()); - } - break; - case 5: - sortField = - new SortedNumericSortField( - TestUtil.randomSimpleString(random()), SortField.Type.FLOAT, reversed); - if (random().nextBoolean()) { - sortField.setMissingValue(random().nextFloat()); - } - break; - case 6: - sortField = - new SortField(TestUtil.randomSimpleString(random()), SortField.Type.DOUBLE, reversed); - if (random().nextBoolean()) { - sortField.setMissingValue(random().nextDouble()); - } - break; - case 7: - sortField = - new SortedNumericSortField( - TestUtil.randomSimpleString(random()), SortField.Type.DOUBLE, reversed); - if (random().nextBoolean()) { - sortField.setMissingValue(random().nextDouble()); - } - break; - case 8: - sortField = - new SortField(TestUtil.randomSimpleString(random()), SortField.Type.STRING, reversed); - if (random().nextBoolean()) { - sortField.setMissingValue(SortField.STRING_LAST); - } - break; - case 9: - sortField = new SortedSetSortField(TestUtil.randomSimpleString(random()), reversed); - if (random().nextBoolean()) { - sortField.setMissingValue(SortField.STRING_LAST); - } - break; - default: - sortField = null; + return switch (random().nextInt(10)) { + case 0 -> + new SortField( + TestUtil.randomSimpleString(random()), + SortField.Type.INT, + reversed, + random().nextBoolean() ? random().nextInt() : null); + case 1 -> + new SortedNumericSortField( + TestUtil.randomSimpleString(random()), + SortField.Type.INT, + reversed, + SortedNumericSelector.Type.MIN, + random().nextBoolean() ? random().nextInt() : null); + case 2 -> + new SortField( + TestUtil.randomSimpleString(random()), + SortField.Type.LONG, + reversed, + random().nextBoolean() ? random().nextLong() : null); + case 3 -> + new SortedNumericSortField( + TestUtil.randomSimpleString(random()), + SortField.Type.LONG, + reversed, + SortedNumericSelector.Type.MIN, + random().nextBoolean() ? random().nextLong() : null); + case 4 -> + new SortField( + TestUtil.randomSimpleString(random()), + SortField.Type.FLOAT, + reversed, + random().nextBoolean() ? random().nextFloat() : null); + case 5 -> + new SortedNumericSortField( + TestUtil.randomSimpleString(random()), + SortField.Type.FLOAT, + reversed, + SortedNumericSelector.Type.MIN, + random().nextBoolean() ? random().nextFloat() : null); + case 6 -> + new SortField( + TestUtil.randomSimpleString(random()), + SortField.Type.DOUBLE, + reversed, + random().nextBoolean() ? random().nextDouble() : null); + case 7 -> + new SortedNumericSortField( + TestUtil.randomSimpleString(random()), + SortField.Type.DOUBLE, + reversed, + SortedNumericSelector.Type.MIN, + random().nextBoolean() ? random().nextDouble() : null); + case 8 -> + new SortField( + TestUtil.randomSimpleString(random()), + SortField.Type.STRING, + reversed, + random().nextBoolean() ? SortField.STRING_LAST : null); + case 9 -> + new SortedSetSortField( + TestUtil.randomSimpleString(random()), + reversed, + SortedSetSelector.Type.MIN, + random().nextBoolean() ? SortField.STRING_LAST : null); + default -> { fail(); - } - return sortField; + yield null; + } + }; } /** Test sort */