1818
1919import java .io .IOException ;
2020import java .lang .invoke .MethodHandles ;
21+ import java .util .function .DoubleBinaryOperator ;
22+ import org .apache .lucene .queries .function .FunctionQuery ;
23+ import org .apache .lucene .queries .function .FunctionScoreQuery ;
24+ import org .apache .lucene .search .DoubleValuesSource ;
25+ import org .apache .lucene .search .DoubleValuesSourceRescorer ;
2126import org .apache .lucene .search .MatchAllDocsQuery ;
2227import org .apache .lucene .search .Query ;
2328import org .apache .lucene .search .QueryRescorer ;
29+ import org .apache .lucene .search .Rescorer ;
2430import org .apache .solr .common .SolrException ;
2531import org .apache .solr .common .params .CommonParams ;
2632import org .apache .solr .common .params .SolrParams ;
@@ -63,6 +69,26 @@ public QParser createParser(
6369 return new ReRankQParser (query , localParams , params , req );
6470 }
6571
72+ /**
73+ * Helper method for constructing a {@link Rescorer} from a {@link #RERANK_QUERY}, {@link
74+ * #RERANK_WEIGHT}, and {@link #RERANK_OPERATOR}.
75+ *
76+ * <p>By default, this returns a customized {@link QueryRescorer}, unless the {@link
77+ * #RERANK_QUERY} is a known type that can more efficiently be re-ranked using a customized {@link
78+ * DoubleValuesSourceRescorer}.
79+ */
80+ private static Rescorer createRescorer (
81+ final Query reRankQuery , final double reRankWeight , final ReRankOperator reRankOperator ) {
82+ assert null != reRankQuery ;
83+ return switch (reRankQuery ) {
84+ case FunctionQuery functionQuery -> new ReRankDoubleValuesSourceRescorer (
85+ functionQuery .getValueSource ().asDoubleValuesSource (), reRankWeight , reRankOperator );
86+ case FunctionScoreQuery functionQuery -> new ReRankDoubleValuesSourceRescorer (
87+ functionQuery .getSource (), reRankWeight , reRankOperator );
88+ default -> new ReRankQueryRescorer (reRankQuery , reRankWeight , reRankOperator );
89+ };
90+ }
91+
6692 private static class ReRankQParser extends QParser {
6793
6894 private boolean isExplainResults () {
@@ -135,7 +161,7 @@ public Query parse() throws SyntaxError {
135161 reRankScale ,
136162 reRankScaleWeight ,
137163 reRankOperator ,
138- new ReRankQueryRescorer (reRankQuery , 1 , ReRankOperator .REPLACE ),
164+ createRescorer (reRankQuery , 1 , ReRankOperator .REPLACE ),
139165 explainResults );
140166
141167 if (reRankScaler .scaleScores ()) {
@@ -148,6 +174,28 @@ public Query parse() throws SyntaxError {
148174 }
149175 }
150176
177+ private static final class ReRankDoubleValuesSourceRescorer extends DoubleValuesSourceRescorer {
178+ final DoubleBinaryOperator scoreCombiner ;
179+
180+ public ReRankDoubleValuesSourceRescorer (
181+ final DoubleValuesSource valuesSource ,
182+ final double reRankWeight ,
183+ final ReRankOperator reRankOperator ) {
184+ super (valuesSource );
185+ this .scoreCombiner =
186+ (score , value ) -> reRankOperator .applyAsDouble (score , reRankWeight * value );
187+ }
188+
189+ @ Override
190+ protected float combine (
191+ final float firstPassScore , final boolean valuePresent , final double sourceValue ) {
192+ if (valuePresent ) {
193+ return (float ) scoreCombiner .applyAsDouble (firstPassScore , sourceValue );
194+ }
195+ return firstPassScore ;
196+ }
197+ }
198+
151199 private static final class ReRankQueryRescorer extends QueryRescorer {
152200
153201 final BiFloatFunction scoreCombiner ;
@@ -160,20 +208,8 @@ interface BiFloatFunction {
160208 public ReRankQueryRescorer (
161209 Query reRankQuery , double reRankWeight , ReRankOperator reRankOperator ) {
162210 super (reRankQuery );
163- switch (reRankOperator ) {
164- case ADD :
165- scoreCombiner = (score , second ) -> (float ) (score + reRankWeight * second );
166- break ;
167- case MULTIPLY :
168- scoreCombiner = (score , second ) -> (float ) (score * reRankWeight * second );
169- break ;
170- case REPLACE :
171- scoreCombiner = (score , second ) -> (float ) (reRankWeight * second );
172- break ;
173- default :
174- scoreCombiner = null ;
175- throw new IllegalArgumentException ("Unexpected: reRankOperator=" + reRankOperator );
176- }
211+ scoreCombiner =
212+ (score , second ) -> (float ) reRankOperator .applyAsDouble (score , reRankWeight * second );
177213 }
178214
179215 @ Override
@@ -226,7 +262,7 @@ public ReRankQuery(
226262 super (
227263 defaultQuery ,
228264 reRankDocs ,
229- new ReRankQueryRescorer (reRankQuery , reRankWeight , reRankOperator ),
265+ createRescorer (reRankQuery , reRankWeight , reRankOperator ),
230266 reRankScaler ,
231267 reRankOperator );
232268 this .reRankQuery = reRankQuery ;
0 commit comments