mirror of https://github.com/apache/lucene.git
LUCENE-10407: Set bpos flag to true when containing filter is exhausted (#648)
ContainedByIntervalIterator and OverlappingIntervalIterator set their 'is the filter interval exhausted' flag to `false` once it has returned NO_MORE_POSITIONS on a document, so that subsequent calls to `startPosition()` will also return NO_MORE_POSITIONS. ContainingIntervalIterator omits to do this, and so it can incorrectly report matches, for example when used in a disjunction. This commit fixes that omission.
This commit is contained in:
parent
9ebee5a058
commit
6b64f4b556
|
@ -223,6 +223,9 @@ Bug Fixes
|
||||||
* LUCENE-10402: Prefix intervals should declare their automaton as binary, otherwise prefixes
|
* LUCENE-10402: Prefix intervals should declare their automaton as binary, otherwise prefixes
|
||||||
containing multibyte characters will not correctly match. (Alan Woodward)
|
containing multibyte characters will not correctly match. (Alan Woodward)
|
||||||
|
|
||||||
|
* LUCENE-10407: Containing intervals could sometimes yield incorrect matches when wrapped
|
||||||
|
in a disjunction. (Alan Woodward, Dawid Weiss)
|
||||||
|
|
||||||
Other
|
Other
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
|
|
|
@ -51,8 +51,10 @@ class ContainingIntervalsSource extends ConjunctionIntervalsSource {
|
||||||
}
|
}
|
||||||
while (a.nextInterval() != IntervalIterator.NO_MORE_INTERVALS) {
|
while (a.nextInterval() != IntervalIterator.NO_MORE_INTERVALS) {
|
||||||
while (b.start() < a.start() && b.end() < a.end()) {
|
while (b.start() < a.start() && b.end() < a.end()) {
|
||||||
if (b.nextInterval() == IntervalIterator.NO_MORE_INTERVALS)
|
if (b.nextInterval() == IntervalIterator.NO_MORE_INTERVALS) {
|
||||||
|
bpos = false;
|
||||||
return IntervalIterator.NO_MORE_INTERVALS;
|
return IntervalIterator.NO_MORE_INTERVALS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (a.start() <= b.start() && a.end() >= b.end()) {
|
if (a.start() <= b.start() && a.end() >= b.end()) {
|
||||||
return a.start();
|
return a.start();
|
||||||
|
|
|
@ -17,6 +17,11 @@
|
||||||
|
|
||||||
package org.apache.lucene.queries.intervals;
|
package org.apache.lucene.queries.intervals;
|
||||||
|
|
||||||
|
import static org.apache.lucene.queries.intervals.Intervals.containing;
|
||||||
|
import static org.apache.lucene.queries.intervals.Intervals.extend;
|
||||||
|
import static org.apache.lucene.queries.intervals.Intervals.or;
|
||||||
|
import static org.apache.lucene.queries.intervals.Intervals.term;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import org.apache.lucene.document.Document;
|
import org.apache.lucene.document.Document;
|
||||||
import org.apache.lucene.document.Field;
|
import org.apache.lucene.document.Field;
|
||||||
|
@ -50,9 +55,9 @@ public class TestIntervalQuery extends LuceneTestCase {
|
||||||
random(),
|
random(),
|
||||||
directory,
|
directory,
|
||||||
newIndexWriterConfig(new MockAnalyzer(random())).setMergePolicy(newLogMergePolicy()));
|
newIndexWriterConfig(new MockAnalyzer(random())).setMergePolicy(newLogMergePolicy()));
|
||||||
for (int i = 0; i < docFields.length; i++) {
|
for (String docField : docFields) {
|
||||||
Document doc = new Document();
|
Document doc = new Document();
|
||||||
doc.add(newTextField(field, docFields[i], Field.Store.YES));
|
doc.add(newTextField(field, docField, Field.Store.YES));
|
||||||
writer.addDocument(doc);
|
writer.addDocument(doc);
|
||||||
}
|
}
|
||||||
reader = writer.getReader();
|
reader = writer.getReader();
|
||||||
|
@ -67,7 +72,7 @@ public class TestIntervalQuery extends LuceneTestCase {
|
||||||
super.tearDown();
|
super.tearDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String[] docFields = {
|
private final String[] docFields = {
|
||||||
"w1 w2 w3 w4 w5",
|
"w1 w2 w3 w4 w5",
|
||||||
"w1 w3 w2 w3",
|
"w1 w3 w2 w3",
|
||||||
"w1 xx w2 w4 yy w3",
|
"w1 xx w2 w4 yy w3",
|
||||||
|
@ -168,7 +173,7 @@ public class TestIntervalQuery extends LuceneTestCase {
|
||||||
assertTrue(explain.toString().contains(field));
|
assertTrue(explain.toString().contains(field));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNullConstructorArgs() throws IOException {
|
public void testNullConstructorArgs() {
|
||||||
expectThrows(NullPointerException.class, () -> new IntervalQuery(null, Intervals.term("z")));
|
expectThrows(NullPointerException.class, () -> new IntervalQuery(null, Intervals.term("z")));
|
||||||
expectThrows(NullPointerException.class, () -> new IntervalQuery("field", null));
|
expectThrows(NullPointerException.class, () -> new IntervalQuery("field", null));
|
||||||
}
|
}
|
||||||
|
@ -423,4 +428,11 @@ public class TestIntervalQuery extends LuceneTestCase {
|
||||||
Query q = new IntervalQuery(field, Intervals.prefix(new BytesRef("場")));
|
Query q = new IntervalQuery(field, Intervals.prefix(new BytesRef("場")));
|
||||||
checkHits(q, new int[] {11});
|
checkHits(q, new int[] {11});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testExtendDisjunctions() throws IOException {
|
||||||
|
Query q =
|
||||||
|
new IntervalQuery(
|
||||||
|
field, or(term("XXX"), containing(extend(term("message"), 0, 10), term("intend"))));
|
||||||
|
checkHits(q, new int[] {});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue