diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index 023c1733b31..df42fd88a93 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -8,6 +8,9 @@ http://s.apache.org/luceneversions API Changes --------------------- +* GITHUB#13859: Allow open-ended ranges in Intervals range queries. (Mayya Sharipova) + + New Features --------------------- (No changes) diff --git a/lucene/queries/src/java/org/apache/lucene/queries/intervals/Intervals.java b/lucene/queries/src/java/org/apache/lucene/queries/intervals/Intervals.java index 57d5674b254..e3808f406cf 100644 --- a/lucene/queries/src/java/org/apache/lucene/queries/intervals/Intervals.java +++ b/lucene/queries/src/java/org/apache/lucene/queries/intervals/Intervals.java @@ -247,8 +247,10 @@ public final class Intervals { * Return an {@link IntervalsSource} over the disjunction of all terms that fall within the given * range * - * @param lowerTerm The term text at the lower end of the range - * @param upperTerm The term text at the upper end of the range + * @param lowerTerm The term text at the lower end of the range; can be {@code null} to indicate + * an open-ended range at this end + * @param upperTerm The term text at the upper end of the range; can be {@code null} to indicate + * an open-ended range at this end * @param includeLower If true, the lowerTerm is included in the range * @param includeUpper If true, the upperTerm is included in the range * @throws IllegalStateException if the range expands to more than {@link #DEFAULT_MAX_EXPANSIONS} @@ -266,8 +268,10 @@ public final class Intervals { *

WARNING: Setting {@code maxExpansions} to higher than the default value of {@link * #DEFAULT_MAX_EXPANSIONS} can be both slow and memory-intensive * - * @param lowerTerm The term text at the lower end of the range - * @param upperTerm The term text at the upper end of the range + * @param lowerTerm The term text at the lower end of the range; can be {@code null} to indicate + * an open-ended range at this end + * @param upperTerm The term text at the upper end of the range; can be {@code null} to indicate + * an open-ended range at this end * @param includeLower If true, the lowerTerm is included in the range * @param includeUpper If true, the upperTerm is included in the range * @param maxExpansions the maximum number of terms to expand to @@ -286,9 +290,9 @@ public final class Intervals { StringBuilder buffer = new StringBuilder(); buffer.append("{"); - buffer.append(lowerTerm.utf8ToString()); + buffer.append(lowerTerm == null ? "* " : lowerTerm.utf8ToString()); buffer.append(","); - buffer.append(upperTerm.utf8ToString()); + buffer.append(upperTerm == null ? "*" : upperTerm.utf8ToString()); buffer.append("}"); return new MultiTermIntervalsSource(ca, maxExpansions, buffer.toString()); } diff --git a/lucene/queries/src/test/org/apache/lucene/queries/intervals/TestIntervals.java b/lucene/queries/src/test/org/apache/lucene/queries/intervals/TestIntervals.java index 43fd8fb7fb8..3d9560858ac 100644 --- a/lucene/queries/src/test/org/apache/lucene/queries/intervals/TestIntervals.java +++ b/lucene/queries/src/test/org/apache/lucene/queries/intervals/TestIntervals.java @@ -1138,6 +1138,46 @@ public class TestIntervals extends LuceneTestCase { checkVisits(source, 1); } + public void testOpenEndedRange() throws IOException { + { + IntervalsSource source = Intervals.range(new BytesRef("porridge"), null, false, false); + checkIntervals( + source, + "field1", + 5, + new int[][] { + {3, 3}, + {9, 9, 10, 10, 14, 14, 18, 18, 22, 22, 26, 26, 27, 27}, + {9, 9, 10, 10, 11, 11, 14, 14, 18, 18, 22, 22, 26, 26}, + {8, 8}, + {9, 9, 10, 10, 12, 12, 14, 14, 18, 18, 21, 21}, + {} + }); + MatchesIterator mi = getMatches(source, 3, "field1"); + assertNotNull(mi); + assertMatch(mi, 8, 8, 37, 41); + } + + { + IntervalsSource source = Intervals.range(null, new BytesRef("anyone"), false, true); + checkIntervals( + source, + "field1", + 1, + new int[][] { + {4, 4}, + {}, + {}, + {}, + {}, + {} + }); + MatchesIterator mi = getMatches(source, 0, "field1"); + assertNotNull(mi); + assertMatch(mi, 4, 4, 23, 29); + } + } + public void testWrappedFilters() throws IOException { IntervalsSource source = Intervals.or(