Index: src/java/org/apache/lucene/search/MultiTermQuery.java =================================================================== --- src/java/org/apache/lucene/search/MultiTermQuery.java (revision 889934) +++ src/java/org/apache/lucene/search/MultiTermQuery.java (working copy) @@ -80,11 +80,18 @@ public void setBoost(float boost); /** Retrieves the boost, default is {@code 1.0f}. */ public float getBoost(); + /** Sets the minimum boost as hint to the producer. + * This value is not changed by {@link AttributeImpl#clear} + * and not used in {@code equals()} and {@code hashCode()}. + */ + public void setMinBoostHint(float minBoost); + /** Retrieves the boost, default is megative infinity. */ + public float getMinBoostHint(); } /** Implementation class for {@link BoostAttribute}. */ - public static class BoostAttributeImpl extends AttributeImpl implements BoostAttribute { - private float boost = 1.0f; + public static final class BoostAttributeImpl extends AttributeImpl implements BoostAttribute { + private float boost = 1.0f, minBoost = Float.NEGATIVE_INFINITY; public void setBoost(float boost) { this.boost = boost; @@ -93,6 +100,14 @@ public float getBoost() { return boost; } + + public void setMinBoostHint(float minBoost) { + this.minBoost = minBoost; + } + + public float getMinBoostHint() { + return minBoost; + } @Override public void clear() { @@ -161,6 +176,7 @@ termsEnum.attributes().addAttribute(BoostAttribute.class); if (query.field == null) throw new NullPointerException("If you implement getTermsEnum(), you must specify a non-null field in the constructor of MultiTermQuery."); + collector.boostAtt = boostAtt; int count = 0; TermRef term; final Term placeholderTerm = new Term(query.field); @@ -194,9 +210,17 @@ } } - protected interface TermCollector { + protected static abstract class TermCollector { + /** this field is only set if a boostAttribute is used (e.g. {@link FuzzyTermsEnum}) */ + BoostAttribute boostAtt = null; + /** return false to stop collecting */ - boolean collect(Term t, float boost) throws IOException; + protected abstract boolean collect(Term t, float minBoost) throws IOException; + + /** set the minimum boost as a hint for the term producer */ + protected final void setMinBoostHint(float minBoost) { + if (boostAtt != null) boostAtt.setMinBoostHint(minBoost); + } } } @@ -253,6 +277,7 @@ stQueue.offer(st); // possibly drop entries from queue st = (stQueue.size() > maxSize) ? stQueue.poll() : new ScoreTerm(); + setMinBoostHint((stQueue.size() >= maxSize) ? stQueue.peek().boost : Float.NEGATIVE_INFINITY); return true; } @@ -416,7 +441,7 @@ } } - private static final class CutOffTermCollector implements TermCollector { + private static final class CutOffTermCollector extends TermCollector { CutOffTermCollector(IndexReader reader, int docCountCutoff, int termCountLimit) { this.reader = reader; this.docCountCutoff = docCountCutoff;