LUCENE-2669: Fix NumericRangeQuery.NumericRangeTermsEnum sometimes seeks backwards. This also adds an assert to FilteredTermsEnum that seeking only goes forward.

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1001582 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Uwe Schindler 2010-09-27 04:07:25 +00:00
parent e071186aa3
commit 877e827489
3 changed files with 38 additions and 12 deletions

View File

@ -253,6 +253,11 @@ Optimizations
interval from 128 to 32, because the terms index now requires much
less RAM. (Robert Muir, Mike McCandless)
* LUCENE-2669: Optimize NumericRangeQuery.NumericRangeTermsEnum to
not seek backwards when a sub-range has no terms. It now only seeks
when the current term is less than the next sub-range's lower end.
(Uwe Schindler, Mike McCandless)
Documentation
* LUCENE-2579: Fix oal.search's package.html description of abstract

View File

@ -198,6 +198,8 @@ public abstract class FilteredTermsEnum extends TermsEnum {
if (doSeek) {
doSeek = false;
final BytesRef t = nextSeekTerm(actualTerm);
// Make sure we always seek forward:
assert actualTerm == null || t == null || getComparator().compare(t, actualTerm) > 0: "curTerm=" + actualTerm + " seekTerm=" + t;
if (t == null || tenum.seek(t, useTermsCache) == SeekStatus.END) {
// no more terms to seek to or enum exhausted
return null;

View File

@ -465,28 +465,47 @@ public final class NumericRangeQuery<T extends Number> extends MultiTermQuery {
termComp = getComparator();
}
private void nextRange() {
assert rangeBounds.size() % 2 == 0;
currentLowerBound = rangeBounds.removeFirst();
assert currentUpperBound == null || termComp.compare(currentUpperBound, currentLowerBound) <= 0 :
"The current upper bound must be <= the new lower bound";
currentUpperBound = rangeBounds.removeFirst();
}
@Override
protected final BytesRef nextSeekTerm(BytesRef term) throws IOException {
if (rangeBounds.size() >= 2) {
assert rangeBounds.size() % 2 == 0;
while (rangeBounds.size() >= 2) {
nextRange();
this.currentLowerBound = rangeBounds.removeFirst();
assert currentUpperBound == null || termComp.compare(currentUpperBound, currentLowerBound) <= 0 :
"The current upper bound must be <= the new lower bound";
this.currentUpperBound = rangeBounds.removeFirst();
return currentLowerBound;
// if the new upper bound is before the term parameter, the sub-range is never a hit
if (term != null && termComp.compare(term, currentUpperBound) > 0)
continue;
// never seek backwards, so use current term if lower bound is smaller
return (term != null && termComp.compare(term, currentLowerBound) > 0) ?
term : currentLowerBound;
}
// no more sub-range enums available
assert rangeBounds.size() == 0;
assert rangeBounds.isEmpty();
currentLowerBound = currentUpperBound = null;
return null;
}
@Override
protected AcceptStatus accept(BytesRef term) {
return (currentUpperBound != null && termComp.compare(term, currentUpperBound) <= 0) ?
AcceptStatus.YES : AcceptStatus.NO_AND_SEEK;
protected final AcceptStatus accept(BytesRef term) {
while (currentUpperBound == null || termComp.compare(term, currentUpperBound) > 0) {
if (rangeBounds.isEmpty())
return AcceptStatus.END;
// peek next sub-range, only seek if the current term is smaller than next lower bound
if (termComp.compare(term, rangeBounds.getFirst()) < 0)
return AcceptStatus.NO_AND_SEEK;
// step forward to next range without seeking, as next lower range bound is less or equal current term
nextRange();
}
return AcceptStatus.YES;
}
}