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:39 UTC

[45/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/test/org/apache/lucene/search/TestBoolean2ScorerSupplier.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestBoolean2ScorerSupplier.java b/lucene/core/src/test/org/apache/lucene/search/TestBoolean2ScorerSupplier.java
index 74e9dd5..fa835ab 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestBoolean2ScorerSupplier.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestBoolean2ScorerSupplier.java
@@ -51,6 +51,10 @@ public class TestBoolean2ScorerSupplier extends LuceneTestCase {
     }
 
     @Override
+    public float maxScore() {
+      return 1;
+    }
+
     public DocIdSetIterator iterator() {
       return it;
     }
@@ -104,13 +108,13 @@ public class TestBoolean2ScorerSupplier extends LuceneTestCase {
     }
 
     subs.get(RandomPicks.randomFrom(random(), Arrays.asList(Occur.FILTER, Occur.MUST))).add(new FakeScorerSupplier(42));
-    assertEquals(42, new Boolean2ScorerSupplier(null, subs, random().nextBoolean(), 0).cost());
+    assertEquals(42, new Boolean2ScorerSupplier(null, subs, RandomPicks.randomFrom(random(), ScoreMode.values()), 0).cost());
 
     subs.get(RandomPicks.randomFrom(random(), Arrays.asList(Occur.FILTER, Occur.MUST))).add(new FakeScorerSupplier(12));
-    assertEquals(12, new Boolean2ScorerSupplier(null, subs, random().nextBoolean(), 0).cost());
+    assertEquals(12, new Boolean2ScorerSupplier(null, subs, RandomPicks.randomFrom(random(), ScoreMode.values()), 0).cost());
 
     subs.get(RandomPicks.randomFrom(random(), Arrays.asList(Occur.FILTER, Occur.MUST))).add(new FakeScorerSupplier(20));
-    assertEquals(12, new Boolean2ScorerSupplier(null, subs, random().nextBoolean(), 0).cost());
+    assertEquals(12, new Boolean2ScorerSupplier(null, subs, RandomPicks.randomFrom(random(), ScoreMode.values()), 0).cost());
   }
 
   public void testDisjunctionCost() throws IOException {
@@ -120,17 +124,17 @@ public class TestBoolean2ScorerSupplier extends LuceneTestCase {
     }
 
     subs.get(Occur.SHOULD).add(new FakeScorerSupplier(42));
-    ScorerSupplier s = new Boolean2ScorerSupplier(null, subs, random().nextBoolean(), 0);
+    ScorerSupplier s = new Boolean2ScorerSupplier(null, subs, RandomPicks.randomFrom(random(), ScoreMode.values()), 0);
     assertEquals(42, s.cost());
     assertEquals(42, s.get(random().nextInt(100)).iterator().cost());
 
     subs.get(Occur.SHOULD).add(new FakeScorerSupplier(12));
-    s = new Boolean2ScorerSupplier(null, subs, random().nextBoolean(), 0);
+    s = new Boolean2ScorerSupplier(null, subs, RandomPicks.randomFrom(random(), ScoreMode.values()), 0);
     assertEquals(42 + 12, s.cost());
     assertEquals(42 + 12, s.get(random().nextInt(100)).iterator().cost());
 
     subs.get(Occur.SHOULD).add(new FakeScorerSupplier(20));
-    s = new Boolean2ScorerSupplier(null, subs, random().nextBoolean(), 0);
+    s = new Boolean2ScorerSupplier(null, subs, RandomPicks.randomFrom(random(), ScoreMode.values()), 0);
     assertEquals(42 + 12 + 20, s.cost());
     assertEquals(42 + 12 + 20, s.get(random().nextInt(100)).iterator().cost());
   }
@@ -143,26 +147,26 @@ public class TestBoolean2ScorerSupplier extends LuceneTestCase {
 
     subs.get(Occur.SHOULD).add(new FakeScorerSupplier(42));
     subs.get(Occur.SHOULD).add(new FakeScorerSupplier(12));
-    ScorerSupplier s = new Boolean2ScorerSupplier(null, subs, random().nextBoolean(), 1);
+    ScorerSupplier s = new Boolean2ScorerSupplier(null, subs, RandomPicks.randomFrom(random(), ScoreMode.values()), 1);
     assertEquals(42 + 12, s.cost());
     assertEquals(42 + 12, s.get(random().nextInt(100)).iterator().cost());
 
     subs.get(Occur.SHOULD).add(new FakeScorerSupplier(20));
-    s = new Boolean2ScorerSupplier(null, subs, random().nextBoolean(), 1);
+    s = new Boolean2ScorerSupplier(null, subs, RandomPicks.randomFrom(random(), ScoreMode.values()), 1);
     assertEquals(42 + 12 + 20, s.cost());
     assertEquals(42 + 12 + 20, s.get(random().nextInt(100)).iterator().cost());
-    s = new Boolean2ScorerSupplier(null, subs, random().nextBoolean(), 2);
+    s = new Boolean2ScorerSupplier(null, subs, RandomPicks.randomFrom(random(), ScoreMode.values()), 2);
     assertEquals(12 + 20, s.cost());
     assertEquals(12 + 20, s.get(random().nextInt(100)).iterator().cost());
 
     subs.get(Occur.SHOULD).add(new FakeScorerSupplier(30));
-    s = new Boolean2ScorerSupplier(null, subs, random().nextBoolean(), 1);
+    s = new Boolean2ScorerSupplier(null, subs, RandomPicks.randomFrom(random(), ScoreMode.values()), 1);
     assertEquals(42 + 12 + 20 + 30, s.cost());
     assertEquals(42 + 12 + 20 + 30, s.get(random().nextInt(100)).iterator().cost());
-    s = new Boolean2ScorerSupplier(null, subs, random().nextBoolean(), 2);
+    s = new Boolean2ScorerSupplier(null, subs, RandomPicks.randomFrom(random(), ScoreMode.values()), 2);
     assertEquals(12 + 20 + 30, s.cost());
     assertEquals(12 + 20 + 30, s.get(random().nextInt(100)).iterator().cost());
-    s = new Boolean2ScorerSupplier(null, subs, random().nextBoolean(), 3);
+    s = new Boolean2ScorerSupplier(null, subs, RandomPicks.randomFrom(random(), ScoreMode.values()), 3);
     assertEquals(12 + 20, s.cost());
     assertEquals(12 + 20, s.get(random().nextInt(100)).iterator().cost());
   }
@@ -186,8 +190,8 @@ public class TestBoolean2ScorerSupplier extends LuceneTestCase {
           numRequired++;
         }
       }
