@@ -87,18 +87,64 @@ public int score(LeafCollector collector, Bits acceptDocs, int min, int max) thr
87
87
// NOTE: windowMax is inclusive
88
88
int windowMax = Math .min (scorers [0 ].advanceShallow (windowMin ), max - 1 );
89
89
90
- float maxWindowScore = Float .POSITIVE_INFINITY ;
91
90
if (0 < scorable .minCompetitiveScore ) {
92
- maxWindowScore = computeMaxScore (windowMin , windowMax );
91
+ float maxWindowScore = computeMaxScore (windowMin , windowMax );
92
+ scoreWindowScoreFirst (collector , acceptDocs , windowMin , windowMax + 1 , maxWindowScore );
93
+ } else {
94
+ scoreWindowDocFirst (collector , acceptDocs , windowMin , windowMax + 1 );
93
95
}
94
- scoreWindow (collector , acceptDocs , windowMin , windowMax + 1 , maxWindowScore );
95
96
windowMin = Math .max (lead .docID (), windowMax + 1 );
96
97
}
97
98
98
99
return windowMin >= maxDoc ? DocIdSetIterator .NO_MORE_DOCS : windowMin ;
99
100
}
100
101
101
- private void scoreWindow (
102
+ /**
103
+ * Score a window of doc IDs by first finding agreement between all iterators, and only then
104
+ * compute scores and call the collector.
105
+ */
106
+ private void scoreWindowDocFirst (LeafCollector collector , Bits acceptDocs , int min , int max )
107
+ throws IOException {
108
+ int doc = lead .docID ();
109
+ if (doc < min ) {
110
+ doc = lead .advance (min );
111
+ }
112
+
113
+ outer :
114
+ while (doc < max ) {
115
+ if (acceptDocs == null || acceptDocs .get (doc )) {
116
+ for (int i = 1 ; i < iterators .length ; ++i ) {
117
+ DocIdSetIterator iterator = iterators [i ];
118
+ int otherDoc = iterator .docID ();
119
+ if (otherDoc < doc ) {
120
+ otherDoc = iterator .advance (doc );
121
+ }
122
+ if (doc != otherDoc ) {
123
+ doc = lead .advance (otherDoc );
124
+ continue outer ;
125
+ }
126
+ }
127
+
128
+ double score = 0 ;
129
+ for (Scorable scorable : scorables ) {
130
+ score += scorable .score ();
131
+ }
132
+ scorable .score = (float ) score ;
133
+ collector .collect (doc );
134
+ }
135
+ doc = lead .nextDoc ();
136
+ }
137
+ }
138
+
139
+ /**
140
+ * Score a window of doc IDs by computing matches and scores on the lead costly clause, then
141
+ * iterate other clauses one by one to remove documents that do not match and increase the global
142
+ * score by the score of the current clause. This is often faster when a minimum competitive score
143
+ * is set, as score computations can be more efficient (e.g. thanks to vectorization) and because
144
+ * we can skip advancing other clauses if the global score so far is not high enough for a doc to
145
+ * have a chance of being competitive.
146
+ */
147
+ private void scoreWindowScoreFirst (
102
148
LeafCollector collector , Bits acceptDocs , int min , int max , float maxWindowScore )
103
149
throws IOException {
104
150
if (maxWindowScore < scorable .minCompetitiveScore ) {
@@ -120,13 +166,11 @@ private void scoreWindow(
120
166
docAndScoreAccBuffer .copyFrom (docAndScoreBuffer );
121
167
122
168
for (int i = 1 ; i < scorers .length ; ++i ) {
123
- if (scorable .minCompetitiveScore > 0 ) {
124
- ScorerUtil .filterCompetitiveHits (
125
- docAndScoreAccBuffer ,
126
- sumOfOtherClauses [i ],
127
- scorable .minCompetitiveScore ,
128
- scorers .length );
129
- }
169
+ ScorerUtil .filterCompetitiveHits (
170
+ docAndScoreAccBuffer ,
171
+ sumOfOtherClauses [i ],
172
+ scorable .minCompetitiveScore ,
173
+ scorers .length );
130
174
131
175
ScorerUtil .applyRequiredClause (docAndScoreAccBuffer , iterators [i ], scorables [i ]);
132
176
}
0 commit comments