1212import org .apache .lucene .analysis .Analyzer ;
1313import org .apache .lucene .index .FieldInvertState ;
1414import org .apache .lucene .index .LeafReaderContext ;
15+ import org .apache .lucene .index .NumericDocValues ;
1516import org .apache .lucene .index .Term ;
1617import org .apache .lucene .index .TermStates ;
1718import org .apache .lucene .index .memory .MemoryIndex ;
2324import org .apache .lucene .search .DocIdSetIterator ;
2425import org .apache .lucene .search .Explanation ;
2526import org .apache .lucene .search .IndexSearcher ;
26- import org .apache .lucene .search .LeafSimScorer ;
2727import org .apache .lucene .search .MatchAllDocsQuery ;
2828import org .apache .lucene .search .MatchNoDocsQuery ;
2929import org .apache .lucene .search .Matches ;
@@ -214,7 +214,6 @@ public Weight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float bo
214214 // No need to ever look at the _source for non-scoring term queries
215215 return in .createWeight (searcher , scoreMode , boost );
216216 }
217-
218217 // We use a LinkedHashSet here to preserve the ordering of terms to ensure that
219218 // later summing of float scores per term is consistent
220219 final Set <Term > terms = new LinkedHashSet <>();
@@ -267,6 +266,7 @@ public boolean isCacheable(LeafReaderContext ctx) {
267266
268267 @ Override
269268 public Explanation explain (LeafReaderContext context , int doc ) throws IOException {
269+ NumericDocValues norms = context .reader ().getNormValues (field );
270270 RuntimePhraseScorer scorer = (RuntimePhraseScorer ) scorerSupplier (context ).get (0 );
271271 if (scorer == null ) {
272272 return Explanation .noMatch ("No matching phrase" );
@@ -277,8 +277,7 @@ public Explanation explain(LeafReaderContext context, int doc) throws IOExceptio
277277 }
278278 float phraseFreq = scorer .freq ();
279279 Explanation freqExplanation = Explanation .match (phraseFreq , "phraseFreq=" + phraseFreq );
280- final LeafSimScorer leafSimScorer = new LeafSimScorer (simScorer , context .reader (), field , scoreMode .needsScores ());
281- Explanation scoreExplanation = leafSimScorer .explain (doc , freqExplanation );
280+ Explanation scoreExplanation = simScorer .explain (freqExplanation , getNormValue (norms , doc ));
282281 return Explanation .match (
283282 scoreExplanation .getValue (),
284283 "weight(" + getQuery () + " in " + doc + ") [" + searcher .getSimilarity ().getClass ().getSimpleName () + "], result of:" ,
@@ -297,9 +296,9 @@ public ScorerSupplier scorerSupplier(LeafReaderContext context) throws IOExcepti
297296 public Scorer get (long leadCost ) throws IOException {
298297 final Scorer approximationScorer = approximationSupplier .get (leadCost );
299298 final DocIdSetIterator approximation = approximationScorer .iterator ();
300- final LeafSimScorer leafSimScorer = new LeafSimScorer (simScorer , context .reader (), field , scoreMode .needsScores ());
301299 final CheckedIntFunction <List <Object >, IOException > valueFetcher = valueFetcherProvider .apply (context );
302- return new RuntimePhraseScorer (approximation , leafSimScorer , valueFetcher , field , in );
300+ NumericDocValues norms = context .reader ().getNormValues (field );
301+ return new RuntimePhraseScorer (approximation , simScorer , norms , valueFetcher , field , in );
303302 }
304303
305304 @ Override
@@ -335,12 +334,23 @@ public Matches matches(LeafReaderContext context, int doc) throws IOException {
335334 };
336335 }
337336
337+ private static long getNormValue (NumericDocValues norms , int doc ) throws IOException {
338+ if (norms != null ) {
339+ boolean found = norms .advanceExact (doc );
340+ assert found ;
341+ return norms .longValue ();
342+ } else {
343+ return 1L ; // default norm
344+ }
345+ }
346+
338347 private class RuntimePhraseScorer extends Scorer {
339- private final LeafSimScorer scorer ;
348+ private final SimScorer scorer ;
340349 private final CheckedIntFunction <List <Object >, IOException > valueFetcher ;
341350 private final String field ;
342351 private final Query query ;
343352 private final TwoPhaseIterator twoPhase ;
353+ private final NumericDocValues norms ;
344354
345355 private final MemoryIndexEntry cacheEntry = new MemoryIndexEntry ();
346356
@@ -349,12 +359,14 @@ private class RuntimePhraseScorer extends Scorer {
349359
350360 private RuntimePhraseScorer (
351361 DocIdSetIterator approximation ,
352- LeafSimScorer scorer ,
362+ SimScorer scorer ,
363+ NumericDocValues norms ,
353364 CheckedIntFunction <List <Object >, IOException > valueFetcher ,
354365 String field ,
355366 Query query
356367 ) {
357368 this .scorer = scorer ;
369+ this .norms = norms ;
358370 this .valueFetcher = valueFetcher ;
359371 this .field = field ;
360372 this .query = query ;
@@ -386,12 +398,12 @@ public TwoPhaseIterator twoPhaseIterator() {
386398
387399 @ Override
388400 public float getMaxScore (int upTo ) throws IOException {
389- return scorer .getSimScorer (). score (Float .MAX_VALUE , 1L );
401+ return scorer .score (Float .MAX_VALUE , 1L );
390402 }
391403
392404 @ Override
393405 public float score () throws IOException {
394- return scorer .score (docID (), freq ( ));
406+ return scorer .score (freq (), getNormValue ( norms , doc ));
395407 }
396408
397409 @ Override
0 commit comments