-      boolean needsScores = random().nextBoolean();
-      if (needsScores == false && numRequired > 0) {
+      ScoreMode scoreMode = RandomPicks.randomFrom(random(), ScoreMode.values());
+      if (scoreMode.needsScores() == false && numRequired > 0) {
         numClauses -= numShoulds;
         numShoulds = 0;
         subs.get(Occur.SHOULD).clear();
@@ -198,7 +202,7 @@ public class TestBoolean2ScorerSupplier extends LuceneTestCase {
       }
       int minShouldMatch = numShoulds == 0 ? 0 : TestUtil.nextInt(random(), 0, numShoulds - 1);
       Boolean2ScorerSupplier supplier = new Boolean2ScorerSupplier(null,
-          subs, needsScores, minShouldMatch);
+          subs, scoreMode, minShouldMatch);
       long cost1 = supplier.cost();
       long cost2 = supplier.get(Long.MAX_VALUE).iterator().cost();
       assertEquals("clauses=" + subs + ", minShouldMatch=" + minShouldMatch, cost1, cost2);
@@ -222,7 +226,7 @@ public class TestBoolean2ScorerSupplier extends LuceneTestCase {
     // If the clauses are less costly than the lead cost, the min cost is the new lead cost
     subs.get(RandomPicks.randomFrom(random(), Arrays.asList(Occur.FILTER, Occur.MUST))).add(new FakeScorerSupplier(42, 12));
     subs.get(RandomPicks.randomFrom(random(), Arrays.asList(Occur.FILTER, Occur.MUST))).add(new FakeScorerSupplier(12, 12));
-    new Boolean2ScorerSupplier(null, subs, random().nextBoolean(), 0).get(Long.MAX_VALUE); // triggers assertions as a side-effect
+    new Boolean2ScorerSupplier(null, subs, RandomPicks.randomFrom(random(), ScoreMode.values()), 0).get(Long.MAX_VALUE); // triggers assertions as a side-effect
 
     subs = new EnumMap<>(Occur.class);
     for (Occur occur : Occur.values()) {
@@ -232,7 +236,7 @@ public class TestBoolean2ScorerSupplier extends LuceneTestCase {
     // If the lead cost is less that the clauses' cost, then we don't modify it
     subs.get(RandomPicks.randomFrom(random(), Arrays.asList(Occur.FILTER, Occur.MUST))).add(new FakeScorerSupplier(42, 7));
     subs.get(RandomPicks.randomFrom(random(), Arrays.asList(Occur.FILTER, Occur.MUST))).add(new FakeScorerSupplier(12, 7));
-    new Boolean2ScorerSupplier(null, subs, random().nextBoolean(), 0).get(7); // triggers assertions as a side-effect
+    new Boolean2ScorerSupplier(null, subs, RandomPicks.randomFrom(random(), ScoreMode.values()), 0).get(7); // triggers assertions as a side-effect
   }
 
   public void testDisjunctionLeadCost() throws IOException {
@@ -242,12 +246,12 @@ public class TestBoolean2ScorerSupplier extends LuceneTestCase {
     }
     subs.get(Occur.SHOULD).add(new FakeScorerSupplier(42, 54));
     subs.get(Occur.SHOULD).add(new FakeScorerSupplier(12, 54));
-    new Boolean2ScorerSupplier(null, subs, random().nextBoolean(), 0).get(100); // triggers assertions as a side-effect
+    new Boolean2ScorerSupplier(null, subs, RandomPicks.randomFrom(random(), ScoreMode.values()), 0).get(100); // triggers assertions as a side-effect
 
     subs.get(Occur.SHOULD).clear();
     subs.get(Occur.SHOULD).add(new FakeScorerSupplier(42, 20));
     subs.get(Occur.SHOULD).add(new FakeScorerSupplier(12, 20));
-    new Boolean2ScorerSupplier(null, subs, random().nextBoolean(), 0).get(20); // triggers assertions as a side-effect
+    new Boolean2ScorerSupplier(null, subs, RandomPicks.randomFrom(random(), ScoreMode.values()), 0).get(20); // triggers assertions as a side-effect
   }
 
   public void testDisjunctionWithMinShouldMatchLeadCost() throws IOException {
@@ -261,7 +265,7 @@ public class TestBoolean2ScorerSupplier extends LuceneTestCase {
     subs.get(Occur.SHOULD).add(new FakeScorerSupplier(50, 42));
     subs.get(Occur.SHOULD).add(new FakeScorerSupplier(12, 42));
     subs.get(Occur.SHOULD).add(new FakeScorerSupplier(30, 42));
-    new Boolean2ScorerSupplier(null, subs, random().nextBoolean(), 2).get(100); // triggers assertions as a side-effect
+    new Boolean2ScorerSupplier(null, subs, RandomPicks.randomFrom(random(), ScoreMode.values()), 2).get(100); // triggers assertions as a side-effect
 
     subs = new EnumMap<>(Occur.class);
     for (Occur occur : Occur.values()) {
@@ -272,7 +276,7 @@ public class TestBoolean2ScorerSupplier extends LuceneTestCase {
     subs.get(Occur.SHOULD).add(new FakeScorerSupplier(42, 20));
     subs.get(Occur.SHOULD).add(new FakeScorerSupplier(12, 20));
     subs.get(Occur.SHOULD).add(new FakeScorerSupplier(30, 20));
-    new Boolean2ScorerSupplier(null, subs, random().nextBoolean(), 2).get(20); // triggers assertions as a side-effect
+    new Boolean2ScorerSupplier(null, subs, RandomPicks.randomFrom(random(), ScoreMode.values()), 2).get(20); // triggers assertions as a side-effect
 
     subs = new EnumMap<>(Occur.class);
     for (Occur occur : Occur.values()) {
@@ -283,7 +287,7 @@ public class TestBoolean2ScorerSupplier extends LuceneTestCase {
     subs.get(Occur.SHOULD).add(new FakeScorerSupplier(12, 62));
     subs.get(Occur.SHOULD).add(new FakeScorerSupplier(30, 62));
     subs.get(Occur.SHOULD).add(new FakeScorerSupplier(20, 62));
-    new Boolean2ScorerSupplier(null, subs, random().nextBoolean(), 2).get(100); // triggers assertions as a side-effect
+    new Boolean2ScorerSupplier(null, subs, RandomPicks.randomFrom(random(), ScoreMode.values()), 2).get(100); // triggers assertions as a side-effect
 
     subs = new EnumMap<>(Occur.class);
     for (Occur occur : Occur.values()) {
@@ -294,7 +298,7 @@ public class TestBoolean2ScorerSupplier extends LuceneTestCase {
     subs.get(Occur.SHOULD).add(new FakeScorerSupplier(12, 32));
     subs.get(Occur.SHOULD).add(new FakeScorerSupplier(30, 32));
     subs.get(Occur.SHOULD).add(new FakeScorerSupplier(20, 32));
-    new Boolean2ScorerSupplier(null, subs, random().nextBoolean(), 3).get(100); // triggers assertions as a side-effect
+    new Boolean2ScorerSupplier(null, subs, RandomPicks.randomFrom(random(), ScoreMode.values()), 3).get(100); // triggers assertions as a side-effect
   }
 
   public void testProhibitedLeadCost() throws IOException {
@@ -306,19 +310,19 @@ public class TestBoolean2ScorerSupplier extends LuceneTestCase {
     // The MUST_NOT clause is called with the same lead cost as the MUST clause
     subs.get(Occur.MUST).add(new FakeScorerSupplier(42, 42));
     subs.get(Occur.MUST_NOT).add(new FakeScorerSupplier(30, 42));
-    new Boolean2ScorerSupplier(null, subs, random().nextBoolean(), 0).get(100); // triggers assertions as a side-effect
+    new Boolean2ScorerSupplier(null, subs, RandomPicks.randomFrom(random(), ScoreMode.values()), 0).get(100); // triggers assertions as a side-effect
 
     subs.get(Occur.MUST).clear();
     subs.get(Occur.MUST_NOT).clear();
     subs.get(Occur.MUST).add(new FakeScorerSupplier(42, 42));
     subs.get(Occur.MUST_NOT).add(new FakeScorerSupplier(80, 42));
-    new Boolean2ScorerSupplier(null, subs, random().nextBoolean(), 0).get(100); // triggers assertions as a side-effect
+    new Boolean2ScorerSupplier(null, subs, RandomPicks.randomFrom(random(), ScoreMode.values()), 0).get(100); // triggers assertions as a side-effect
 
     subs.get(Occur.MUST).clear();
     subs.get(Occur.MUST_NOT).clear();
     subs.get(Occur.MUST).add(new FakeScorerSupplier(42, 20));
     subs.get(Occur.MUST_NOT).add(new FakeScorerSupplier(30, 20));
-    new Boolean2ScorerSupplier(null, subs, random().nextBoolean(), 0).get(20); // triggers assertions as a side-effect
+    new Boolean2ScorerSupplier(null, subs, RandomPicks.randomFrom(random(), ScoreMode.values()), 0).get(20); // triggers assertions as a side-effect
   }
 
   public void testMixedLeadCost() throws IOException {
@@ -330,19 +334,19 @@ public class TestBoolean2ScorerSupplier extends LuceneTestCase {
     // The SHOULD clause is always called with the same lead cost as the MUST clause
     subs.get(Occur.MUST).add(new FakeScorerSupplier(42, 42));
     subs.get(Occur.SHOULD).add(new FakeScorerSupplier(30, 42));
-    new Boolean2ScorerSupplier(null, subs, true, 0).get(100); // triggers assertions as a side-effect
+    new Boolean2ScorerSupplier(null, subs, ScoreMode.COMPLETE, 0).get(100); // triggers assertions as a side-effect
 
     subs.get(Occur.MUST).clear();
     subs.get(Occur.SHOULD).clear();
     subs.get(Occur.MUST).add(new FakeScorerSupplier(42, 42));
     subs.get(Occur.SHOULD).add(new FakeScorerSupplier(80, 42));
-    new Boolean2ScorerSupplier(null, subs, true, 0).get(100); // triggers assertions as a side-effect
+    new Boolean2ScorerSupplier(null, subs, ScoreMode.COMPLETE, 0).get(100); // triggers assertions as a side-effect
 
     subs.get(Occur.MUST).clear();
     subs.get(Occur.SHOULD).clear();
     subs.get(Occur.MUST).add(new FakeScorerSupplier(42, 20));
     subs.get(Occur.SHOULD).add(new FakeScorerSupplier(80, 20));
-    new Boolean2ScorerSupplier(null, subs, true, 0).get(20); // triggers assertions as a side-effect
+    new Boolean2ScorerSupplier(null, subs, ScoreMode.COMPLETE, 0).get(20); // triggers assertions as a side-effect
   }
 
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/search/TestBooleanOr.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestBooleanOr.java b/lucene/core/src/test/org/apache/lucene/search/TestBooleanOr.java
index e95ffa4..d37fd2e 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestBooleanOr.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestBooleanOr.java
@@ -186,7 +186,7 @@ public class TestBooleanOr extends LuceneTestCase {
     bq.add(new TermQuery(new Term("field", "a")), BooleanClause.Occur.SHOULD);
     bq.add(new TermQuery(new Term("field", "a")), BooleanClause.Occur.SHOULD);
 
-    Weight w = s.createNormalizedWeight(bq.build(), true);
+    Weight w = s.createNormalizedWeight(bq.build(), ScoreMode.COMPLETE);
 
     assertEquals(1, s.getIndexReader().leaves().size());
     BulkScorer scorer = w.bulkScorer(s.getIndexReader().leaves().get(0));
@@ -202,8 +202,8 @@ public class TestBooleanOr 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/TestBooleanQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestBooleanQuery.java b/lucene/core/src/test/org/apache/lucene/search/TestBooleanQuery.java
index ad44603..c479a8c 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestBooleanQuery.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestBooleanQuery.java
@@ -313,7 +313,7 @@ public class TestBooleanQuery extends LuceneTestCase {
         q.add(new BooleanClause(new TermQuery(new Term("field", term)), BooleanClause.Occur.SHOULD));
       }
 
-      Weight weight = s.createNormalizedWeight(q.build(), true);
+      Weight weight = s.createNormalizedWeight(q.build(), ScoreMode.COMPLETE);
 
       Scorer scorer = weight.scorer(s.leafContexts.get(0));
 
@@ -331,7 +331,7 @@ public class TestBooleanQuery extends LuceneTestCase {
       // verify exact match:
       for(int iter2=0;iter2<10;iter2++) {
 
-        weight = s.createNormalizedWeight(q.build(), true);
+        weight = s.createNormalizedWeight(q.build(), ScoreMode.COMPLETE);
         scorer = weight.scorer(s.leafContexts.get(0));
 
         if (VERBOSE) {
@@ -431,8 +431,8 @@ public class TestBooleanQuery extends LuceneTestCase {
     searcher.search(query, new SimpleCollector() {
       int docBase = 0;
       @Override
-      public boolean needsScores() {
-        return random().nextBoolean();
+      public ScoreMode scoreMode() {
+        return ScoreMode.COMPLETE_NO_SCORES;
       }
       @Override
       protected void doSetNextReader(LeafReaderContext context)
@@ -511,8 +511,8 @@ public class TestBooleanQuery extends LuceneTestCase {
       }
 
       @Override
-      public boolean needsScores() {
-        return true;
+      public ScoreMode scoreMode() {
+        return ScoreMode.COMPLETE;
       }
 
       @Override
@@ -617,7 +617,7 @@ public class TestBooleanQuery extends LuceneTestCase {
     q.add(pq, Occur.MUST);
     q.add(new TermQuery(new Term("field", "c")), Occur.FILTER);
 
-    final Weight weight = searcher.createNormalizedWeight(q.build(), random().nextBoolean());
+    final Weight weight = searcher.createNormalizedWeight(q.build(), ScoreMode.COMPLETE);
     final Scorer scorer = weight.scorer(searcher.getIndexReader().leaves().get(0));
     assertTrue(scorer instanceof ConjunctionScorer);
     assertNotNull(scorer.twoPhaseIterator());
@@ -646,7 +646,7 @@ public class TestBooleanQuery extends LuceneTestCase {
     q.add(pq, Occur.SHOULD);
     q.add(new TermQuery(new Term("field", "c")), Occur.SHOULD);
 
-    final Weight weight = searcher.createNormalizedWeight(q.build(), random().nextBoolean());
+    final Weight weight = searcher.createNormalizedWeight(q.build(), ScoreMode.COMPLETE);
     final Scorer scorer = weight.scorer(reader.leaves().get(0));
     assertTrue(scorer instanceof DisjunctionScorer);
     assertNotNull(scorer.twoPhaseIterator());
@@ -677,7 +677,7 @@ public class TestBooleanQuery extends LuceneTestCase {
     q.add(pq, Occur.SHOULD);
     q.add(new TermQuery(new Term("field", "d")), Occur.SHOULD);
 
-    final Weight weight = searcher.createNormalizedWeight(q.build(), random().nextBoolean());
+    final Weight weight = searcher.createNormalizedWeight(q.build(), ScoreMode.COMPLETE);
     final Scorer scorer = weight.scorer(searcher.getIndexReader().leaves().get(0));
     assertTrue(scorer instanceof ExactPhraseScorer);
     assertNotNull(scorer.twoPhaseIterator());
@@ -706,7 +706,7 @@ public class TestBooleanQuery extends LuceneTestCase {
     q.add(pq, Occur.SHOULD);
     q.add(new TermQuery(new Term("field", "c")), Occur.MUST_NOT);
 
-    final Weight weight = searcher.createNormalizedWeight(q.build(), random().nextBoolean());
+    final Weight weight = searcher.createNormalizedWeight(q.build(), ScoreMode.COMPLETE);
     final Scorer scorer = weight.scorer(reader.leaves().get(0));
     assertTrue(scorer instanceof ReqExclScorer);
     assertNotNull(scorer.twoPhaseIterator());
@@ -735,7 +735,7 @@ public class TestBooleanQuery extends LuceneTestCase {
     q.add(pq, Occur.MUST);
     q.add(new TermQuery(new Term("field", "c")), Occur.SHOULD);
 
-    final Weight weight = searcher.createNormalizedWeight(q.build(), true);
+    final Weight weight = searcher.createNormalizedWeight(q.build(), ScoreMode.COMPLETE);
     final Scorer scorer = weight.scorer(reader.leaves().get(0));
     assertTrue(scorer instanceof ReqOptSumScorer);
     assertNotNull(scorer.twoPhaseIterator());
@@ -768,11 +768,11 @@ public class TestBooleanQuery extends LuceneTestCase {
     BooleanQuery bq = bqBuilder.build();
 
     Set<Term> scoringTerms = new HashSet<>();
-    searcher.createNormalizedWeight(bq, true).extractTerms(scoringTerms);
+    searcher.createNormalizedWeight(bq, ScoreMode.COMPLETE).extractTerms(scoringTerms);
     assertEquals(new HashSet<>(Arrays.asList(a, b)), scoringTerms);
 
     Set<Term> matchingTerms = new HashSet<>();
-    searcher.createNormalizedWeight(bq, false).extractTerms(matchingTerms);
+    searcher.createNormalizedWeight(bq, ScoreMode.COMPLETE_NO_SCORES).extractTerms(matchingTerms);
     assertEquals(new HashSet<>(Arrays.asList(a, b, c)), matchingTerms);
   }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/search/TestBooleanQueryVisitSubscorers.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestBooleanQueryVisitSubscorers.java b/lucene/core/src/test/org/apache/lucene/search/TestBooleanQueryVisitSubscorers.java
index a0ffdae..19f45f8 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestBooleanQueryVisitSubscorers.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestBooleanQueryVisitSubscorers.java
@@ -197,7 +197,7 @@ public class TestBooleanQueryVisitSubscorers extends LuceneTestCase {
     bq1.add(new TermQuery(new Term(F1, "lucene")), Occur.SHOULD);
     bq1.add(new PhraseQuery(F2, "search", "engine"), Occur.SHOULD);
 
-    Weight w1 = scorerSearcher.createNormalizedWeight(bq1.build(), true);
+    Weight w1 = scorerSearcher.createNormalizedWeight(bq1.build(), ScoreMode.COMPLETE);
     Scorer s1 = w1.scorer(reader.leaves().get(0));
     assertEquals(0, s1.iterator().nextDoc());
     assertEquals(2, s1.getChildren().size());
@@ -206,7 +206,7 @@ public class TestBooleanQueryVisitSubscorers extends LuceneTestCase {
     bq2.add(new TermQuery(new Term(F1, "lucene")), Occur.SHOULD);
     bq2.add(new PhraseQuery(F2, "search", "library"), Occur.SHOULD);
 
-    Weight w2 = scorerSearcher.createNormalizedWeight(bq2.build(), true);
+    Weight w2 = scorerSearcher.createNormalizedWeight(bq2.build(), ScoreMode.COMPLETE);
     Scorer s2 = w2.scorer(reader.leaves().get(0));
     assertEquals(0, s2.iterator().nextDoc());
     assertEquals(1, s2.getChildren().size());
@@ -219,7 +219,7 @@ public class TestBooleanQueryVisitSubscorers extends LuceneTestCase {
     bq.add(new PhraseQuery(F2, "search", "library"), Occur.SHOULD);
     bq.setMinimumNumberShouldMatch(2);
 
-    Weight w = scorerSearcher.createNormalizedWeight(bq.build(), true);
+    Weight w = scorerSearcher.createNormalizedWeight(bq.build(), ScoreMode.COMPLETE);
     Scorer s = w.scorer(reader.leaves().get(0));
     assertEquals(0, s.iterator().nextDoc());
     assertEquals(2, s.getChildren().size());
@@ -275,8 +275,8 @@ public class TestBooleanQueryVisitSubscorers extends LuceneTestCase {
     }
     
     @Override
-    public boolean needsScores() {
-      return true;
+    public ScoreMode scoreMode() {
+      return ScoreMode.COMPLETE;
     }
 
     @Override
@@ -340,6 +340,10 @@ public class TestBooleanQueryVisitSubscorers extends LuceneTestCase {
         public float score(int doc, float freq) throws IOException {
           return freq;
         }
+        @Override
+        public float maxScore(float maxFreq) {
+          return maxFreq;
+        }
       };
     }
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/search/TestBooleanRewrites.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestBooleanRewrites.java b/lucene/core/src/test/org/apache/lucene/search/TestBooleanRewrites.java
index 9337bf7..d21f373 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestBooleanRewrites.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestBooleanRewrites.java
@@ -93,7 +93,7 @@ public class TestBooleanRewrites extends LuceneTestCase {
     BooleanQuery.Builder query2 = new BooleanQuery.Builder();
     query2.add(new TermQuery(new Term("field", "a")), Occur.FILTER);
     query2.add(new TermQuery(new Term("field", "b")), Occur.SHOULD);
-    final Weight weight = searcher.createNormalizedWeight(query2.build(), true);
+    final Weight weight = searcher.createNormalizedWeight(query2.build(), ScoreMode.COMPLETE);
     final Scorer scorer = weight.scorer(reader.leaves().get(0));
     assertEquals(0, scorer.iterator().nextDoc());
     assertTrue(scorer.getClass().getName(), scorer instanceof FilterScorer);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/search/TestBooleanScorer.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestBooleanScorer.java b/lucene/core/src/test/org/apache/lucene/search/TestBooleanScorer.java
index 6e20a11..8a8379b 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestBooleanScorer.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestBooleanScorer.java
@@ -77,7 +77,7 @@ public class TestBooleanScorer extends LuceneTestCase {
     }
 
     @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 Weight(CrazyMustUseBulkScorerQuery.this) {
         @Override
         public void extractTerms(Set<Term> terms) {
@@ -172,7 +172,7 @@ public class TestBooleanScorer extends LuceneTestCase {
       .build();
 
     // no scores -> term scorer
-    Weight weight = searcher.createNormalizedWeight(query, false);
+    Weight weight = searcher.createNormalizedWeight(query, ScoreMode.COMPLETE_NO_SCORES);
     BulkScorer scorer = ((BooleanWeight) weight).booleanScorer(ctx);
     assertTrue(scorer instanceof DefaultBulkScorer); // term scorer
 
@@ -181,7 +181,7 @@ public class TestBooleanScorer extends LuceneTestCase {
       .add(new TermQuery(new Term("foo", "bar")), Occur.SHOULD) // existing term
       .add(new TermQuery(new Term("foo", "baz")), Occur.SHOULD) // missing term
       .build();
-    weight = searcher.createNormalizedWeight(query, true);
+    weight = searcher.createNormalizedWeight(query, ScoreMode.COMPLETE);
     scorer = ((BooleanWeight) weight).booleanScorer(ctx);
     assertTrue(scorer instanceof DefaultBulkScorer); // term scorer
 
@@ -210,7 +210,7 @@ public class TestBooleanScorer extends LuceneTestCase {
       .add(new TermQuery(new Term("foo", "baz")), Occur.SHOULD)
       .add(new TermQuery(new Term("foo", "bar")), Occur.MUST_NOT)
       .build();
-    Weight weight = searcher.createNormalizedWeight(query, true);
+    Weight weight = searcher.createNormalizedWeight(query, ScoreMode.COMPLETE);
     BulkScorer scorer = ((BooleanWeight) weight).booleanScorer(ctx);
     assertTrue(scorer instanceof ReqExclBulkScorer);
 
@@ -219,7 +219,7 @@ public class TestBooleanScorer extends LuceneTestCase {
         .add(new MatchAllDocsQuery(), Occur.SHOULD)
         .add(new TermQuery(new Term("foo", "bar")), Occur.MUST_NOT)
         .build();
-    weight = searcher.createNormalizedWeight(query, true);
+    weight = searcher.createNormalizedWeight(query, ScoreMode.COMPLETE);
     scorer = ((BooleanWeight) weight).booleanScorer(ctx);
     assertTrue(scorer instanceof ReqExclBulkScorer);
 
@@ -227,7 +227,7 @@ public class TestBooleanScorer extends LuceneTestCase {
         .add(new TermQuery(new Term("foo", "baz")), Occur.MUST)
         .add(new TermQuery(new Term("foo", "bar")), Occur.MUST_NOT)
         .build();
-    weight = searcher.createNormalizedWeight(query, true);
+    weight = searcher.createNormalizedWeight(query, ScoreMode.COMPLETE);
     scorer = ((BooleanWeight) weight).booleanScorer(ctx);
     assertTrue(scorer instanceof ReqExclBulkScorer);
 
@@ -235,7 +235,7 @@ public class TestBooleanScorer extends LuceneTestCase {
         .add(new TermQuery(new Term("foo", "baz")), Occur.FILTER)
         .add(new TermQuery(new Term("foo", "bar")), Occur.MUST_NOT)
         .build();
-    weight = searcher.createNormalizedWeight(query, true);
+    weight = searcher.createNormalizedWeight(query, ScoreMode.COMPLETE);
     scorer = ((BooleanWeight) weight).booleanScorer(ctx);
     assertTrue(scorer instanceof ReqExclBulkScorer);
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/search/TestCachingCollector.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestCachingCollector.java b/lucene/core/src/test/org/apache/lucene/search/TestCachingCollector.java
index 29b6a9d..24038f5 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestCachingCollector.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestCachingCollector.java
@@ -35,6 +35,9 @@ public class TestCachingCollector extends LuceneTestCase {
     public float score() throws IOException { return 0; }
 
     @Override
+    public float maxScore() { return 0; }
+
+    @Override
     public int docID() { return 0; }
 
     @Override
@@ -49,8 +52,8 @@ public class TestCachingCollector extends LuceneTestCase {
     public void collect(int doc) throws IOException {}
     
     @Override
-    public boolean needsScores() {
-      return false;
+    public ScoreMode scoreMode() {
+      return ScoreMode.COMPLETE_NO_SCORES;
     }
 
   }
@@ -77,8 +80,8 @@ public class TestCachingCollector 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/TestConjunctionDISI.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestConjunctionDISI.java b/lucene/core/src/test/org/apache/lucene/search/TestConjunctionDISI.java
index f11809a..544c6da 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestConjunctionDISI.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestConjunctionDISI.java
@@ -146,6 +146,10 @@ public class TestConjunctionDISI extends LuceneTestCase {
         return 0;
       }
 
+      @Override
+      public float maxScore() {
+        return 0;
+      }
     };
   }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/search/TestConjunctions.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestConjunctions.java b/lucene/core/src/test/org/apache/lucene/search/TestConjunctions.java
index e561471..a4e9596 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestConjunctions.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestConjunctions.java
@@ -112,6 +112,11 @@ public class TestConjunctions extends LuceneTestCase {
         public float score(int doc, float freq) {
           return freq;
         }
+
+        @Override
+        public float maxScore(float maxFreq) {
+          return maxFreq;
+        }
       };
     }
   }
@@ -153,8 +158,8 @@ public class TestConjunctions extends LuceneTestCase {
         }
 
         @Override
-        public boolean needsScores() {
-          return true;
+        public ScoreMode scoreMode() {
+          return ScoreMode.COMPLETE;
         }
       });
     assertTrue(setScorerCalled[0]);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/search/TestConstantScoreQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestConstantScoreQuery.java b/lucene/core/src/test/org/apache/lucene/search/TestConstantScoreQuery.java
index f97afd5..f3382a5bf 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestConstantScoreQuery.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestConstantScoreQuery.java
@@ -74,8 +74,8 @@ public class TestConstantScoreQuery extends LuceneTestCase {
       }
       
       @Override
-      public boolean needsScores() {
-        return true;
+      public ScoreMode scoreMode() {
+        return ScoreMode.COMPLETE;
       }
     });
     assertEquals("invalid number of results", 1, count[0]);
@@ -135,8 +135,8 @@ public class TestConstantScoreQuery extends LuceneTestCase {
     }
     
     @Override
-    public Weight createWeight(IndexSearcher searcher, boolean needsScores, float boost) throws IOException {
-      return in.createWeight(searcher, needsScores, boost);
+    public Weight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
+      return in.createWeight(searcher, scoreMode, boost);
     }
 
     @Override
@@ -203,7 +203,7 @@ public class TestConstantScoreQuery extends LuceneTestCase {
 
     ConstantScoreQuery q = new ConstantScoreQuery(pq);
 
-    final Weight weight = searcher.createNormalizedWeight(q, true);
+    final Weight weight = searcher.createNormalizedWeight(q, ScoreMode.COMPLETE);
     final Scorer scorer = weight.scorer(searcher.getIndexReader().leaves().get(0));
     assertNotNull(scorer.twoPhaseIterator());
 
@@ -218,11 +218,11 @@ public class TestConstantScoreQuery extends LuceneTestCase {
     final ConstantScoreQuery csq = new ConstantScoreQuery(termQuery);
 
     final Set<Term> scoringTerms = new HashSet<>();
-    searcher.createNormalizedWeight(csq, true).extractTerms(scoringTerms);
+    searcher.createNormalizedWeight(csq, ScoreMode.COMPLETE).extractTerms(scoringTerms);
     assertEquals(Collections.emptySet(), scoringTerms);
 
     final Set<Term> matchingTerms = new HashSet<>();
-    searcher.createNormalizedWeight(csq, false).extractTerms(matchingTerms);
+    searcher.createNormalizedWeight(csq, ScoreMode.COMPLETE_NO_SCORES).extractTerms(matchingTerms);
     assertEquals(Collections.singleton(new Term("foo", "bar")), matchingTerms);
   }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/search/TestDisjunctionMaxQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestDisjunctionMaxQuery.java b/lucene/core/src/test/org/apache/lucene/search/TestDisjunctionMaxQuery.java
index 82ae647..70bb996 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestDisjunctionMaxQuery.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestDisjunctionMaxQuery.java
@@ -175,7 +175,7 @@ public class TestDisjunctionMaxQuery extends LuceneTestCase {
 
     QueryUtils.check(random(), dq, s);
     assertTrue(s.getTopReaderContext() instanceof LeafReaderContext);
-    final Weight dw = s.createNormalizedWeight(dq, true);
+    final Weight dw = s.createNormalizedWeight(dq, ScoreMode.COMPLETE);
     LeafReaderContext context = (LeafReaderContext)s.getTopReaderContext();
     final Scorer ds = dw.scorer(context);
     final boolean skipOk = ds.iterator().advance(3) != DocIdSetIterator.NO_MORE_DOCS;
@@ -191,7 +191,7 @@ public class TestDisjunctionMaxQuery extends LuceneTestCase {
 
     assertTrue(s.getTopReaderContext() instanceof LeafReaderContext);
     QueryUtils.check(random(), dq, s);
-    final Weight dw = s.createNormalizedWeight(dq, true);
+    final Weight dw = s.createNormalizedWeight(dq, ScoreMode.COMPLETE);
     LeafReaderContext context = (LeafReaderContext)s.getTopReaderContext();
     final Scorer ds = dw.scorer(context);
     assertTrue("firsttime skipTo found no match",

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/search/TestDocValuesQueries.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestDocValuesQueries.java b/lucene/core/src/test/org/apache/lucene/search/TestDocValuesQueries.java
index 43fae3e..3e9cabc 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestDocValuesQueries.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestDocValuesQueries.java
@@ -230,7 +230,7 @@ public class TestDocValuesQueries extends LuceneTestCase {
         SortedNumericDocValuesField.newSlowRangeQuery("foo", 2, 4),
         SortedDocValuesField.newSlowRangeQuery("foo", new BytesRef("abc"), new BytesRef("bcd"), random().nextBoolean(), random().nextBoolean()),
         SortedSetDocValuesField.newSlowRangeQuery("foo", new BytesRef("abc"), new BytesRef("bcd"), random().nextBoolean(), random().nextBoolean()))) {
-      Weight w = searcher.createNormalizedWeight(query, random().nextBoolean());
+      Weight w = searcher.createNormalizedWeight(query, ScoreMode.COMPLETE);
       assertNull(w.scorer(searcher.getIndexReader().leaves().get(0)));
     }
     reader.close();

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/search/TestDocValuesScoring.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestDocValuesScoring.java b/lucene/core/src/test/org/apache/lucene/search/TestDocValuesScoring.java
index 6cdbaf1..7b5fba6 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestDocValuesScoring.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestDocValuesScoring.java
@@ -174,6 +174,11 @@ public class TestDocValuesScoring extends LuceneTestCase {
         }
 
         @Override
+        public float maxScore(float maxFreq) {
+          return Float.POSITIVE_INFINITY;
+        }
+
+        @Override
         public Explanation explain(int doc, Explanation freq) throws IOException {
           Explanation boostExplanation = Explanation.match(getValueForDoc(doc), "indexDocValue(" + boostField + ")");
           Explanation simExplanation = sub.explain(doc, freq);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/search/TestDoubleValuesSource.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestDoubleValuesSource.java b/lucene/core/src/test/org/apache/lucene/search/TestDoubleValuesSource.java
index d424cfb..5a5a3ae 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestDoubleValuesSource.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestDoubleValuesSource.java
@@ -225,8 +225,8 @@ public class TestDoubleValuesSource extends LuceneTestCase {
       }
 
       @Override
-      public boolean needsScores() {
-        return rewritten.needsScores();
+      public ScoreMode scoreMode() {
+        return vs.needsScores() ? ScoreMode.COMPLETE : ScoreMode.COMPLETE_NO_SCORES;
       }
     });
   }
@@ -258,8 +258,8 @@ public class TestDoubleValuesSource extends LuceneTestCase {
       }
 
       @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/test/org/apache/lucene/search/TestEarlyTermination.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestEarlyTermination.java b/lucene/core/src/test/org/apache/lucene/search/TestEarlyTermination.java
index 4a52491..9466282 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestEarlyTermination.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestEarlyTermination.java
@@ -82,8 +82,8 @@ public class TestEarlyTermination 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/TestIndexOrDocValuesQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestIndexOrDocValuesQuery.java b/lucene/core/src/test/org/apache/lucene/search/TestIndexOrDocValuesQuery.java
index 7f3e599..cea9443 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestIndexOrDocValuesQuery.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestIndexOrDocValuesQuery.java
@@ -67,7 +67,7 @@ public class TestIndexOrDocValuesQuery extends LuceneTestCase {
         .add(new IndexOrDocValuesQuery(LongPoint.newExactQuery("f2", 2), NumericDocValuesField.newSlowRangeQuery("f2", 2L, 2L)), Occur.MUST)
         .build();
 
-    final Weight w1 = searcher.createNormalizedWeight(q1, random().nextBoolean());
+    final Weight w1 = searcher.createNormalizedWeight(q1, ScoreMode.COMPLETE);
     final Scorer s1 = w1.scorer(searcher.getIndexReader().leaves().get(0));
     assertNotNull(s1.twoPhaseIterator()); // means we use doc values
 
@@ -77,7 +77,7 @@ public class TestIndexOrDocValuesQuery extends LuceneTestCase {
         .add(new IndexOrDocValuesQuery(LongPoint.newExactQuery("f2", 42), NumericDocValuesField.newSlowRangeQuery("f2", 42L, 42L)), Occur.MUST)
         .build();
 
-    final Weight w2 = searcher.createNormalizedWeight(q2, random().nextBoolean());
+    final Weight w2 = searcher.createNormalizedWeight(q2, ScoreMode.COMPLETE);
     final Scorer s2 = w2.scorer(searcher.getIndexReader().leaves().get(0));
     assertNull(s2.twoPhaseIterator()); // means we use points
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/search/TestLRUQueryCache.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestLRUQueryCache.java b/lucene/core/src/test/org/apache/lucene/search/TestLRUQueryCache.java
index b777286..f6b1c73 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestLRUQueryCache.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestLRUQueryCache.java
@@ -346,7 +346,7 @@ public class TestLRUQueryCache extends LuceneTestCase {
     }
 
     @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
         public Scorer scorer(LeafReaderContext context) throws IOException {
@@ -939,7 +939,7 @@ public class TestLRUQueryCache extends LuceneTestCase {
     int[] i = new int[] {42}; // an array so that clone keeps the reference
 
     @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
         public Scorer scorer(LeafReaderContext context) throws IOException {
@@ -1139,7 +1139,7 @@ public class TestLRUQueryCache extends LuceneTestCase {
     LRUQueryCache cache = new LRUQueryCache(1, Long.MAX_VALUE, context -> true, Float.POSITIVE_INFINITY);
 
     // test that the bulk scorer is propagated when a scorer should not be cached
-    Weight weight = searcher.createNormalizedWeight(new MatchAllDocsQuery(), false);
+    Weight weight = searcher.createNormalizedWeight(new MatchAllDocsQuery(), ScoreMode.COMPLETE_NO_SCORES);
     weight = new WeightWrapper(weight, scorerCalled, bulkScorerCalled);
     weight = cache.doCache(weight, NEVER_CACHE);
     weight.bulkScorer(leaf);
@@ -1273,7 +1273,7 @@ public class TestLRUQueryCache extends LuceneTestCase {
   private static class NoCacheQuery 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 {
       return new Weight(this) {
         @Override
         public void extractTerms(Set<Term> terms) {
@@ -1350,7 +1350,7 @@ public class TestLRUQueryCache extends LuceneTestCase {
     }
 
     @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
         public Scorer scorer(LeafReaderContext context) throws IOException {
@@ -1412,7 +1412,7 @@ public class TestLRUQueryCache extends LuceneTestCase {
 
     AtomicBoolean scorerCreated = new AtomicBoolean(false);
     Query query = new DummyQuery2(scorerCreated);
-    Weight weight = searcher.createNormalizedWeight(query, false);
+    Weight weight = searcher.createNormalizedWeight(query, ScoreMode.COMPLETE_NO_SCORES);
     ScorerSupplier supplier = weight.scorerSupplier(searcher.getIndexReader().leaves().get(0));
     assertFalse(scorerCreated.get());
     supplier.get(random().nextLong() & 0x7FFFFFFFFFFFFFFFL);
@@ -1449,7 +1449,7 @@ public class TestLRUQueryCache extends LuceneTestCase {
     }
 
     @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, 1) {
 
         @Override

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/search/TestMinShouldMatch2.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestMinShouldMatch2.java b/lucene/core/src/test/org/apache/lucene/search/TestMinShouldMatch2.java
index 81ae187..924a1af 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestMinShouldMatch2.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestMinShouldMatch2.java
@@ -119,7 +119,7 @@ public class TestMinShouldMatch2 extends LuceneTestCase {
     }
     bq.setMinimumNumberShouldMatch(minShouldMatch);
 
-    BooleanWeight weight = (BooleanWeight) searcher.createNormalizedWeight(bq.build(), true);
+    BooleanWeight weight = (BooleanWeight) searcher.createNormalizedWeight(bq.build(), ScoreMode.COMPLETE);
     
     switch (mode) {
     case DOC_VALUES:
@@ -346,6 +346,10 @@ public class TestMinShouldMatch2 extends LuceneTestCase {
     }
 
     @Override
+    public float maxScore() {
+      return Float.POSITIVE_INFINITY;
+    }
+
     public int docID() {
       return currentDoc;
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/search/TestNeedsScores.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestNeedsScores.java b/lucene/core/src/test/org/apache/lucene/search/TestNeedsScores.java
index 3f8b59f..9352f72 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestNeedsScores.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestNeedsScores.java
@@ -62,27 +62,27 @@ public class TestNeedsScores extends LuceneTestCase {
     Query required = new TermQuery(new Term("field", "this"));
     Query prohibited = new TermQuery(new Term("field", "3"));
     BooleanQuery.Builder bq = new BooleanQuery.Builder();
-    bq.add(new AssertNeedsScores(required, true), BooleanClause.Occur.MUST);
-    bq.add(new AssertNeedsScores(prohibited, false), BooleanClause.Occur.MUST_NOT);
+    bq.add(new AssertNeedsScores(required, ScoreMode.COMPLETE), BooleanClause.Occur.MUST);
+    bq.add(new AssertNeedsScores(prohibited, ScoreMode.COMPLETE_NO_SCORES), BooleanClause.Occur.MUST_NOT);
     assertEquals(4, searcher.search(bq.build(), 5).totalHits); // we exclude 3
   }
   
   /** nested inside constant score query */
   public void testConstantScoreQuery() throws Exception {
     Query term = new TermQuery(new Term("field", "this"));
-    Query constantScore = new ConstantScoreQuery(new AssertNeedsScores(term, false));
+    Query constantScore = new ConstantScoreQuery(new AssertNeedsScores(term, ScoreMode.COMPLETE_NO_SCORES));
     assertEquals(5, searcher.search(constantScore, 5).totalHits);
   }
   
   /** when not sorting by score */
   public void testSortByField() throws Exception {
-    Query query = new AssertNeedsScores(new MatchAllDocsQuery(), false);
+    Query query = new AssertNeedsScores(new MatchAllDocsQuery(), ScoreMode.COMPLETE_NO_SCORES);
     assertEquals(5, searcher.search(query, 5, Sort.INDEXORDER).totalHits);
   }
   
   /** when sorting by score */
   public void testSortByScore() throws Exception {
-    Query query = new AssertNeedsScores(new MatchAllDocsQuery(), true);
+    Query query = new AssertNeedsScores(new MatchAllDocsQuery(), ScoreMode.COMPLETE);
     assertEquals(5, searcher.search(query, 5, Sort.RELEVANCE).totalHits);
   }
 
@@ -92,20 +92,20 @@ public class TestNeedsScores extends LuceneTestCase {
    */
   static class AssertNeedsScores extends Query {
     final Query in;
-    final boolean value;
+    final ScoreMode value;
     
-    AssertNeedsScores(Query in, boolean value) {
+    AssertNeedsScores(Query in, ScoreMode value) {
       this.in = Objects.requireNonNull(in);
       this.value = value;
     }
 
     @Override
-    public Weight createWeight(IndexSearcher searcher, boolean needsScores, float boost) throws IOException {
-      final Weight w = in.createWeight(searcher, needsScores, boost);
+    public Weight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
+      final Weight w = in.createWeight(searcher, scoreMode, boost);
       return new FilterWeight(w) {
         @Override
         public Scorer scorer(LeafReaderContext context) throws IOException {
-          assertEquals("query=" + in, value, needsScores);
+          assertEquals("query=" + in, value, scoreMode);
           return w.scorer(context);
         }
       };
@@ -126,7 +126,7 @@ public class TestNeedsScores extends LuceneTestCase {
       final int prime = 31;
       int result = classHash();
       result = prime * result + in.hashCode();
-      result = prime * result + (value ? 1231 : 1237);
+      result = prime * result + value.hashCode();
       return result;
     }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/search/TestPointQueries.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestPointQueries.java b/lucene/core/src/test/org/apache/lucene/search/TestPointQueries.java
index 8f7beaf..08c3735 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestPointQueries.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestPointQueries.java
@@ -559,8 +559,8 @@ public class TestPointQueries extends LuceneTestCase {
                   private int docBase;
 
                   @Override
-                  public boolean needsScores() {
-                    return false;
+                  public ScoreMode scoreMode() {
+                    return ScoreMode.COMPLETE_NO_SCORES;
                   }
 
                   @Override
@@ -814,8 +814,8 @@ public class TestPointQueries extends LuceneTestCase {
                   private int docBase;
 
                   @Override
-                  public boolean needsScores() {
-                    return false;
+                  public ScoreMode scoreMode() {
+                    return ScoreMode.COMPLETE_NO_SCORES;
                   }
 
                   @Override
@@ -1903,7 +1903,7 @@ public class TestPointQueries extends LuceneTestCase {
       upperBound[i] = value[i] + random().nextInt(1);
     }
     Query query = IntPoint.newRangeQuery("point", lowerBound, upperBound);
-    Weight weight = searcher.createNormalizedWeight(query, false);
+    Weight weight = searcher.createNormalizedWeight(query, ScoreMode.COMPLETE_NO_SCORES);
     Scorer scorer = weight.scorer(searcher.getIndexReader().leaves().get(0));
     assertEquals(DocIdSetIterator.all(1).getClass(), scorer.iterator().getClass());
 
@@ -1914,7 +1914,7 @@ public class TestPointQueries extends LuceneTestCase {
     reader = w.getReader();
     searcher = new IndexSearcher(reader);
     searcher.setQueryCache(null);
-    weight = searcher.createNormalizedWeight(query, false);
+    weight = searcher.createNormalizedWeight(query, ScoreMode.COMPLETE_NO_SCORES);
     scorer = weight.scorer(searcher.getIndexReader().leaves().get(0));
     assertFalse(DocIdSetIterator.all(1).getClass().equals(scorer.iterator().getClass()));
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/search/TestPositionIncrement.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestPositionIncrement.java b/lucene/core/src/test/org/apache/lucene/search/TestPositionIncrement.java
index 3dd9b18..9348862 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestPositionIncrement.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestPositionIncrement.java
@@ -252,7 +252,7 @@ public class TestPositionIncrement extends LuceneTestCase {
       System.out.println("\ngetPayloadSpans test");
     }
     PayloadSpanCollector collector = new PayloadSpanCollector();
-    Spans pspans = snq.createWeight(is, false, 1f).getSpans(is.getIndexReader().leaves().get(0), SpanWeight.Postings.PAYLOADS);
+    Spans pspans = snq.createWeight(is, ScoreMode.COMPLETE_NO_SCORES, 1f).getSpans(is.getIndexReader().leaves().get(0), SpanWeight.Postings.PAYLOADS);
     while (pspans.nextDoc() != Spans.NO_MORE_DOCS) {
       while (pspans.nextStartPosition() != Spans.NO_MORE_POSITIONS) {
         if (VERBOSE) {
@@ -274,7 +274,7 @@ public class TestPositionIncrement extends LuceneTestCase {
     assertEquals(8, count);
 
     // System.out.println("\ngetSpans test");
-    Spans spans = snq.createWeight(is, false, 1f).getSpans(is.getIndexReader().leaves().get(0), SpanWeight.Postings.POSITIONS);
+    Spans spans = snq.createWeight(is, ScoreMode.COMPLETE_NO_SCORES, 1f).getSpans(is.getIndexReader().leaves().get(0), SpanWeight.Postings.POSITIONS);
     count = 0;
     sawZero = false;
     while (spans.nextDoc() != Spans.NO_MORE_DOCS) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/search/TestPositiveScoresOnlyCollector.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestPositiveScoresOnlyCollector.java b/lucene/core/src/test/org/apache/lucene/search/TestPositiveScoresOnlyCollector.java
index 44aa829..bf19b12 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestPositiveScoresOnlyCollector.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestPositiveScoresOnlyCollector.java
@@ -37,6 +37,11 @@ public class TestPositiveScoresOnlyCollector extends LuceneTestCase {
       return idx == scores.length ? Float.NaN : scores[idx];
     }
 
+    @Override
+    public float maxScore() {
+      return Float.POSITIVE_INFINITY;
+    }
+
     @Override public int docID() { return idx; }
 
     @Override
@@ -90,7 +95,7 @@ public class TestPositiveScoresOnlyCollector extends LuceneTestCase {
     IndexReader ir = writer.getReader();
     writer.close();
     IndexSearcher searcher = newSearcher(ir);
-    Weight fake = new TermQuery(new Term("fake", "weight")).createWeight(searcher, true, 1f);
+    Weight fake = new TermQuery(new Term("fake", "weight")).createWeight(searcher, ScoreMode.COMPLETE, 1f);
     Scorer s = new SimpleScorer(fake);
     TopDocsCollector<ScoreDoc> tdc = TopScoreDocCollector.create(scores.length);
     Collector c = new PositiveScoresOnlyCollector(tdc);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/search/TestQueryRescorer.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestQueryRescorer.java b/lucene/core/src/test/org/apache/lucene/search/TestQueryRescorer.java
index bda4008..9f5de37 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestQueryRescorer.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestQueryRescorer.java
@@ -418,7 +418,7 @@ public class TestQueryRescorer extends LuceneTestCase {
     }
 
     @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 Weight(FixedScoreQuery.this) {
 
@@ -479,6 +479,11 @@ public class TestQueryRescorer extends LuceneTestCase {
                 return 1f / (1 + num);
               }
             }
+
+            @Override
+            public float maxScore() {
+              return Float.POSITIVE_INFINITY;
+            }
           };
         }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/search/TestScoreCachingWrappingScorer.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestScoreCachingWrappingScorer.java b/lucene/core/src/test/org/apache/lucene/search/TestScoreCachingWrappingScorer.java
index a61fac8..fa852b6 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestScoreCachingWrappingScorer.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestScoreCachingWrappingScorer.java
@@ -42,6 +42,11 @@ public class TestScoreCachingWrappingScorer extends LuceneTestCase {
       // once per document.
       return idx == scores.length ? Float.NaN : scores[idx++];
     }
+    
+    @Override
+    public float maxScore() {
+      return Float.POSITIVE_INFINITY;
+    }
 
     @Override public int docID() { return doc; }
 
@@ -95,8 +100,8 @@ public class TestScoreCachingWrappingScorer extends LuceneTestCase {
     }
     
     @Override
-    public boolean needsScores() {
-      return true;
+    public ScoreMode scoreMode() {
+      return ScoreMode.COMPLETE;
     }
 
   }
@@ -112,7 +117,7 @@ public class TestScoreCachingWrappingScorer extends LuceneTestCase {
     IndexReader ir = writer.getReader();
     writer.close();
     IndexSearcher searcher = newSearcher(ir);
-    Weight fake = new TermQuery(new Term("fake", "weight")).createWeight(searcher, true, 1f);
+    Weight fake = new TermQuery(new Term("fake", "weight")).createWeight(searcher, ScoreMode.COMPLETE, 1f);
     Scorer s = new SimpleScorer(fake);
     ScoreCachingCollector scc = new ScoreCachingCollector(scores.length);
     scc.setScorer(s);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/search/TestScorerPerf.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestScorerPerf.java b/lucene/core/src/test/org/apache/lucene/search/TestScorerPerf.java
index c28ed8c..59a246c 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestScorerPerf.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestScorerPerf.java
@@ -117,8 +117,8 @@ public class TestScorerPerf extends LuceneTestCase {
     }
     
     @Override
-    public boolean needsScores() {
-      return false;
+    public ScoreMode scoreMode() {
+      return ScoreMode.COMPLETE_NO_SCORES;
     }
   }
 
@@ -149,7 +149,7 @@ public class TestScorerPerf extends LuceneTestCase {
     }
 
     @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
         public Scorer scorer(LeafReaderContext context) throws IOException {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/search/TestSimilarity.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestSimilarity.java b/lucene/core/src/test/org/apache/lucene/search/TestSimilarity.java
index 434b5d9..d855b4f 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestSimilarity.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestSimilarity.java
@@ -80,8 +80,8 @@ public class TestSimilarity extends LuceneTestCase {
            assertEquals(1.0f, scorer.score(), 0);
          }
          @Override
-         public boolean needsScores() {
-           return true;
+         public ScoreMode scoreMode() {
+           return ScoreMode.COMPLETE;
          }
        });
 
@@ -106,8 +106,8 @@ public class TestSimilarity extends LuceneTestCase {
            base = context.docBase;
          }
          @Override
-         public boolean needsScores() {
-           return true;
+         public ScoreMode scoreMode() {
+           return ScoreMode.COMPLETE;
          }
        });
 
@@ -126,8 +126,8 @@ public class TestSimilarity extends LuceneTestCase {
            assertEquals(1.0f, scorer.score(), 0);
          }
          @Override
-         public boolean needsScores() {
-           return true;
+         public ScoreMode scoreMode() {
+           return ScoreMode.COMPLETE;
          }
        });
 
@@ -145,8 +145,8 @@ public class TestSimilarity extends LuceneTestCase {
         assertEquals(0.5f, scorer.score(), 0);
       }
       @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/test/org/apache/lucene/search/TestSimilarityProvider.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestSimilarityProvider.java b/lucene/core/src/test/org/apache/lucene/search/TestSimilarityProvider.java
index ae8c949..a6970f9 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestSimilarityProvider.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestSimilarityProvider.java
@@ -126,6 +126,10 @@ public class TestSimilarityProvider extends LuceneTestCase {
           return 1;
         }
 
+        @Override
+        public float maxScore(float maxFreq) {
+          return 1;
+        }
       };
     }
 
@@ -151,7 +155,11 @@ public class TestSimilarityProvider extends LuceneTestCase {
         public float score(int doc, float freq) throws IOException {
           return 10;
         }
-        
+
+        @Override
+        public float maxScore(float maxFreq) {
+          return 10;
+        }
       };
     }
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/search/TestSloppyPhraseQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestSloppyPhraseQuery.java b/lucene/core/src/test/org/apache/lucene/search/TestSloppyPhraseQuery.java
index ee36d3b..66ee0c5 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestSloppyPhraseQuery.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestSloppyPhraseQuery.java
@@ -202,8 +202,8 @@ public class TestSloppyPhraseQuery extends LuceneTestCase {
     }
     
     @Override
-    public boolean needsScores() {
-      return true;
+    public ScoreMode scoreMode() {
+      return ScoreMode.COMPLETE;
     }
   }
   
@@ -227,8 +227,8 @@ public class TestSloppyPhraseQuery extends LuceneTestCase {
       }
       
       @Override
-      public boolean needsScores() {
-        return true;
+      public ScoreMode scoreMode() {
+        return ScoreMode.COMPLETE;
       }
     });
     QueryUtils.check(random(), pq, searcher);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/search/TestSortRandom.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestSortRandom.java b/lucene/core/src/test/org/apache/lucene/search/TestSortRandom.java
index ecfbb1b..05b016c 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestSortRandom.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestSortRandom.java
@@ -229,7 +229,7 @@ public class TestSortRandom extends LuceneTestCase {
     }
 
     @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
         public Scorer scorer(LeafReaderContext context) throws IOException {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/search/TestSubScorerFreqs.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestSubScorerFreqs.java b/lucene/core/src/test/org/apache/lucene/search/TestSubScorerFreqs.java
index 03b90d2..7278a3b 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestSubScorerFreqs.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestSubScorerFreqs.java
@@ -242,6 +242,11 @@ public class TestSubScorerFreqs extends LuceneTestCase {
         public float score(int doc, float freq) throws IOException {
           return freq;
         }
+
+        @Override
+        public float maxScore(float maxFreq) {
+          return maxFreq;
+        }
       };
     }
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/search/TestTermQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestTermQuery.java b/lucene/core/src/test/org/apache/lucene/search/TestTermQuery.java
index 02c1228..f65c54e 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestTermQuery.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestTermQuery.java
@@ -73,10 +73,10 @@ public class TestTermQuery extends LuceneTestCase {
     IndexSearcher noSeekSearcher = new IndexSearcher(noSeekReader);
     Query query = new TermQuery(new Term("foo", "bar"));
     AssertionError e = expectThrows(AssertionError.class,
-        () -> noSeekSearcher.createNormalizedWeight(query, true));
+        () -> noSeekSearcher.createNormalizedWeight(query, ScoreMode.COMPLETE));
     assertEquals("no seek", e.getMessage());
 
-    noSeekSearcher.createNormalizedWeight(query, false); // no exception
+    noSeekSearcher.createNormalizedWeight(query, ScoreMode.COMPLETE_NO_SCORES); // no exception
     IndexSearcher searcher = new IndexSearcher(reader);
     // use a collector rather than searcher.count() which would just read the
     // doc freq instead of creating a scorer

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/search/TestTermScorer.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestTermScorer.java b/lucene/core/src/test/org/apache/lucene/search/TestTermScorer.java
index f0ad9b9..2758c96 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestTermScorer.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestTermScorer.java
@@ -76,7 +76,7 @@ public class TestTermScorer extends LuceneTestCase {
     Term allTerm = new Term(FIELD, "all");
     TermQuery termQuery = new TermQuery(allTerm);
     
-    Weight weight = indexSearcher.createNormalizedWeight(termQuery, true);
+    Weight weight = indexSearcher.createNormalizedWeight(termQuery, ScoreMode.COMPLETE);
     assertTrue(indexSearcher.getTopReaderContext() instanceof LeafReaderContext);
     LeafReaderContext context = (LeafReaderContext)indexSearcher.getTopReaderContext();
     BulkScorer ts = weight.bulkScorer(context);
@@ -110,8 +110,8 @@ public class TestTermScorer extends LuceneTestCase {
       }
       
       @Override
-      public boolean needsScores() {
-        return true;
+      public ScoreMode scoreMode() {
+        return ScoreMode.COMPLETE;
       }
     }, null);
     assertTrue("docs Size: " + docs.size() + " is not: " + 2, docs.size() == 2);
@@ -127,7 +127,7 @@ public class TestTermScorer extends LuceneTestCase {
     Term allTerm = new Term(FIELD, "all");
     TermQuery termQuery = new TermQuery(allTerm);
     
-    Weight weight = indexSearcher.createNormalizedWeight(termQuery, true);
+    Weight weight = indexSearcher.createNormalizedWeight(termQuery, ScoreMode.COMPLETE);
     assertTrue(indexSearcher.getTopReaderContext() instanceof LeafReaderContext);
     LeafReaderContext context = (LeafReaderContext) indexSearcher.getTopReaderContext();
     Scorer ts = weight.scorer(context);
@@ -144,7 +144,7 @@ public class TestTermScorer extends LuceneTestCase {
     Term allTerm = new Term(FIELD, "all");
     TermQuery termQuery = new TermQuery(allTerm);
     
-    Weight weight = indexSearcher.createNormalizedWeight(termQuery, true);
+    Weight weight = indexSearcher.createNormalizedWeight(termQuery, ScoreMode.COMPLETE);
     assertTrue(indexSearcher.getTopReaderContext() instanceof LeafReaderContext);
     LeafReaderContext context = (LeafReaderContext) indexSearcher.getTopReaderContext();
     Scorer ts = weight.scorer(context);
@@ -193,12 +193,12 @@ public class TestTermScorer extends LuceneTestCase {
     // We don't use newSearcher because it sometimes runs checkIndex which loads norms
     IndexSearcher indexSearcher = new IndexSearcher(forbiddenNorms);
     
-    Weight weight = indexSearcher.createNormalizedWeight(termQuery, true);
+    Weight weight = indexSearcher.createNormalizedWeight(termQuery, ScoreMode.COMPLETE);
     expectThrows(AssertionError.class, () -> {
       weight.scorer(forbiddenNorms.getContext()).iterator().nextDoc();
     });
     
-    Weight weight2 = indexSearcher.createNormalizedWeight(termQuery, false);
+    Weight weight2 = indexSearcher.createNormalizedWeight(termQuery, ScoreMode.COMPLETE_NO_SCORES);
     // should not fail this time since norms are not necessary
     weight2.scorer(forbiddenNorms.getContext()).iterator().nextDoc();
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/search/TestTimeLimitingCollector.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestTimeLimitingCollector.java b/lucene/core/src/test/org/apache/lucene/search/TestTimeLimitingCollector.java
index 6a02e58..f375537 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestTimeLimitingCollector.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestTimeLimitingCollector.java
@@ -367,8 +367,8 @@ public class TestTimeLimitingCollector extends LuceneTestCase {
     }
     
     @Override
-    public boolean needsScores() {
-      return false;
+    public ScoreMode scoreMode() {
+      return ScoreMode.COMPLETE;
     }
 
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/search/TestTopDocsCollector.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestTopDocsCollector.java b/lucene/core/src/test/org/apache/lucene/search/TestTopDocsCollector.java
index 9a769fe..035003e 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestTopDocsCollector.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestTopDocsCollector.java
@@ -18,10 +18,14 @@ package org.apache.lucene.search;
 
 
 import java.io.IOException;
+import java.util.Arrays;
 
 import org.apache.lucene.document.Document;
-import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.DirectoryReader;
 import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.NoMergePolicy;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.LuceneTestCase;
@@ -72,8 +76,8 @@ public class TestTopDocsCollector extends LuceneTestCase {
     }
     
     @Override
-    public boolean needsScores() {
-      return false;
+    public ScoreMode scoreMode() {
+      return ScoreMode.COMPLETE_NO_SCORES;
     }
 
   }
@@ -207,5 +211,199 @@ public class TestTopDocsCollector extends LuceneTestCase {
       assertTrue(sd[i - 1].score >= sd[i].score);
     }
   }
-  
+
+  private static class FakeScorer extends Scorer {
+    int doc = -1;
+    float score;
+    Float minCompetitiveScore = null;
+
+    FakeScorer() {
+      super(null);
+    }
+
+    @Override
+    public void setMinCompetitiveScore(float minCompetitiveScore) {
+      this.minCompetitiveScore = minCompetitiveScore;
+    }
+
+    @Override
+    public int docID() {
+      return doc;
+    }
+
+    @Override
+    public float score() throws IOException {
+      return score;
+    }
+
+    @Override
+    public float maxScore() {
+      return Float.POSITIVE_INFINITY;
+    }
+
+    @Override
+    public DocIdSetIterator iterator() {
+      throw new UnsupportedOperationException();
+    }
+  }
+
+  public void testSetMinCompetitiveScore() throws Exception {
+    Directory dir = newDirectory();
+    IndexWriter w = new IndexWriter(dir, newIndexWriterConfig().setMergePolicy(NoMergePolicy.INSTANCE));
+    Document doc = new Document();
+    w.addDocuments(Arrays.asList(doc, doc, doc, doc));
+    w.flush();
+    w.addDocuments(Arrays.asList(doc, doc));
+    w.flush();
+    IndexReader reader = DirectoryReader.open(w);
+    assertEquals(2, reader.leaves().size());
+    w.close();
+
+    TopScoreDocCollector collector = TopScoreDocCollector.create(2, null, false);
+    FakeScorer scorer = new FakeScorer();
+
+    LeafCollector leafCollector = collector.getLeafCollector(reader.leaves().get(0));
+    leafCollector.setScorer(scorer);
+    assertNull(scorer.minCompetitiveScore);
+
+    scorer.doc = 0;
+    scorer.score = 1;
+    leafCollector.collect(0);
+    assertNull(scorer.minCompetitiveScore);
+
+    scorer.doc = 1;
+    scorer.score = 2;
+    leafCollector.collect(1);
+    assertEquals(Math.nextUp(1f), scorer.minCompetitiveScore, 0f);
+
+    scorer.doc = 2;
+    scorer.score = 0.5f;
+    // Make sure we do not call setMinCompetitiveScore for non-competitive hits
+    scorer.minCompetitiveScore = Float.NaN;
+    leafCollector.collect(2);
+    assertTrue(Float.isNaN(scorer.minCompetitiveScore));
+
+    scorer.doc = 3;
+    scorer.score = 4;
+    leafCollector.collect(3);
+    assertEquals(Math.nextUp(2f), scorer.minCompetitiveScore, 0f);
+
+    // Make sure the min score is set on scorers on new segments
+    scorer = new FakeScorer();
+    leafCollector = collector.getLeafCollector(reader.leaves().get(1));
+    leafCollector.setScorer(scorer);
+    assertEquals(Math.nextUp(2f), scorer.minCompetitiveScore, 0f);
+
+    scorer.doc = 0;
+    scorer.score = 1;
+    leafCollector.collect(0);
+    assertEquals(Math.nextUp(2f), scorer.minCompetitiveScore, 0f);
+
+    scorer.doc = 1;
+    scorer.score = 3;
+    leafCollector.collect(1);
+    assertEquals(Math.nextUp(3f), scorer.minCompetitiveScore, 0f);
+
+    reader.close();
+    dir.close();
+  }
+
+  public void testEstimateHitCount() throws Exception {
+    Directory dir = newDirectory();
+    IndexWriter w = new IndexWriter(dir, newIndexWriterConfig().setMergePolicy(NoMergePolicy.INSTANCE));
+    Document doc = new Document();
+    w.addDocuments(Arrays.asList(doc, doc, doc, doc));
+    w.flush();
+    w.addDocuments(Arrays.asList(doc, doc, doc, doc, doc, doc));
+    w.flush();
+    IndexReader reader = DirectoryReader.open(w);
+    assertEquals(2, reader.leaves().size());
+    w.close();
+
+    TopScoreDocCollector collector = TopScoreDocCollector.create(2, null, false);
+    FakeScorer scorer = new FakeScorer();
+
+    LeafCollector leafCollector = collector.getLeafCollector(reader.leaves().get(0));
+    leafCollector.setScorer(scorer);
+
+    scorer.doc = 0;
+    scorer.score = 3;
+    leafCollector.collect(0);
+
+    scorer.doc = 1;
+    scorer.score = 3;
+    leafCollector.collect(1);
+
+    leafCollector = collector.getLeafCollector(reader.leaves().get(1));
+    leafCollector.setScorer(scorer);
+
+    scorer.doc = 1;
+    scorer.score = 3;
+    leafCollector.collect(1);
+
+    TopDocs topDocs = collector.topDocs();
+    // It assumes all docs matched since numHits was 2 and the first 2 collected docs matched
+    assertEquals(10, topDocs.totalHits);
+
+    // Now test an index that is more sparsely collected
+    collector = TopScoreDocCollector.create(2, null, false);
+
+    leafCollector = collector.getLeafCollector(reader.leaves().get(0));
+    leafCollector.setScorer(scorer);
+
+    scorer.doc = 1;
+    scorer.score = 3;
+    leafCollector.collect(1);
+
+    leafCollector = collector.getLeafCollector(reader.leaves().get(1));
+    leafCollector.setScorer(scorer);
+
+    scorer.doc = 0;
+    scorer.score = 2;
+    leafCollector.collect(0);
+
+    scorer.doc = 2;
+    scorer.score = 5;
+    leafCollector.collect(2);
+
+    topDocs = collector.topDocs();
+    assertEquals(4, topDocs.totalHits);
+
+    // Same 2 first collected docs, but then we collect more docs to make sure
+    // that we use the actual number of collected docs as a lower bound
+    collector = TopScoreDocCollector.create(2, null, false);
+
+    leafCollector = collector.getLeafCollector(reader.leaves().get(0));
+    leafCollector.setScorer(scorer);
+
+    scorer.doc = 1;
+    scorer.score = 3;
+    leafCollector.collect(1);
+
+    leafCollector = collector.getLeafCollector(reader.leaves().get(1));
+    leafCollector.setScorer(scorer);
+
+    scorer.doc = 0;
+    scorer.score = 2;
+    leafCollector.collect(0);
+
+    scorer.doc = 2;
+    scorer.score = 5;
+    leafCollector.collect(2);
+
+    scorer.doc = 3;
+    scorer.score = 4;
+    leafCollector.collect(3);
+
+    scorer.doc = 4;
+    scorer.score = 1;
+    leafCollector.collect(4);
+
+    topDocs = collector.topDocs();
+    assertEquals(5, topDocs.totalHits);
+
+    reader.close();
+    dir.close();
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/search/TestTopDocsMerge.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestTopDocsMerge.java b/lucene/core/src/test/org/apache/lucene/search/TestTopDocsMerge.java
index 9759863..ccc8eb6 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestTopDocsMerge.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestTopDocsMerge.java
@@ -316,7 +316,7 @@ public class TestTopDocsMerge extends LuceneTestCase {
       }
 
       // ... then all shards:
-      final Weight w = searcher.createNormalizedWeight(query, true);
+      final Weight w = searcher.createNormalizedWeight(query, ScoreMode.COMPLETE);
 
       final TopDocs[] shardHits;
       if (sort == null) {
@@ -377,4 +377,5 @@ public class TestTopDocsMerge extends LuceneTestCase {
     reader.close();
     dir.close();
   }
+
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/search/TestTopFieldCollector.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestTopFieldCollector.java b/lucene/core/src/test/org/apache/lucene/search/TestTopFieldCollector.java
index d9be584..0b7dc5b 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestTopFieldCollector.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestTopFieldCollector.java
@@ -226,6 +226,11 @@ public class TestTopFieldCollector extends LuceneTestCase {
                     }
 
                     @Override
+                    public float maxScore() {
+                      return scorer.maxScore();
+                    }
+
+                    @Override
                     public int docID() {
                       return scorer.docID();
                     }
@@ -241,8 +246,8 @@ public class TestTopFieldCollector extends LuceneTestCase {
               };
             }
             @Override
-            public boolean needsScores() {
-              return topCollector.needsScores();
+            public ScoreMode scoreMode() {
+              return topCollector.scoreMode();
             }
           };
           searcher.search(query, assertingCollector);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a872/lucene/core/src/test/org/apache/lucene/search/TestUsageTrackingFilterCachingPolicy.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestUsageTrackingFilterCachingPolicy.java b/lucene/core/src/test/org/apache/lucene/search/TestUsageTrackingFilterCachingPolicy.java
index f6e75c2..670df77 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestUsageTrackingFilterCachingPolicy.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestUsageTrackingFilterCachingPolicy.java
@@ -118,7 +118,7 @@ public class TestUsageTrackingFilterCachingPolicy extends LuceneTestCase {
     }
 
     @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(DummyQuery.this, boost) {
         @Override
         public Scorer scorer(LeafReaderContext context) throws IOException {