1 package org.apache.lucene.search.function;
4 * Licensed to the Apache Software Foundation (ASF) under one or more
5 * contributor license agreements. See the NOTICE file distributed with
6 * this work for additional information regarding copyright ownership.
7 * The ASF licenses this file to You under the Apache License, Version 2.0
8 * (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
20 import java.io.IOException;
22 import org.apache.lucene.index.IndexReader;
23 import org.apache.lucene.search.Explanation;
24 import org.apache.lucene.search.FieldCache; // for javadocs
27 * An instance of this subclass should be returned by
28 * {@link CustomScoreQuery#getCustomScoreProvider}, if you want
29 * to modify the custom score calculation of a {@link CustomScoreQuery}.
30 * <p>Since Lucene 2.9, queries operate on each segment of an index separately,
31 * so the protected {@link #reader} field can be used to resolve doc IDs,
32 * as the supplied <code>doc</code> ID is per-segment and without knowledge
33 * of the IndexReader you cannot access the document or {@link FieldCache}.
35 * @lucene.experimental
38 public class CustomScoreProvider {
40 protected final IndexReader reader;
43 * Creates a new instance of the provider class for the given {@link IndexReader}.
45 public CustomScoreProvider(IndexReader reader) {
50 * Compute a custom score by the subQuery score and a number of
51 * {@link ValueSourceQuery} scores.
53 * Subclasses can override this method to modify the custom score.
55 * If your custom scoring is different than the default herein you
56 * should override at least one of the two customScore() methods.
57 * If the number of ValueSourceQueries is always < 2 it is
58 * sufficient to override the other
59 * {@link #customScore(int, float, float) customScore()}
60 * method, which is simpler.
62 * The default computation herein is a multiplication of given scores:
64 * ModifiedScore = valSrcScore * valSrcScores[0] * valSrcScores[1] * ...
67 * @param doc id of scored doc.
68 * @param subQueryScore score of that doc by the subQuery.
69 * @param valSrcScores scores of that doc by the ValueSourceQuery.
70 * @return custom score.
72 public float customScore(int doc, float subQueryScore, float valSrcScores[]) throws IOException {
73 if (valSrcScores.length == 1) {
74 return customScore(doc, subQueryScore, valSrcScores[0]);
76 if (valSrcScores.length == 0) {
77 return customScore(doc, subQueryScore, 1);
79 float score = subQueryScore;
80 for(int i = 0; i < valSrcScores.length; i++) {
81 score *= valSrcScores[i];
87 * Compute a custom score by the subQuery score and the ValueSourceQuery score.
89 * Subclasses can override this method to modify the custom score.
91 * If your custom scoring is different than the default herein you
92 * should override at least one of the two customScore() methods.
93 * If the number of ValueSourceQueries is always < 2 it is
94 * sufficient to override this customScore() method, which is simpler.
96 * The default computation herein is a multiplication of the two scores:
98 * ModifiedScore = subQueryScore * valSrcScore
101 * @param doc id of scored doc.
102 * @param subQueryScore score of that doc by the subQuery.
103 * @param valSrcScore score of that doc by the ValueSourceQuery.
104 * @return custom score.
106 public float customScore(int doc, float subQueryScore, float valSrcScore) throws IOException {
107 return subQueryScore * valSrcScore;
111 * Explain the custom score.
112 * Whenever overriding {@link #customScore(int, float, float[])},
113 * this method should also be overridden to provide the correct explanation
114 * for the part of the custom scoring.
116 * @param doc doc being explained.
117 * @param subQueryExpl explanation for the sub-query part.
118 * @param valSrcExpls explanation for the value source part.
119 * @return an explanation for the custom score
121 public Explanation customExplain(int doc, Explanation subQueryExpl, Explanation valSrcExpls[]) throws IOException {
122 if (valSrcExpls.length == 1) {
123 return customExplain(doc, subQueryExpl, valSrcExpls[0]);
125 if (valSrcExpls.length == 0) {
128 float valSrcScore = 1;
129 for (int i = 0; i < valSrcExpls.length; i++) {
130 valSrcScore *= valSrcExpls[i].getValue();
132 Explanation exp = new Explanation( valSrcScore * subQueryExpl.getValue(), "custom score: product of:");
133 exp.addDetail(subQueryExpl);
134 for (int i = 0; i < valSrcExpls.length; i++) {
135 exp.addDetail(valSrcExpls[i]);
141 * Explain the custom score.
142 * Whenever overriding {@link #customScore(int, float, float)},
143 * this method should also be overridden to provide the correct explanation
144 * for the part of the custom scoring.
146 * @param doc doc being explained.
147 * @param subQueryExpl explanation for the sub-query part.
148 * @param valSrcExpl explanation for the value source part.
149 * @return an explanation for the custom score
151 public Explanation customExplain(int doc, Explanation subQueryExpl, Explanation valSrcExpl) throws IOException {
152 float valSrcScore = 1;
153 if (valSrcExpl != null) {
154 valSrcScore *= valSrcExpl.getValue();
156 Explanation exp = new Explanation( valSrcScore * subQueryExpl.getValue(), "custom score: product of:");
157 exp.addDetail(subQueryExpl);
158 exp.addDetail(valSrcExpl);