You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ab...@apache.org on 2017/12/07 12:45:40 UTC
[46/50] [abbrv] lucene-solr:jira/solr-11285-sim: LUCENE-4100: Faster
disjunctions when the hit count is not needed.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/TermInSetQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/TermInSetQuery.java b/lucene/core/src/java/org/apache/lucene/search/TermInSetQuery.java
index 19b3922..95f6564 100644
--- a/lucene/core/src/java/org/apache/lucene/search/TermInSetQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/TermInSetQuery.java
@@ -205,7 +205,7 @@ public class TermInSetQuery extends Query implements Accountable {
}
@Override
- public Weight createWeight(IndexSearcher searcher, boolean needsScores, float boost) throws IOException {
+ public Weight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
return new ConstantScoreWeight(this, boost) {
@Override
@@ -269,7 +269,7 @@ public class TermInSetQuery extends Query implements Accountable {
bq.add(new TermQuery(new Term(t.field, t.term), termContext), Occur.SHOULD);
}
Query q = new ConstantScoreQuery(bq.build());
- final Weight weight = searcher.rewrite(q).createWeight(searcher, needsScores, score());
+ final Weight weight = searcher.rewrite(q).createWeight(searcher, scoreMode, score());
return new WeightOrDocIdSet(weight);
} else {
assert builder != null;
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/TermQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/TermQuery.java b/lucene/core/src/java/org/apache/lucene/search/TermQuery.java
index 5b3f1ad..925fe93 100644
--- a/lucene/core/src/java/org/apache/lucene/search/TermQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/TermQuery.java
@@ -21,6 +21,7 @@ import java.io.IOException;
import java.util.Objects;
import java.util.Set;
+import org.apache.lucene.index.IndexOptions;
import org.apache.lucene.index.IndexReaderContext;
import org.apache.lucene.index.LeafReader;
import org.apache.lucene.index.LeafReaderContext;
@@ -94,9 +95,25 @@ public class TermQuery extends Query {
if (termsEnum == null) {
return null;
}
+ IndexOptions indexOptions = context.reader()
+ .getFieldInfos()
+ .fieldInfo(getTerm().field())
+ .getIndexOptions();
PostingsEnum docs = termsEnum.postings(null, needsScores ? PostingsEnum.FREQS : PostingsEnum.NONE);
assert docs != null;
- return new TermScorer(this, docs, similarity.simScorer(stats, context));
+ return new TermScorer(this, docs, similarity.simScorer(stats, context),
+ getMaxFreq(indexOptions, termsEnum.totalTermFreq(), termsEnum.docFreq()));
+ }
+
+ private long getMaxFreq(IndexOptions indexOptions, long ttf, long df) {
+ // TODO: store the max term freq?
+ if (indexOptions.compareTo(IndexOptions.DOCS) <= 0) {
+ // omitTFAP field, tf values are implicitly 1.
+ return 1;
+ } else {
+ assert ttf >= 0;
+ return Math.min(Integer.MAX_VALUE, ttf - df + 1);
+ }
}
@Override
@@ -185,12 +202,12 @@ public class TermQuery extends Query {
}
@Override
- public Weight createWeight(IndexSearcher searcher, boolean needsScores, float boost) throws IOException {
+ public Weight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
final IndexReaderContext context = searcher.getTopReaderContext();
final TermContext termState;
if (perReaderTermState == null
|| perReaderTermState.wasBuiltFor(context) == false) {
- if (needsScores) {
+ if (scoreMode.needsScores()) {
// make TermQuery single-pass if we don't have a PRTS or if the context
// differs!
termState = TermContext.build(context, term);
@@ -204,7 +221,7 @@ public class TermQuery extends Query {
termState = this.perReaderTermState;
}
- return new TermWeight(searcher, needsScores, boost, termState);
+ return new TermWeight(searcher, scoreMode.needsScores(), boost, termState);
}
/** Prints a user-readable version of this query. */
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/TermScorer.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/TermScorer.java b/lucene/core/src/java/org/apache/lucene/search/TermScorer.java
index c478a25..a4aeb04 100644
--- a/lucene/core/src/java/org/apache/lucene/search/TermScorer.java
+++ b/lucene/core/src/java/org/apache/lucene/search/TermScorer.java
@@ -27,6 +27,7 @@ import org.apache.lucene.search.similarities.Similarity;
final class TermScorer extends Scorer {
private final PostingsEnum postingsEnum;
private final Similarity.SimScorer docScorer;
+ private final float maxFreq;
/**
* Construct a <code>TermScorer</code>.
@@ -38,11 +39,14 @@ final class TermScorer extends Scorer {
* @param docScorer
* The <code>Similarity.SimScorer</code> implementation
* to be used for score computations.
+ * @param maxFreq
+ * An upper bound of the term frequency of the searched term in any document.
*/
- TermScorer(Weight weight, PostingsEnum td, Similarity.SimScorer docScorer) {
+ TermScorer(Weight weight, PostingsEnum td, Similarity.SimScorer docScorer, float maxFreq) {
super(weight);
this.docScorer = docScorer;
this.postingsEnum = td;
+ this.maxFreq = maxFreq;
}
@Override
@@ -65,6 +69,11 @@ final class TermScorer extends Scorer {
return docScorer.score(postingsEnum.docID(), postingsEnum.freq());
}
+ @Override
+ public float maxScore() {
+ return docScorer.maxScore(maxFreq);
+ }
+
/** Returns a string representation of this <code>TermScorer</code>. */
@Override
public String toString() { return "scorer(" + weight + ")[" + super.toString() + "]"; }
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/TimeLimitingCollector.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/TimeLimitingCollector.java b/lucene/core/src/java/org/apache/lucene/search/TimeLimitingCollector.java
index 4708b20..6957994 100644
--- a/lucene/core/src/java/org/apache/lucene/search/TimeLimitingCollector.java
+++ b/lucene/core/src/java/org/apache/lucene/search/TimeLimitingCollector.java
@@ -162,8 +162,8 @@ public class TimeLimitingCollector implements Collector {
}
@Override
- public boolean needsScores() {
- return collector.needsScores();
+ public ScoreMode scoreMode() {
+ return collector.scoreMode();
}
/**
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/TopDocsCollector.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/TopDocsCollector.java b/lucene/core/src/java/org/apache/lucene/search/TopDocsCollector.java
index 86bf17e..219ee3a 100644
--- a/lucene/core/src/java/org/apache/lucene/search/TopDocsCollector.java
+++ b/lucene/core/src/java/org/apache/lucene/search/TopDocsCollector.java
@@ -43,7 +43,7 @@ public abstract class TopDocsCollector<T extends ScoreDoc> implements Collector
* HitQueue for example aggregates the top scoring documents, while other PQ
* implementations may hold documents sorted by other criteria.
*/
- protected PriorityQueue<T> pq;
+ protected final PriorityQueue<T> pq;
/** The total number of documents that the collector encountered. */
protected int totalHits;
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/TopFieldCollector.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/TopFieldCollector.java b/lucene/core/src/java/org/apache/lucene/search/TopFieldCollector.java
index 94f156e..c3597e9 100644
--- a/lucene/core/src/java/org/apache/lucene/search/TopFieldCollector.java
+++ b/lucene/core/src/java/org/apache/lucene/search/TopFieldCollector.java
@@ -338,8 +338,8 @@ public abstract class TopFieldCollector extends TopDocsCollector<Entry> {
}
@Override
- public boolean needsScores() {
- return needsScores;
+ public ScoreMode scoreMode() {
+ return needsScores ? ScoreMode.COMPLETE : ScoreMode.COMPLETE_NO_SCORES;
}
/**
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/TopScoreDocCollector.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/TopScoreDocCollector.java b/lucene/core/src/java/org/apache/lucene/search/TopScoreDocCollector.java
index bc5ba16..afae1fc 100644
--- a/lucene/core/src/java/org/apache/lucene/search/TopScoreDocCollector.java
+++ b/lucene/core/src/java/org/apache/lucene/search/TopScoreDocCollector.java
@@ -49,17 +49,37 @@ public abstract class TopScoreDocCollector extends TopDocsCollector<ScoreDoc> {
private static class SimpleTopScoreDocCollector extends TopScoreDocCollector {
- SimpleTopScoreDocCollector(int numHits) {
+ private final int numHits;
+ private final boolean trackTotalHits;
+ private int sumMaxDoc;
+ private int maxCollectedExactly = -1;
+
+ SimpleTopScoreDocCollector(int numHits, boolean trackTotalHits) {
super(numHits);
+ this.numHits = numHits;
+ this.trackTotalHits = trackTotalHits;
}
@Override
public LeafCollector getLeafCollector(LeafReaderContext context)
throws IOException {
final int docBase = context.docBase;
+ sumMaxDoc += context.reader().maxDoc();
return new ScorerLeafCollector() {
@Override
+ public void setScorer(Scorer scorer) throws IOException {
+ super.setScorer(scorer);
+ if (trackTotalHits == false
+ && pqTop != null
+ && pqTop.score != Float.NEGATIVE_INFINITY) {
+ // since we tie-break on doc id and collect in doc id order, we can require
+ // the next float
+ scorer.setMinCompetitiveScore(Math.nextUp(pqTop.score));
+ }
+ }
+
+ @Override
public void collect(int doc) throws IOException {
float score = scorer.score();
@@ -76,11 +96,38 @@ public abstract class TopScoreDocCollector extends TopDocsCollector<ScoreDoc> {
pqTop.doc = doc + docBase;
pqTop.score = score;
pqTop = pq.updateTop();
+ if (trackTotalHits == false && pqTop.score != Float.NEGATIVE_INFINITY) { // -Infinity is the score of sentinels
+ // since we tie-break on doc id and collect in doc id order, we can require
+ // the next float
+ scorer.setMinCompetitiveScore(Math.nextUp(pqTop.score));
+ if (maxCollectedExactly < 0) {
+ assert totalHits == numHits;
+ maxCollectedExactly = doc + docBase;
+ }
+ }
}
};
}
+ @Override
+ public TopDocs topDocs() {
+ TopDocs topDocs = super.topDocs();
+ if (trackTotalHits == false && maxCollectedExactly >= 0) {
+ // assume matches are evenly spread in the doc id space
+ // this may be completely off
+ long totalHitsEstimate = (long) numHits * sumMaxDoc / (maxCollectedExactly + 1);
+ // we take the max since the current topDocs.totalHits is a lower bound
+ // of the total hit count
+ topDocs.totalHits = Math.max(topDocs.totalHits, totalHitsEstimate);
+ }
+ return topDocs;
+ }
+
+ @Override
+ public ScoreMode scoreMode() {
+ return trackTotalHits ? ScoreMode.COMPLETE : ScoreMode.TOP_SCORES;
+ }
}
private static class PagingTopScoreDocCollector extends TopScoreDocCollector {
@@ -140,8 +187,7 @@ public abstract class TopScoreDocCollector extends TopDocsCollector<ScoreDoc> {
/**
* Creates a new {@link TopScoreDocCollector} given the number of hits to
- * collect and whether documents are scored in order by the input
- * {@link Scorer} to {@link LeafCollector#setScorer(Scorer)}.
+ * collect.
*
* <p><b>NOTE</b>: The instances returned by this method
* pre-allocate a full array of length
@@ -149,27 +195,30 @@ public abstract class TopScoreDocCollector extends TopDocsCollector<ScoreDoc> {
* objects.
*/
public static TopScoreDocCollector create(int numHits) {
- return create(numHits, null);
+ return create(numHits, null, true);
}
/**
* Creates a new {@link TopScoreDocCollector} given the number of hits to
- * collect, the bottom of the previous page, and whether documents are scored in order by the input
- * {@link Scorer} to {@link LeafCollector#setScorer(Scorer)}.
+ * collect, the bottom of the previous page, and whether the total hit count
+ * is needed.
*
+ * <p><b>NOTE</b>: If {@code trackTotalHits} is {@code false} then the
+ * {@link TopDocs#totalHits} of the returned {@link TopDocs} will be an
+ * approximation and may be completely off.
* <p><b>NOTE</b>: The instances returned by this method
* pre-allocate a full array of length
* <code>numHits</code>, and fill the array with sentinel
* objects.
*/
- public static TopScoreDocCollector create(int numHits, ScoreDoc after) {
+ public static TopScoreDocCollector create(int numHits, ScoreDoc after, boolean trackTotalHits) {
if (numHits <= 0) {
throw new IllegalArgumentException("numHits must be > 0; please use TotalHitCountCollector if you just need the total hit count");
}
if (after == null) {
- return new SimpleTopScoreDocCollector(numHits);
+ return new SimpleTopScoreDocCollector(numHits, trackTotalHits);
} else {
return new PagingTopScoreDocCollector(numHits, after);
}
@@ -207,7 +256,7 @@ public abstract class TopScoreDocCollector extends TopDocsCollector<ScoreDoc> {
}
@Override
- public boolean needsScores() {
- return true;
+ public ScoreMode scoreMode() {
+ return ScoreMode.COMPLETE;
}
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/TotalHitCountCollector.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/TotalHitCountCollector.java b/lucene/core/src/java/org/apache/lucene/search/TotalHitCountCollector.java
index e5180f9..2d0139c 100644
--- a/lucene/core/src/java/org/apache/lucene/search/TotalHitCountCollector.java
+++ b/lucene/core/src/java/org/apache/lucene/search/TotalHitCountCollector.java
@@ -35,7 +35,7 @@ public class TotalHitCountCollector extends SimpleCollector {
}
@Override
- public boolean needsScores() {
- return false;
+ public ScoreMode scoreMode() {
+ return ScoreMode.COMPLETE_NO_SCORES;
}
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/WANDScorer.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/WANDScorer.java b/lucene/core/src/java/org/apache/lucene/search/WANDScorer.java
new file mode 100644
index 0000000..2f3b600
--- /dev/null
+++ b/lucene/core/src/java/org/apache/lucene/search/WANDScorer.java
@@ -0,0 +1,478 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.lucene.search;
+
+import static org.apache.lucene.search.DisiPriorityQueue.leftNode;
+import static org.apache.lucene.search.DisiPriorityQueue.parentNode;
+import static org.apache.lucene.search.DisiPriorityQueue.rightNode;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.OptionalInt;
+
+/**
+ * This implements the WAND (Weak AND) algorithm for dynamic pruning
+ * described in "Efficient Query Evaluation using a Two-Level Retrieval
+ * Process" by Broder, Carmel, Herscovici, Soffer and Zien.
+ * This scorer maintains a feedback loop with the collector in order to
+ * know at any time the minimum score that is required in order for a hit
+ * to be competitive. Then it leverages the {@link Scorer#maxScore() max score}
+ * from each scorer in order to know when it may call
+ * {@link DocIdSetIterator#advance} rather than {@link DocIdSetIterator#nextDoc}
+ * to move to the next competitive hit.
+ * Implementation is similar to {@link MinShouldMatchSumScorer} except that
+ * instead of enforcing that {@code freq >= minShouldMatch}, we enforce that
+ * {@code ∑ max_score >= minCompetitiveScore}.
+ */
+final class WANDScorer extends Scorer {
+
+ /** Return a scaling factor for the given float so that
+ * f x 2^scalingFactor would be in ]2^15, 2^16]. Special
+ * cases:
+ * scalingFactor(0) = scalingFactor(MIN_VALUE) - 1
+ * scalingFactor(+Infty) = scalingFactor(MAX_VALUE) + 1
+ */
+ static int scalingFactor(float f) {
+ if (f < 0) {
+ throw new IllegalArgumentException("");
+ } else if (f == 0) {
+ return scalingFactor(Float.MIN_VALUE) - 1;
+ } else if (Float.isInfinite(f)) {
+ return scalingFactor(Float.MAX_VALUE) + 1;
+ } else {
+ double d = f;
+ // Since doubles have more amplitude than floats for the
+ // exponent, the cast produces a normal value.
+ assert d == 0 || Math.getExponent(d) >= Double.MIN_EXPONENT; // normal double
+ return 15 - Math.getExponent(Math.nextDown(d));
+ }
+ }
+
+ /**
+ * Scale max scores in an unsigned integer to avoid overflows
+ * (only the lower 32 bits of the long are used) as well as
+ * floating-point arithmetic errors. Those are rounded up in order
+ * to make sure we do not miss any matches.
+ */
+ private static long scaleMaxScore(float maxScore, int scalingFactor) {
+ assert Float.isNaN(maxScore) == false;
+ assert maxScore >= 0;
+
+ if (Float.isInfinite(maxScore)) {
+ return (1L << 32) - 1; // means +Infinity in practice for this scorer
+ }
+
+ // NOTE: because doubles have more amplitude than floats for the
+ // exponent, the scalb call produces an accurate value.
+ double scaled = Math.scalb((double) maxScore, scalingFactor);
+ assert scaled <= 1 << 16 : scaled + " " + maxScore; // regular values of max_score go into 0..2^16
+ return (long) Math.ceil(scaled); // round up, cast is accurate since value is <= 2^16
+ }
+
+ /**
+ * Scale min competitive scores the same way as max scores but this time
+ * by rounding down in order to make sure that we do not miss any matches.
+ */
+ private static long scaleMinScore(float minScore, int scalingFactor) {
+ assert Float.isNaN(minScore) == false;
+ assert minScore >= 0;
+
+ // like for scaleMaxScore, this scalb call is accurate
+ double scaled = Math.scalb((double) minScore, scalingFactor);
+ return (long) Math.floor(scaled); // round down, cast might lower the value again if scaled > Long.MAX_VALUE, which is fine
+ }
+
+ private final int scalingFactor;
+ // scaled min competitive score
+ private long minCompetitiveScore = 0;
+
+ // list of scorers which 'lead' the iteration and are currently
+ // positioned on 'doc'. This is sometimes called the 'pivot' in
+ // some descriptions of WAND (Weak AND).
+ DisiWrapper lead;
+ int doc; // current doc ID of the leads
+ long leadMaxScore; // sum of the max scores of scorers in 'lead'
+
+ // priority queue of scorers that are too advanced compared to the current
+ // doc. Ordered by doc ID.
+ final DisiPriorityQueue head;
+
+ // priority queue of scorers which are behind the current doc.
+ // Ordered by maxScore.
+ final DisiWrapper[] tail;
+ long tailMaxScore; // sum of the max scores of scorers in 'tail'
+ int tailSize;
+
+ final long cost;
+
+ WANDScorer(Weight weight, Collection<Scorer> scorers) {
+ super(weight);
+
+ this.minCompetitiveScore = 0;
+ this.doc = -1;
+
+ head = new DisiPriorityQueue(scorers.size());
+ // there can be at most num_scorers - 1 scorers beyond the current position
+ tail = new DisiWrapper[scorers.size() - 1];
+
+ OptionalInt scalingFactor = OptionalInt.empty();
+ for (Scorer scorer : scorers) {
+ float maxScore = scorer.maxScore();
+ if (maxScore != 0 && Float.isFinite(maxScore)) {
+ // 0 and +Infty should not impact the scale
+ scalingFactor = OptionalInt.of(Math.min(scalingFactor.orElse(Integer.MAX_VALUE), scalingFactor(maxScore)));
+ }
+ }
+ // Use a scaling factor of 0 if all max scores are either 0 or +Infty
+ this.scalingFactor = scalingFactor.orElse(0);
+
+ for (Scorer scorer : scorers) {
+ DisiWrapper w = new DisiWrapper(scorer);
+ float maxScore = scorer.maxScore();
+ w.maxScore = scaleMaxScore(maxScore, this.scalingFactor);
+ addLead(w);
+ }
+
+ long cost = 0;
+ for (DisiWrapper w = lead; w != null; w = w.next) {
+ cost += w.cost;
+ }
+ this.cost = cost;
+ }
+
+ // returns a boolean so that it can be called from assert
+ // the return value is useless: it always returns true
+ private boolean ensureConsistent() {
+ long maxScoreSum = 0;
+ for (int i = 0; i < tailSize; ++i) {
+ assert tail[i].doc < doc;
+ maxScoreSum = Math.addExact(maxScoreSum, tail[i].maxScore);
+ }
+ assert maxScoreSum == tailMaxScore : maxScoreSum + " " + tailMaxScore;
+
+ maxScoreSum = 0;
+ for (DisiWrapper w = lead; w != null; w = w.next) {
+ assert w.doc == doc;
+ maxScoreSum = Math.addExact(maxScoreSum, w.maxScore);
+ }
+ assert maxScoreSum == leadMaxScore : maxScoreSum + " " + leadMaxScore;
+
+ for (DisiWrapper w : head) {
+ assert w.doc > doc;
+ }
+
+ assert tailSize == 0 || tailMaxScore < minCompetitiveScore;
+
+ return true;
+ }
+
+ @Override
+ public void setMinCompetitiveScore(float minScore) {
+ assert minScore >= 0;
+ long scaledMinScore = scaleMinScore(minScore, scalingFactor);
+ assert scaledMinScore >= minCompetitiveScore;
+ minCompetitiveScore = scaledMinScore;
+ }
+
+ @Override
+ public final Collection<ChildScorer> getChildren() throws IOException {
+ List<ChildScorer> matchingChildren = new ArrayList<>();
+ updateFreq();
+ for (DisiWrapper s = lead; s != null; s = s.next) {
+ matchingChildren.add(new ChildScorer(s.scorer, "SHOULD"));
+ }
+ return matchingChildren;
+ }
+
+ @Override
+ public DocIdSetIterator iterator() {
+ return TwoPhaseIterator.asDocIdSetIterator(twoPhaseIterator());
+ }
+
+ @Override
+ public TwoPhaseIterator twoPhaseIterator() {
+ DocIdSetIterator approximation = new DocIdSetIterator() {
+
+ @Override
+ public int docID() {
+ return doc;
+ }
+
+ @Override
+ public int nextDoc() throws IOException {
+ return advance(doc + 1);
+ }
+
+ @Override
+ public int advance(int target) throws IOException {
+ assert ensureConsistent();
+
+ // Move 'lead' iterators back to the tail
+ pushBackLeads(target);
+
+ // Advance 'head' as well
+ advanceHead(target);
+
+ // Pop the new 'lead' from the 'head'
+ setDocAndFreq();
+
+ assert ensureConsistent();
+
+ // Advance to the next possible match
+ return doNextCandidate();
+ }
+
+ @Override
+ public long cost() {
+ return cost;
+ }
+ };
+ return new TwoPhaseIterator(approximation) {
+
+ @Override
+ public boolean matches() throws IOException {
+ while (leadMaxScore < minCompetitiveScore) {
+ if (leadMaxScore + tailMaxScore >= minCompetitiveScore) {
+ // a match on doc is still possible, try to
+ // advance scorers from the tail
+ advanceTail();
+ } else {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public float matchCost() {
+ // maximum number of scorer that matches() might advance
+ return tail.length;
+ }
+
+ };
+ }
+
+ private void addLead(DisiWrapper lead) {
+ lead.next = this.lead;
+ this.lead = lead;
+ leadMaxScore += lead.maxScore;
+ }
+
+ private void pushBackLeads(int target) throws IOException {
+ for (DisiWrapper s = lead; s != null; s = s.next) {
+ final DisiWrapper evicted = insertTailWithOverFlow(s);
+ if (evicted != null) {
+ evicted.doc = evicted.iterator.advance(target);
+ head.add(evicted);
+ }
+ }
+ }
+
+ private void advanceHead(int target) throws IOException {
+ DisiWrapper headTop = head.top();
+ while (headTop.doc < target) {
+ final DisiWrapper evicted = insertTailWithOverFlow(headTop);
+ if (evicted != null) {
+ evicted.doc = evicted.iterator.advance(target);
+ headTop = head.updateTop(evicted);
+ } else {
+ head.pop();
+ headTop = head.top();
+ }
+ }
+ }
+
+ private void advanceTail(DisiWrapper disi) throws IOException {
+ disi.doc = disi.iterator.advance(doc);
+ if (disi.doc == doc) {
+ addLead(disi);
+ } else {
+ head.add(disi);
+ }
+ }
+
+ private void advanceTail() throws IOException {
+ final DisiWrapper top = popTail();
+ advanceTail(top);
+ }
+
+ /** Reinitializes head, freq and doc from 'head' */
+ private void setDocAndFreq() {
+ assert head.size() > 0;
+
+ // The top of `head` defines the next potential match
+ // pop all documents which are on this doc
+ lead = head.pop();
+ lead.next = null;
+ leadMaxScore = lead.maxScore;
+ doc = lead.doc;
+ while (head.size() > 0 && head.top().doc == doc) {
+ addLead(head.pop());
+ }
+ }
+
+ /** Move iterators to the tail until there is a potential match. */
+ private int doNextCandidate() throws IOException {
+ while (leadMaxScore + tailMaxScore < minCompetitiveScore) {
+ // no match on doc is possible, move to the next potential match
+ if (head.size() == 0) {
+ // special case: the total max score is less than the min competitive score, there are no more matches
+ return doc = DocIdSetIterator.NO_MORE_DOCS;
+ }
+ pushBackLeads(doc + 1);
+ setDocAndFreq();
+ assert ensureConsistent();
+ }
+
+ return doc;
+ }
+
+ /** Advance all entries from the tail to know about all matches on the
+ * current doc. */
+ private void updateFreq() throws IOException {
+ // we return the next doc when the sum of the scores of the potential
+ // matching clauses is high enough but some of the clauses in 'tail' might
+ // match as well
+ // in general we want to advance least-costly clauses first in order to
+ // skip over non-matching documents as fast as possible. However here,
+ // we are advancing everything anyway so iterating over clauses in
+ // (roughly) cost-descending order might help avoid some permutations in
+ // the head heap
+ for (int i = tailSize - 1; i >= 0; --i) {
+ advanceTail(tail[i]);
+ }
+ tailSize = 0;
+ tailMaxScore = 0;
+ assert ensureConsistent();
+ }
+
+ @Override
+ public float score() throws IOException {
+ // we need to know about all matches
+ updateFreq();
+ double score = 0;
+ for (DisiWrapper s = lead; s != null; s = s.next) {
+ score += s.scorer.score();
+ }
+ return (float) score;
+ }
+
+ @Override
+ public float maxScore() {
+ // TODO: implement but be careful about floating-point errors.
+ return Float.POSITIVE_INFINITY;
+ }
+
+ @Override
+ public int docID() {
+ return doc;
+ }
+
+ /** Insert an entry in 'tail' and evict the least-costly scorer if full. */
+ private DisiWrapper insertTailWithOverFlow(DisiWrapper s) {
+ if (tailSize < tail.length && tailMaxScore + s.maxScore < minCompetitiveScore) {
+ // we have free room for this new entry
+ addTail(s);
+ tailMaxScore += s.maxScore;
+ return null;
+ } else if (tailSize == 0) {
+ return s;
+ } else {
+ final DisiWrapper top = tail[0];
+ if (greaterMaxScore(top, s) == false) {
+ return s;
+ }
+ // Swap top and s
+ tail[0] = s;
+ downHeapMaxScore(tail, tailSize);
+ tailMaxScore = tailMaxScore - top.maxScore + s.maxScore;
+ return top;
+ }
+ }
+
+ /** Add an entry to 'tail'. Fails if over capacity. */
+ private void addTail(DisiWrapper s) {
+ tail[tailSize] = s;
+ upHeapMaxScore(tail, tailSize);
+ tailSize += 1;
+ }
+
+ /** Pop the least-costly scorer from 'tail'. */
+ private DisiWrapper popTail() {
+ assert tailSize > 0;
+ final DisiWrapper result = tail[0];
+ tail[0] = tail[--tailSize];
+ downHeapMaxScore(tail, tailSize);
+ tailMaxScore -= result.maxScore;
+ return result;
+ }
+
+ /** Heap helpers */
+
+ private static void upHeapMaxScore(DisiWrapper[] heap, int i) {
+ final DisiWrapper node = heap[i];
+ int j = parentNode(i);
+ while (j >= 0 && greaterMaxScore(node, heap[j])) {
+ heap[i] = heap[j];
+ i = j;
+ j = parentNode(j);
+ }
+ heap[i] = node;
+ }
+
+ private static void downHeapMaxScore(DisiWrapper[] heap, int size) {
+ int i = 0;
+ final DisiWrapper node = heap[0];
+ int j = leftNode(i);
+ if (j < size) {
+ int k = rightNode(j);
+ if (k < size && greaterMaxScore(heap[k], heap[j])) {
+ j = k;
+ }
+ if (greaterMaxScore(heap[j], node)) {
+ do {
+ heap[i] = heap[j];
+ i = j;
+ j = leftNode(i);
+ k = rightNode(j);
+ if (k < size && greaterMaxScore(heap[k], heap[j])) {
+ j = k;
+ }
+ } while (j < size && greaterMaxScore(heap[j], node));
+ heap[i] = node;
+ }
+ }
+ }
+
+ /**
+ * In the tail, we want to get first entries that produce the maximum scores
+ * and in case of ties (eg. constant-score queries), those that have the least
+ * cost so that they are likely to advance further.
+ */
+ private static boolean greaterMaxScore(DisiWrapper w1, DisiWrapper w2) {
+ if (w1.maxScore > w2.maxScore) {
+ return true;
+ } else if (w1.maxScore < w2.maxScore) {
+ return false;
+ } else {
+ return w1.cost < w2.cost;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/Weight.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/Weight.java b/lucene/core/src/java/org/apache/lucene/search/Weight.java
index 3892d4f..7853ccf 100644
--- a/lucene/core/src/java/org/apache/lucene/search/Weight.java
+++ b/lucene/core/src/java/org/apache/lucene/search/Weight.java
@@ -43,7 +43,7 @@ import org.apache.lucene.util.Bits;
* A <code>Weight</code> is used in the following way:
* <ol>
* <li>A <code>Weight</code> is constructed by a top-level query, given a
- * <code>IndexSearcher</code> ({@link Query#createWeight(IndexSearcher, boolean, float)}).
+ * <code>IndexSearcher</code> ({@link Query#createWeight(IndexSearcher, ScoreMode, float)}).
* <li>A <code>Scorer</code> is constructed by
* {@link #scorer(org.apache.lucene.index.LeafReaderContext)}.
* </ol>
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/package-info.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/package-info.java b/lucene/core/src/java/org/apache/lucene/search/package-info.java
index 52b9411..69c5c2a 100644
--- a/lucene/core/src/java/org/apache/lucene/search/package-info.java
+++ b/lucene/core/src/java/org/apache/lucene/search/package-info.java
@@ -338,7 +338,7 @@
* {@link org.apache.lucene.search.Query Query} class has several methods that are important for
* derived classes:
* <ol>
- * <li>{@link org.apache.lucene.search.Query#createWeight(IndexSearcher,boolean,float) createWeight(IndexSearcher searcher, boolean needsScores, float boost)} — A
+ * <li>{@link org.apache.lucene.search.Query#createWeight(IndexSearcher,ScoreMode,float) createWeight(IndexSearcher searcher, boolean needsScores, float boost)} — A
* {@link org.apache.lucene.search.Weight Weight} is the internal representation of the
* Query, so each Query implementation must
* provide an implementation of Weight. See the subsection on <a
@@ -347,7 +347,7 @@
* <li>{@link org.apache.lucene.search.Query#rewrite(org.apache.lucene.index.IndexReader) rewrite(IndexReader reader)} — Rewrites queries into primitive queries. Primitive queries are:
* {@link org.apache.lucene.search.TermQuery TermQuery},
* {@link org.apache.lucene.search.BooleanQuery BooleanQuery}, <span
- * >and other queries that implement {@link org.apache.lucene.search.Query#createWeight(IndexSearcher,boolean,float) createWeight(IndexSearcher searcher,boolean needsScores, float boost)}</span></li>
+ * >and other queries that implement {@link org.apache.lucene.search.Query#createWeight(IndexSearcher,ScoreMode,float) createWeight(IndexSearcher searcher,boolean needsScores, float boost)}</span></li>
* </ol>
* <a name="weightClass"></a>
* <h3>The Weight Interface</h3>
@@ -453,7 +453,7 @@
* <p>Assuming we are not sorting (since sorting doesn't affect the raw Lucene score),
* we call one of the search methods of the IndexSearcher, passing in the
* {@link org.apache.lucene.search.Weight Weight} object created by
- * {@link org.apache.lucene.search.IndexSearcher#createNormalizedWeight(org.apache.lucene.search.Query,boolean)
+ * {@link org.apache.lucene.search.IndexSearcher#createNormalizedWeight(org.apache.lucene.search.Query,ScoreMode)
* IndexSearcher.createNormalizedWeight(Query,boolean)} and the number of results we want.
* This method returns a {@link org.apache.lucene.search.TopDocs TopDocs} object,
* which is an internal collection of search results. The IndexSearcher creates
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/similarities/Axiomatic.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/similarities/Axiomatic.java b/lucene/core/src/java/org/apache/lucene/search/similarities/Axiomatic.java
index 9183cb6..2a7f353 100644
--- a/lucene/core/src/java/org/apache/lucene/search/similarities/Axiomatic.java
+++ b/lucene/core/src/java/org/apache/lucene/search/similarities/Axiomatic.java
@@ -109,6 +109,12 @@ public abstract class Axiomatic extends SimilarityBase {
}
@Override
+ protected double maxScore(BasicStats stats, double maxFreq) {
+ // TODO: can we compute a better upper bound on the produced scores
+ return Double.POSITIVE_INFINITY;
+ }
+
+ @Override
protected void explain(List<Explanation> subs, BasicStats stats, int doc,
double freq, double docLen) {
if (stats.getBoost() != 1.0d) {
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/similarities/BM25Similarity.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/similarities/BM25Similarity.java b/lucene/core/src/java/org/apache/lucene/search/similarities/BM25Similarity.java
index 9810d3d..c920891 100644
--- a/lucene/core/src/java/org/apache/lucene/search/similarities/BM25Similarity.java
+++ b/lucene/core/src/java/org/apache/lucene/search/similarities/BM25Similarity.java
@@ -223,7 +223,13 @@ public class BM25Similarity extends Similarity {
}
return weightValue * (float) (freq / (freq + norm));
}
-
+
+ @Override
+ public float maxScore(float maxFreq) {
+ // TODO: leverage maxFreq and the min norm from the cache
+ return weightValue;
+ }
+
@Override
public Explanation explain(int doc, Explanation freq) throws IOException {
List<Explanation> subs = new ArrayList<>();
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/similarities/BooleanSimilarity.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/similarities/BooleanSimilarity.java b/lucene/core/src/java/org/apache/lucene/search/similarities/BooleanSimilarity.java
index e1ad2e8..35f7083 100644
--- a/lucene/core/src/java/org/apache/lucene/search/similarities/BooleanSimilarity.java
+++ b/lucene/core/src/java/org/apache/lucene/search/similarities/BooleanSimilarity.java
@@ -71,6 +71,11 @@ public class BooleanSimilarity extends Similarity {
}
@Override
+ public float maxScore(float maxFreq) {
+ return boost;
+ }
+
+ @Override
public Explanation explain(int doc, Explanation freq) throws IOException {
Explanation queryBoostExpl = Explanation.match(boost, "boost");
return Explanation.match(
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/similarities/DFISimilarity.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/similarities/DFISimilarity.java b/lucene/core/src/java/org/apache/lucene/search/similarities/DFISimilarity.java
index 8b7e43a..ca0f4aa 100644
--- a/lucene/core/src/java/org/apache/lucene/search/similarities/DFISimilarity.java
+++ b/lucene/core/src/java/org/apache/lucene/search/similarities/DFISimilarity.java
@@ -62,6 +62,12 @@ public class DFISimilarity extends SimilarityBase {
return stats.getBoost() * log2(measure + 1);
}
+ @Override
+ protected double maxScore(BasicStats stats, double maxFreq) {
+ // TODO: can we compute a better upper bound on the produced scores
+ return Double.POSITIVE_INFINITY;
+ }
+
/**
* Returns the measure of independence
*/
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/similarities/DFRSimilarity.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/similarities/DFRSimilarity.java b/lucene/core/src/java/org/apache/lucene/search/similarities/DFRSimilarity.java
index d793d94..788f30a 100644
--- a/lucene/core/src/java/org/apache/lucene/search/similarities/DFRSimilarity.java
+++ b/lucene/core/src/java/org/apache/lucene/search/similarities/DFRSimilarity.java
@@ -111,7 +111,13 @@ public class DFRSimilarity extends SimilarityBase {
double aeTimes1pTfn = afterEffect.scoreTimes1pTfn(stats);
return stats.getBoost() * basicModel.score(stats, tfn, aeTimes1pTfn);
}
-
+
+ @Override
+ protected double maxScore(BasicStats stats, double maxFreq) {
+ // TODO: can we compute a better upper bound on the produced scores
+ return Double.POSITIVE_INFINITY;
+ }
+
@Override
protected void explain(List<Explanation> subs,
BasicStats stats, int doc, double freq, double docLen) {
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/similarities/IBSimilarity.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/similarities/IBSimilarity.java b/lucene/core/src/java/org/apache/lucene/search/similarities/IBSimilarity.java
index 875cbe4..a71614c 100644
--- a/lucene/core/src/java/org/apache/lucene/search/similarities/IBSimilarity.java
+++ b/lucene/core/src/java/org/apache/lucene/search/similarities/IBSimilarity.java
@@ -104,6 +104,12 @@ public class IBSimilarity extends SimilarityBase {
}
@Override
+ protected double maxScore(BasicStats stats, double maxFreq) {
+ // TODO: can we compute a better upper bound on the produced scores
+ return Double.POSITIVE_INFINITY;
+ }
+
+ @Override
protected void explain(
List<Explanation> subs, BasicStats stats, int doc, double freq, double docLen) {
if (stats.getBoost() != 1.0d) {
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/similarities/LMDirichletSimilarity.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/similarities/LMDirichletSimilarity.java b/lucene/core/src/java/org/apache/lucene/search/similarities/LMDirichletSimilarity.java
index a901bad..2a4354e 100644
--- a/lucene/core/src/java/org/apache/lucene/search/similarities/LMDirichletSimilarity.java
+++ b/lucene/core/src/java/org/apache/lucene/search/similarities/LMDirichletSimilarity.java
@@ -75,7 +75,13 @@ public class LMDirichletSimilarity extends LMSimilarity {
Math.log(mu / (docLen + mu)));
return score > 0.0d ? score : 0.0d;
}
-
+
+ @Override
+ protected double maxScore(BasicStats stats, double maxFreq) {
+ // TODO: can we compute a better upper bound on the produced scores
+ return Double.POSITIVE_INFINITY;
+ }
+
@Override
protected void explain(List<Explanation> subs, BasicStats stats, int doc,
double freq, double docLen) {
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/similarities/LMJelinekMercerSimilarity.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/similarities/LMJelinekMercerSimilarity.java b/lucene/core/src/java/org/apache/lucene/search/similarities/LMJelinekMercerSimilarity.java
index 2799e3a..fa0ebcf 100644
--- a/lucene/core/src/java/org/apache/lucene/search/similarities/LMJelinekMercerSimilarity.java
+++ b/lucene/core/src/java/org/apache/lucene/search/similarities/LMJelinekMercerSimilarity.java
@@ -65,7 +65,13 @@ public class LMJelinekMercerSimilarity extends LMSimilarity {
((1 - lambda) * freq / docLen) /
(lambda * ((LMStats)stats).getCollectionProbability()));
}
-
+
+ @Override
+ protected double maxScore(BasicStats stats, double maxFreq) {
+ // TODO: can we compute a better upper bound on the produced scores
+ return Double.POSITIVE_INFINITY;
+ }
+
@Override
protected void explain(List<Explanation> subs, BasicStats stats, int doc,
double freq, double docLen) {
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/similarities/MultiSimilarity.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/similarities/MultiSimilarity.java b/lucene/core/src/java/org/apache/lucene/search/similarities/MultiSimilarity.java
index 15b472f..cbd61dd 100644
--- a/lucene/core/src/java/org/apache/lucene/search/similarities/MultiSimilarity.java
+++ b/lucene/core/src/java/org/apache/lucene/search/similarities/MultiSimilarity.java
@@ -83,6 +83,15 @@ public class MultiSimilarity extends Similarity {
}
@Override
+ public float maxScore(float freq) {
+ float sumMaxScore = 0;
+ for (SimScorer subScorer : subScorers) {
+ sumMaxScore += subScorer.maxScore(freq);
+ }
+ return sumMaxScore;
+ }
+
+ @Override
public Explanation explain(int doc, Explanation freq) throws IOException {
List<Explanation> subs = new ArrayList<>();
for (SimScorer subScorer : subScorers) {
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/similarities/Similarity.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/similarities/Similarity.java b/lucene/core/src/java/org/apache/lucene/search/similarities/Similarity.java
index 23f5b62..30895eb 100644
--- a/lucene/core/src/java/org/apache/lucene/search/similarities/Similarity.java
+++ b/lucene/core/src/java/org/apache/lucene/search/similarities/Similarity.java
@@ -159,6 +159,13 @@ public abstract class Similarity {
public abstract float score(int doc, float freq) throws IOException;
/**
+ * Return the maximum score that this scorer may produce for freqs in {@code ]0, maxFreq]}.
+ * {@code Float.POSITIVE_INFINITY} is a fine return value if scores are not bounded.
+ * @param maxFreq the maximum frequency
+ */
+ public abstract float maxScore(float maxFreq);
+
+ /**
* Explain the score for a single document
* @param doc document id within the inverted index segment
* @param freq Explanation of how the sloppy term frequency was computed
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/similarities/SimilarityBase.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/similarities/SimilarityBase.java b/lucene/core/src/java/org/apache/lucene/search/similarities/SimilarityBase.java
index 380673a..99a2e36 100644
--- a/lucene/core/src/java/org/apache/lucene/search/similarities/SimilarityBase.java
+++ b/lucene/core/src/java/org/apache/lucene/search/similarities/SimilarityBase.java
@@ -120,7 +120,14 @@ public abstract class SimilarityBase extends Similarity {
* @return the score.
*/
protected abstract double score(BasicStats stats, double freq, double docLen);
-
+
+ /**
+ * Return the maximum value that may be returned by {@link #score(BasicStats, double, double)}
+ * for the given stats.
+ * @see org.apache.lucene.search.similarities.Similarity.SimScorer#maxScore(float)
+ */
+ protected abstract double maxScore(BasicStats stats, double maxFreq);
+
/**
* Subclasses should implement this method to explain the score. {@code expl}
* already contains the score, the name of the class and the doc id, as well
@@ -250,6 +257,11 @@ public abstract class SimilarityBase extends Similarity {
}
@Override
+ public float maxScore(float maxFreq) {
+ return (float) SimilarityBase.this.maxScore(stats, maxFreq);
+ }
+
+ @Override
public Explanation explain(int doc, Explanation freq) throws IOException {
return SimilarityBase.this.explain(stats, doc, freq, getLengthValue(doc));
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/similarities/TFIDFSimilarity.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/similarities/TFIDFSimilarity.java b/lucene/core/src/java/org/apache/lucene/search/similarities/TFIDFSimilarity.java
index 87b8b52..51e6278 100644
--- a/lucene/core/src/java/org/apache/lucene/search/similarities/TFIDFSimilarity.java
+++ b/lucene/core/src/java/org/apache/lucene/search/similarities/TFIDFSimilarity.java
@@ -561,6 +561,20 @@ public abstract class TFIDFSimilarity extends Similarity {
}
@Override
+ public float maxScore(float maxFreq) {
+ final float raw = tf(maxFreq) * weightValue;
+ if (norms == null) {
+ return raw;
+ } else {
+ float maxNormValue = Float.NEGATIVE_INFINITY;
+ for (float norm : normTable) {
+ maxNormValue = Math.max(maxNormValue, norm);
+ }
+ return raw * maxNormValue;
+ }
+ }
+
+ @Override
public Explanation explain(int doc, Explanation freq) throws IOException {
return explainScore(doc, freq, stats, norms, normTable);
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/spans/FieldMaskingSpanQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/spans/FieldMaskingSpanQuery.java b/lucene/core/src/java/org/apache/lucene/search/spans/FieldMaskingSpanQuery.java
index 7759683..4a4c4fb 100644
--- a/lucene/core/src/java/org/apache/lucene/search/spans/FieldMaskingSpanQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/spans/FieldMaskingSpanQuery.java
@@ -20,6 +20,7 @@ package org.apache.lucene.search.spans;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
+import org.apache.lucene.search.ScoreMode;
import java.io.IOException;
import java.util.Objects;
@@ -89,8 +90,8 @@ public final class FieldMaskingSpanQuery extends SpanQuery {
// ...this is done to be more consistent with things like SpanFirstQuery
@Override
- public SpanWeight createWeight(IndexSearcher searcher, boolean needsScores, float boost) throws IOException {
- return maskedQuery.createWeight(searcher, needsScores, boost);
+ public SpanWeight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
+ return maskedQuery.createWeight(searcher, scoreMode, boost);
}
@Override
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/spans/SpanBoostQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/spans/SpanBoostQuery.java b/lucene/core/src/java/org/apache/lucene/search/spans/SpanBoostQuery.java
index 0ce3b0a..9556959 100644
--- a/lucene/core/src/java/org/apache/lucene/search/spans/SpanBoostQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/spans/SpanBoostQuery.java
@@ -24,6 +24,7 @@ import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.BoostQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
+import org.apache.lucene.search.ScoreMode;
/**
* Counterpart of {@link BoostQuery} for spans.
@@ -108,8 +109,8 @@ public final class SpanBoostQuery extends SpanQuery {
}
@Override
- public SpanWeight createWeight(IndexSearcher searcher, boolean needsScores, float boost) throws IOException {
- return query.createWeight(searcher, needsScores, SpanBoostQuery.this.boost * boost);
+ public SpanWeight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
+ return query.createWeight(searcher, scoreMode, SpanBoostQuery.this.boost * boost);
}
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/spans/SpanContainingQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/spans/SpanContainingQuery.java b/lucene/core/src/java/org/apache/lucene/search/spans/SpanContainingQuery.java
index 552d146..0d62f74 100644
--- a/lucene/core/src/java/org/apache/lucene/search/spans/SpanContainingQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/spans/SpanContainingQuery.java
@@ -25,6 +25,7 @@ import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermContext;
import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.ScoreMode;
/** Keep matches that contain another SpanScorer. */
public final class SpanContainingQuery extends SpanContainQuery {
@@ -43,10 +44,10 @@ public final class SpanContainingQuery extends SpanContainQuery {
}
@Override
- public SpanWeight createWeight(IndexSearcher searcher, boolean needsScores, float boost) throws IOException {
- SpanWeight bigWeight = big.createWeight(searcher, false, boost);
- SpanWeight littleWeight = little.createWeight(searcher, false, boost);
- return new SpanContainingWeight(searcher, needsScores ? getTermContexts(bigWeight, littleWeight) : null,
+ public SpanWeight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
+ SpanWeight bigWeight = big.createWeight(searcher, ScoreMode.COMPLETE_NO_SCORES, boost);
+ SpanWeight littleWeight = little.createWeight(searcher, ScoreMode.COMPLETE_NO_SCORES, boost);
+ return new SpanContainingWeight(searcher, scoreMode.needsScores() ? getTermContexts(bigWeight, littleWeight) : null,
bigWeight, littleWeight, boost);
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/spans/SpanMultiTermQueryWrapper.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/spans/SpanMultiTermQueryWrapper.java b/lucene/core/src/java/org/apache/lucene/search/spans/SpanMultiTermQueryWrapper.java
index 9c844d1..ee3f5de 100644
--- a/lucene/core/src/java/org/apache/lucene/search/spans/SpanMultiTermQueryWrapper.java
+++ b/lucene/core/src/java/org/apache/lucene/search/spans/SpanMultiTermQueryWrapper.java
@@ -29,6 +29,7 @@ import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.MultiTermQuery;
import org.apache.lucene.search.Query;
+import org.apache.lucene.search.ScoreMode;
import org.apache.lucene.search.ScoringRewrite;
import org.apache.lucene.search.TopTermsRewrite;
@@ -95,7 +96,7 @@ public class SpanMultiTermQueryWrapper<Q extends MultiTermQuery> extends SpanQue
}
@Override
- public SpanWeight createWeight(IndexSearcher searcher, boolean needsScores, float boost) throws IOException {
+ public SpanWeight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
throw new IllegalArgumentException("Rewrite first!");
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/spans/SpanNearQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/spans/SpanNearQuery.java b/lucene/core/src/java/org/apache/lucene/search/spans/SpanNearQuery.java
index 720d943..24a047f 100644
--- a/lucene/core/src/java/org/apache/lucene/search/spans/SpanNearQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/spans/SpanNearQuery.java
@@ -33,6 +33,7 @@ import org.apache.lucene.index.TermContext;
import org.apache.lucene.index.Terms;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
+import org.apache.lucene.search.ScoreMode;
import org.apache.lucene.search.Weight;
/** Matches spans which are near one another. One can specify <i>slop</i>, the
@@ -177,12 +178,12 @@ public class SpanNearQuery extends SpanQuery implements Cloneable {
}
@Override
- public SpanWeight createWeight(IndexSearcher searcher, boolean needsScores, float boost) throws IOException {
+ public SpanWeight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
List<SpanWeight> subWeights = new ArrayList<>();
for (SpanQuery q : clauses) {
- subWeights.add(q.createWeight(searcher, false, boost));
+ subWeights.add(q.createWeight(searcher, ScoreMode.COMPLETE_NO_SCORES, boost));
}
- return new SpanNearWeight(subWeights, searcher, needsScores ? getTermContexts(subWeights) : null, boost);
+ return new SpanNearWeight(subWeights, searcher, scoreMode.needsScores() ? getTermContexts(subWeights) : null, boost);
}
public class SpanNearWeight extends SpanWeight {
@@ -306,7 +307,7 @@ public class SpanNearQuery extends SpanQuery implements Cloneable {
}
@Override
- public SpanWeight createWeight(IndexSearcher searcher, boolean needsScores, float boost) throws IOException {
+ public SpanWeight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
return new SpanGapWeight(searcher, boost);
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/spans/SpanNotQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/spans/SpanNotQuery.java b/lucene/core/src/java/org/apache/lucene/search/spans/SpanNotQuery.java
index d8c7862..5b97f8d 100644
--- a/lucene/core/src/java/org/apache/lucene/search/spans/SpanNotQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/spans/SpanNotQuery.java
@@ -29,6 +29,7 @@ import org.apache.lucene.index.TermContext;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
+import org.apache.lucene.search.ScoreMode;
import org.apache.lucene.search.TwoPhaseIterator;
/** Removes matches which overlap with another SpanQuery or which are
@@ -97,10 +98,10 @@ public final class SpanNotQuery extends SpanQuery {
@Override
- public SpanWeight createWeight(IndexSearcher searcher, boolean needsScores, float boost) throws IOException {
- SpanWeight includeWeight = include.createWeight(searcher, false, boost);
- SpanWeight excludeWeight = exclude.createWeight(searcher, false, boost);
- return new SpanNotWeight(searcher, needsScores ? getTermContexts(includeWeight, excludeWeight) : null,
+ public SpanWeight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
+ SpanWeight includeWeight = include.createWeight(searcher, ScoreMode.COMPLETE_NO_SCORES, boost);
+ SpanWeight excludeWeight = exclude.createWeight(searcher, ScoreMode.COMPLETE_NO_SCORES, boost);
+ return new SpanNotWeight(searcher, scoreMode.needsScores() ? getTermContexts(includeWeight, excludeWeight) : null,
includeWeight, excludeWeight, boost);
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/spans/SpanOrQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/spans/SpanOrQuery.java b/lucene/core/src/java/org/apache/lucene/search/spans/SpanOrQuery.java
index 59dbac7..2e15c92 100644
--- a/lucene/core/src/java/org/apache/lucene/search/spans/SpanOrQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/spans/SpanOrQuery.java
@@ -33,6 +33,7 @@ import org.apache.lucene.search.DisiWrapper;
import org.apache.lucene.search.DisjunctionDISIApproximation;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
+import org.apache.lucene.search.ScoreMode;
import org.apache.lucene.search.TwoPhaseIterator;
import org.apache.lucene.search.Weight;
@@ -115,12 +116,12 @@ public final class SpanOrQuery extends SpanQuery {
}
@Override
- public SpanWeight createWeight(IndexSearcher searcher, boolean needsScores, float boost) throws IOException {
+ public SpanWeight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
List<SpanWeight> subWeights = new ArrayList<>(clauses.size());
for (SpanQuery q : clauses) {
- subWeights.add(q.createWeight(searcher, false, boost));
+ subWeights.add(q.createWeight(searcher, ScoreMode.COMPLETE_NO_SCORES, boost));
}
- return new SpanOrWeight(searcher, needsScores ? getTermContexts(subWeights) : null, subWeights, boost);
+ return new SpanOrWeight(searcher, scoreMode.needsScores() ? getTermContexts(subWeights) : null, subWeights, boost);
}
public class SpanOrWeight extends SpanWeight {
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/spans/SpanPositionCheckQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/spans/SpanPositionCheckQuery.java b/lucene/core/src/java/org/apache/lucene/search/spans/SpanPositionCheckQuery.java
index dddf766..f9b7697 100644
--- a/lucene/core/src/java/org/apache/lucene/search/spans/SpanPositionCheckQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/spans/SpanPositionCheckQuery.java
@@ -28,6 +28,7 @@ import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermContext;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
+import org.apache.lucene.search.ScoreMode;
import org.apache.lucene.search.spans.FilterSpans.AcceptStatus;
@@ -67,9 +68,9 @@ public abstract class SpanPositionCheckQuery extends SpanQuery implements Clonea
protected abstract AcceptStatus acceptPosition(Spans spans) throws IOException;
@Override
- public SpanWeight createWeight(IndexSearcher searcher, boolean needsScores, float boost) throws IOException {
- SpanWeight matchWeight = match.createWeight(searcher, false, boost);
- return new SpanPositionCheckWeight(matchWeight, searcher, needsScores ? getTermContexts(matchWeight) : null, boost);
+ public SpanWeight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
+ SpanWeight matchWeight = match.createWeight(searcher, ScoreMode.COMPLETE_NO_SCORES, boost);
+ return new SpanPositionCheckWeight(matchWeight, searcher, scoreMode.needsScores() ? getTermContexts(matchWeight) : null, boost);
}
public class SpanPositionCheckWeight extends SpanWeight {
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/spans/SpanQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/spans/SpanQuery.java b/lucene/core/src/java/org/apache/lucene/search/spans/SpanQuery.java
index 965f80e..607a375 100644
--- a/lucene/core/src/java/org/apache/lucene/search/spans/SpanQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/spans/SpanQuery.java
@@ -26,6 +26,7 @@ import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermContext;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
+import org.apache.lucene.search.ScoreMode;
/** Base class for span-based queries. */
public abstract class SpanQuery extends Query {
@@ -36,7 +37,7 @@ public abstract class SpanQuery extends Query {
public abstract String getField();
@Override
- public abstract SpanWeight createWeight(IndexSearcher searcher, boolean needsScores, float boost) throws IOException;
+ public abstract SpanWeight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException;
/**
* Build a map of terms to termcontexts, for use in constructing SpanWeights
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/spans/SpanScorer.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/spans/SpanScorer.java b/lucene/core/src/java/org/apache/lucene/search/spans/SpanScorer.java
index 699fa1b..57a68e4 100644
--- a/lucene/core/src/java/org/apache/lucene/search/spans/SpanScorer.java
+++ b/lucene/core/src/java/org/apache/lucene/search/spans/SpanScorer.java
@@ -134,6 +134,11 @@ public class SpanScorer extends Scorer {
return scoreCurrentDoc();
}
+ @Override
+ public float maxScore() {
+ return Float.POSITIVE_INFINITY;
+ }
+
/** Returns the intermediate "sloppy freq" adjusted for edit distance
* @lucene.internal */
final float sloppyFreq() throws IOException {
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/spans/SpanTermQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/spans/SpanTermQuery.java b/lucene/core/src/java/org/apache/lucene/search/spans/SpanTermQuery.java
index 4a2e6bc..9eea3aa 100644
--- a/lucene/core/src/java/org/apache/lucene/search/spans/SpanTermQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/spans/SpanTermQuery.java
@@ -33,6 +33,7 @@ import org.apache.lucene.index.TermState;
import org.apache.lucene.index.Terms;
import org.apache.lucene.index.TermsEnum;
import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.ScoreMode;
/** Matches spans containing a term.
* This should not be used for terms that are indexed at position Integer.MAX_VALUE.
@@ -64,7 +65,7 @@ public class SpanTermQuery extends SpanQuery {
public String getField() { return term.field(); }
@Override
- public SpanWeight createWeight(IndexSearcher searcher, boolean needsScores, float boost) throws IOException {
+ public SpanWeight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
final TermContext context;
final IndexReaderContext topContext = searcher.getTopReaderContext();
if (termContext == null || termContext.wasBuiltFor(topContext) == false) {
@@ -73,7 +74,7 @@ public class SpanTermQuery extends SpanQuery {
else {
context = termContext;
}
- return new SpanTermWeight(context, searcher, needsScores ? Collections.singletonMap(term, context) : null, boost);
+ return new SpanTermWeight(context, searcher, scoreMode.needsScores() ? Collections.singletonMap(term, context) : null, boost);
}
public class SpanTermWeight extends SpanWeight {
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/java/org/apache/lucene/search/spans/SpanWithinQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/spans/SpanWithinQuery.java b/lucene/core/src/java/org/apache/lucene/search/spans/SpanWithinQuery.java
index 0a8f4e4..9c618dd 100644
--- a/lucene/core/src/java/org/apache/lucene/search/spans/SpanWithinQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/spans/SpanWithinQuery.java
@@ -25,6 +25,7 @@ import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermContext;
import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.ScoreMode;
/** Keep matches that are contained within another Spans. */
public final class SpanWithinQuery extends SpanContainQuery {
@@ -44,10 +45,10 @@ public final class SpanWithinQuery extends SpanContainQuery {
}
@Override
- public SpanWeight createWeight(IndexSearcher searcher, boolean needsScores, float boost) throws IOException {
- SpanWeight bigWeight = big.createWeight(searcher, false, boost);
- SpanWeight littleWeight = little.createWeight(searcher, false, boost);
- return new SpanWithinWeight(searcher, needsScores ? getTermContexts(bigWeight, littleWeight) : null,
+ public SpanWeight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
+ SpanWeight bigWeight = big.createWeight(searcher, ScoreMode.COMPLETE_NO_SCORES, boost);
+ SpanWeight littleWeight = little.createWeight(searcher, ScoreMode.COMPLETE_NO_SCORES, boost);
+ return new SpanWithinWeight(searcher, scoreMode.needsScores() ? getTermContexts(bigWeight, littleWeight) : null,
bigWeight, littleWeight, boost);
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/index/TestMaxTermFrequency.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestMaxTermFrequency.java b/lucene/core/src/test/org/apache/lucene/index/TestMaxTermFrequency.java
index 9b755c9..f391c5a 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestMaxTermFrequency.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestMaxTermFrequency.java
@@ -123,6 +123,10 @@ public class TestMaxTermFrequency extends LuceneTestCase {
return 0;
}
+ @Override
+ public float maxScore(float maxFreq) {
+ return 0;
+ }
};
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/index/TestOmitTf.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestOmitTf.java b/lucene/core/src/test/org/apache/lucene/index/TestOmitTf.java
index 2c179c5..a995e16 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestOmitTf.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestOmitTf.java
@@ -31,6 +31,7 @@ import org.apache.lucene.search.CollectionStatistics;
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.PhraseQuery;
+import org.apache.lucene.search.ScoreMode;
import org.apache.lucene.search.Scorer;
import org.apache.lucene.search.SimpleCollector;
import org.apache.lucene.search.TermQuery;
@@ -310,8 +311,8 @@ public class TestOmitTf extends LuceneTestCase {
new CountingHitCollector() {
private Scorer scorer;
@Override
- public boolean needsScores() {
- return true;
+ public ScoreMode scoreMode() {
+ return ScoreMode.COMPLETE;
}
@Override
public final void setScorer(Scorer scorer) {
@@ -332,8 +333,8 @@ public class TestOmitTf extends LuceneTestCase {
new CountingHitCollector() {
private Scorer scorer;
@Override
- public boolean needsScores() {
- return true;
+ public ScoreMode scoreMode() {
+ return ScoreMode.COMPLETE;
}
@Override
public final void setScorer(Scorer scorer) {
@@ -357,8 +358,8 @@ public class TestOmitTf extends LuceneTestCase {
new CountingHitCollector() {
private Scorer scorer;
@Override
- public boolean needsScores() {
- return true;
+ public ScoreMode scoreMode() {
+ return ScoreMode.COMPLETE;
}
@Override
public final void setScorer(Scorer scorer) {
@@ -380,8 +381,8 @@ public class TestOmitTf extends LuceneTestCase {
new CountingHitCollector() {
private Scorer scorer;
@Override
- public boolean needsScores() {
- return true;
+ public ScoreMode scoreMode() {
+ return ScoreMode.COMPLETE;
}
@Override
public final void setScorer(Scorer scorer) {
@@ -438,8 +439,8 @@ public class TestOmitTf extends LuceneTestCase {
}
@Override
- public boolean needsScores() {
- return false;
+ public ScoreMode scoreMode() {
+ return ScoreMode.COMPLETE_NO_SCORES;
}
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/search/JustCompileSearch.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/JustCompileSearch.java b/lucene/core/src/test/org/apache/lucene/search/JustCompileSearch.java
index 18dae47..0523e2c 100644
--- a/lucene/core/src/test/org/apache/lucene/search/JustCompileSearch.java
+++ b/lucene/core/src/test/org/apache/lucene/search/JustCompileSearch.java
@@ -55,7 +55,7 @@ final class JustCompileSearch {
}
@Override
- public boolean needsScores() {
+ public ScoreMode scoreMode() {
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
}
}
@@ -176,6 +176,11 @@ final class JustCompileSearch {
}
@Override
+ public float maxScore() {
+ throw new UnsupportedOperationException(UNSUPPORTED_MSG);
+ }
+
+ @Override
public int docID() {
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
}
@@ -231,7 +236,7 @@ final class JustCompileSearch {
}
@Override
- public boolean needsScores() {
+ public ScoreMode scoreMode() {
throw new UnsupportedOperationException( UNSUPPORTED_MSG );
}
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/search/MultiCollectorTest.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/MultiCollectorTest.java b/lucene/core/src/test/org/apache/lucene/search/MultiCollectorTest.java
index de97954..d4e1e24 100644
--- a/lucene/core/src/test/org/apache/lucene/search/MultiCollectorTest.java
+++ b/lucene/core/src/test/org/apache/lucene/search/MultiCollectorTest.java
@@ -51,8 +51,8 @@ public class MultiCollectorTest extends LuceneTestCase {
}
@Override
- public boolean needsScores() {
- return true;
+ public ScoreMode scoreMode() {
+ return ScoreMode.COMPLETE;
}
}
@@ -102,7 +102,7 @@ public class MultiCollectorTest extends LuceneTestCase {
}
- private static Collector collector(boolean needsScores, Class<?> expectedScorer) {
+ private static Collector collector(ScoreMode scoreMode, Class<?> expectedScorer) {
return new Collector() {
@Override
@@ -121,8 +121,8 @@ public class MultiCollectorTest extends LuceneTestCase {
}
@Override
- public boolean needsScores() {
- return needsScores;
+ public ScoreMode scoreMode() {
+ return scoreMode;
}
};
@@ -139,22 +139,22 @@ public class MultiCollectorTest extends LuceneTestCase {
final LeafReaderContext ctx = reader.leaves().get(0);
expectThrows(AssertionError.class, () -> {
- collector(false, ScoreCachingWrappingScorer.class).getLeafCollector(ctx).setScorer(new FakeScorer());
+ collector(ScoreMode.COMPLETE_NO_SCORES, ScoreCachingWrappingScorer.class).getLeafCollector(ctx).setScorer(new FakeScorer());
});
// no collector needs scores => no caching
- Collector c1 = collector(false, FakeScorer.class);
- Collector c2 = collector(false, FakeScorer.class);
+ Collector c1 = collector(ScoreMode.COMPLETE_NO_SCORES, FakeScorer.class);
+ Collector c2 = collector(ScoreMode.COMPLETE_NO_SCORES, FakeScorer.class);
MultiCollector.wrap(c1, c2).getLeafCollector(ctx).setScorer(new FakeScorer());
// only one collector needs scores => no caching
- c1 = collector(true, FakeScorer.class);
- c2 = collector(false, FakeScorer.class);
+ c1 = collector(ScoreMode.COMPLETE, FakeScorer.class);
+ c2 = collector(ScoreMode.COMPLETE_NO_SCORES, FakeScorer.class);
MultiCollector.wrap(c1, c2).getLeafCollector(ctx).setScorer(new FakeScorer());
// several collectors need scores => caching
- c1 = collector(true, ScoreCachingWrappingScorer.class);
- c2 = collector(true, ScoreCachingWrappingScorer.class);
+ c1 = collector(ScoreMode.COMPLETE, ScoreCachingWrappingScorer.class);
+ c2 = collector(ScoreMode.COMPLETE, ScoreCachingWrappingScorer.class);
MultiCollector.wrap(c1, c2).getLeafCollector(ctx).setScorer(new FakeScorer());
reader.close();