You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-commits@lucene.apache.org by us...@apache.org on 2010/02/21 19:27:06 UTC
svn commit: r912386 - in /lucene/java/trunk: ./
contrib/spatial/src/test/org/apache/lucene/spatial/tier/
src/java/org/apache/lucene/search/function/
src/test/org/apache/lucene/search/function/
Author: uschindler
Date: Sun Feb 21 18:27:05 2010
New Revision: 912386
URL: http://svn.apache.org/viewvc?rev=912386&view=rev
Log:
LUCENE-2190: Added a new class CustomScoreProvider to function package that can be subclassed to provide custom scoring to CustomScoreQuery
Added:
lucene/java/trunk/src/java/org/apache/lucene/search/function/CustomScoreProvider.java (with props)
Modified:
lucene/java/trunk/CHANGES.txt
lucene/java/trunk/common-build.xml
lucene/java/trunk/contrib/spatial/src/test/org/apache/lucene/spatial/tier/TestCartesian.java
lucene/java/trunk/src/java/org/apache/lucene/search/function/CustomScoreQuery.java
lucene/java/trunk/src/test/org/apache/lucene/search/function/TestCustomScoreQuery.java
Modified: lucene/java/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/java/trunk/CHANGES.txt?rev=912386&r1=912385&r2=912386&view=diff
==============================================================================
--- lucene/java/trunk/CHANGES.txt (original)
+++ lucene/java/trunk/CHANGES.txt Sun Feb 21 18:27:05 2010
@@ -20,6 +20,9 @@
toString. These are advanced APIs and subject to change suddenly.
(Tim Smith via Mike McCandless)
+* LUCENE-2190: Removed deprecated customScore() and customExplain()
+ methods from experimental CustomScoreQuery. (Uwe Schindler)
+
Changes in runtime behavior
* LUCENE-1923: Made IndexReader.toString() produce something
@@ -259,10 +262,16 @@
* LUCENE-1972 (3.0.1 only): Restore SortField.getComparatorSource
(it was accidentally removed in 3.0.0) (John Wang via Uwe Schindler)
- * LUCENE-2190: Added setNextReader method to CustomScoreQuery, which
- is necessary with per-segment searching to notify the subclass
- which reader the int doc, passed to customScore, refers to. (Paul
- chez Jamespot via Mike McCandless)
+ * LUCENE-2190: Added a new class CustomScoreProvider to function package
+ that can be subclassed to provide custom scoring to CustomScoreQuery.
+ The methods in CustomScoreQuery that did this before were deprecated
+ and replaced by a method getCustomScoreProvider(IndexReader) that
+ returns a custom score implementation using the above class. The change
+ is necessary with per-segment searching, as CustomScoreQuery is
+ a stateless class (like all other Queries) and does not know about
+ the currently searched segment. This API works similar to Filter's
+ getDocIdSet(IndexReader). (Paul chez Jamespot via Mike McCandless,
+ Uwe Schindler)
* LUCENE-2080: Deprecate Version.LUCENE_CURRENT, as using this constant
will cause backwards compatibility problems when upgrading Lucene. See
Modified: lucene/java/trunk/common-build.xml
URL: http://svn.apache.org/viewvc/lucene/java/trunk/common-build.xml?rev=912386&r1=912385&r2=912386&view=diff
==============================================================================
--- lucene/java/trunk/common-build.xml (original)
+++ lucene/java/trunk/common-build.xml Sun Feb 21 18:27:05 2010
@@ -43,7 +43,7 @@
<property name="dev.version" value="3.1-dev"/>
<property name="version" value="${dev.version}"/>
<property name="backwards.branch" value="lucene_3_0_back_compat_tests"/>
- <property name="backwards.rev" value="912375"/>
+ <property name="backwards.rev" value="912385"/>
<property name="spec.version" value="${version}"/>
<property name="year" value="2000-${current.year}"/>
<property name="final.name" value="lucene-${name}-${version}"/>
Modified: lucene/java/trunk/contrib/spatial/src/test/org/apache/lucene/spatial/tier/TestCartesian.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/contrib/spatial/src/test/org/apache/lucene/spatial/tier/TestCartesian.java?rev=912386&r1=912385&r2=912386&view=diff
==============================================================================
--- lucene/java/trunk/contrib/spatial/src/test/org/apache/lucene/spatial/tier/TestCartesian.java (original)
+++ lucene/java/trunk/contrib/spatial/src/test/org/apache/lucene/spatial/tier/TestCartesian.java Sun Feb 21 18:27:05 2010
@@ -27,6 +27,7 @@
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
@@ -36,6 +37,7 @@
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.function.CustomScoreQuery;
+import org.apache.lucene.search.function.CustomScoreProvider;
import org.apache.lucene.search.function.FieldScoreQuery;
import org.apache.lucene.search.function.FieldScoreQuery.Type;
import org.apache.lucene.spatial.geohash.GeoHashUtils;
@@ -189,20 +191,26 @@
CustomScoreQuery customScore = new CustomScoreQuery(dq.getQuery(tq),fsQuery){
@Override
- public float customScore(int doc, float subQueryScore, float valSrcScore){
- System.out.println(doc);
- if (dq.distanceFilter.getDistance(doc) == null)
- return 0;
-
- double distance = dq.distanceFilter.getDistance(doc);
- // boost score shouldn't exceed 1
- if (distance < 1.0d)
- distance = 1.0d;
- //boost by distance is invertly proportional to
- // to distance from center point to location
- float score = (float) ((miles - distance) / miles );
- return score * subQueryScore;
+ protected CustomScoreProvider getCustomScoreProvider(IndexReader reader) {
+ return new CustomScoreProvider(reader) {
+ @Override // TODO: broken, as reader is not used!
+ public float customScore(int doc, float subQueryScore, float valSrcScore){
+ System.out.println(doc);
+ if (dq.distanceFilter.getDistance(doc) == null)
+ return 0;
+
+ double distance = dq.distanceFilter.getDistance(doc);
+ // boost score shouldn't exceed 1
+ if (distance < 1.0d)
+ distance = 1.0d;
+ //boost by distance is invertly proportional to
+ // to distance from center point to location
+ float score = (float) ((miles - distance) / miles );
+ return score * subQueryScore;
+ }
+ };
}
+
};
// Create a distance sort
// As the radius filter has performed the distance calculations
@@ -276,20 +284,26 @@
CustomScoreQuery customScore = new CustomScoreQuery(dq.getQuery(tq),fsQuery){
@Override
- public float customScore(int doc, float subQueryScore, float valSrcScore){
- System.out.println(doc);
- if (dq.distanceFilter.getDistance(doc) == null)
- return 0;
-
- double distance = dq.distanceFilter.getDistance(doc);
- // boost score shouldn't exceed 1
- if (distance < 1.0d)
- distance = 1.0d;
- //boost by distance is invertly proportional to
- // to distance from center point to location
- float score = (float) ((miles - distance) / miles );
- return score * subQueryScore;
+ protected CustomScoreProvider getCustomScoreProvider(IndexReader reader) {
+ return new CustomScoreProvider(reader) {
+ @Override // TODO: broken, as reader is not used!
+ public float customScore(int doc, float subQueryScore, float valSrcScore){
+ System.out.println(doc);
+ if (dq.distanceFilter.getDistance(doc) == null)
+ return 0;
+
+ double distance = dq.distanceFilter.getDistance(doc);
+ // boost score shouldn't exceed 1
+ if (distance < 1.0d)
+ distance = 1.0d;
+ //boost by distance is invertly proportional to
+ // to distance from center point to location
+ float score = (float) ((miles - distance) / miles );
+ return score * subQueryScore;
+ }
+ };
}
+
};
// Create a distance sort
// As the radius filter has performed the distance calculations
@@ -363,23 +377,27 @@
FieldScoreQuery fsQuery = new FieldScoreQuery("geo_distance", Type.FLOAT);
CustomScoreQuery customScore = new CustomScoreQuery(dq.getQuery(tq),fsQuery){
-
- @Override
+ @Override
+ protected CustomScoreProvider getCustomScoreProvider(IndexReader reader) {
+ return new CustomScoreProvider(reader) {
+ @Override // TODO: broken, as reader is not used!
public float customScore(int doc, float subQueryScore, float valSrcScore){
- //System.out.println(doc);
- if (dq.distanceFilter.getDistance(doc) == null)
- return 0;
-
- double distance = dq.distanceFilter.getDistance(doc);
- // boost score shouldn't exceed 1
- if (distance < 1.0d)
- distance = 1.0d;
- //boost by distance is invertly proportional to
- // to distance from center point to location
- float score = (float) ( (miles - distance) / miles );
- return score * subQueryScore;
- }
- };
+ //System.out.println(doc);
+ if (dq.distanceFilter.getDistance(doc) == null)
+ return 0;
+
+ double distance = dq.distanceFilter.getDistance(doc);
+ // boost score shouldn't exceed 1
+ if (distance < 1.0d)
+ distance = 1.0d;
+ //boost by distance is invertly proportional to
+ // to distance from center point to location
+ float score = (float) ( (miles - distance) / miles );
+ return score * subQueryScore;
+ }
+ };
+ }
+ };
// Create a distance sort
// As the radius filter has performed the distance calculations
// already, pass in the filter to reuse the results.
@@ -452,23 +470,27 @@
FieldScoreQuery fsQuery = new FieldScoreQuery("geo_distance", Type.FLOAT);
CustomScoreQuery customScore = new CustomScoreQuery(tq,fsQuery){
-
- @Override
- public float customScore(int doc, float subQueryScore, float valSrcScore){
- //System.out.println(doc);
- if (dq.distanceFilter.getDistance(doc) == null)
- return 0;
-
- double distance = dq.distanceFilter.getDistance(doc);
- // boost score shouldn't exceed 1
- if (distance < 1.0d)
- distance = 1.0d;
- //boost by distance is invertly proportional to
- // to distance from center point to location
- float score = (float) ( (miles - distance) / miles );
- return score * subQueryScore;
- }
- };
+ @Override
+ protected CustomScoreProvider getCustomScoreProvider(IndexReader reader) {
+ return new CustomScoreProvider(reader) {
+ @Override // TODO: broken, as reader is not used!
+ public float customScore(int doc, float subQueryScore, float valSrcScore){
+ //System.out.println(doc);
+ if (dq.distanceFilter.getDistance(doc) == null)
+ return 0;
+
+ double distance = dq.distanceFilter.getDistance(doc);
+ // boost score shouldn't exceed 1
+ if (distance < 1.0d)
+ distance = 1.0d;
+ //boost by distance is invertly proportional to
+ // to distance from center point to location
+ float score = (float) ( (miles - distance) / miles );
+ return score * subQueryScore;
+ }
+ };
+ }
+ };
// Create a distance sort
// As the radius filter has performed the distance calculations
// already, pass in the filter to reuse the results.
Added: lucene/java/trunk/src/java/org/apache/lucene/search/function/CustomScoreProvider.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/function/CustomScoreProvider.java?rev=912386&view=auto
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/function/CustomScoreProvider.java (added)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/function/CustomScoreProvider.java Sun Feb 21 18:27:05 2010
@@ -0,0 +1,163 @@
+package org.apache.lucene.search.function;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.IOException;
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.ComplexExplanation;
+import org.apache.lucene.search.Explanation;
+import org.apache.lucene.search.FieldCache; // for javadocs
+
+/**
+ * An instance of this subclass should be returned by
+ * {@link CustomScoreQuery#getCustomScoreProvider}, if you want
+ * to modify the custom score calculation of a {@link CustomScoreQuery}.
+ * <p>Since Lucene 2.9, queries operate on each segment of an index separately,
+ * so the protected {@link #reader} field can be used to resolve doc IDs,
+ * as the supplied <code>doc</code> ID is per-segment and without knowledge
+ * of the IndexReader you cannot access the document or {@link FieldCache}.
+ *
+ * @lucene.experimental
+ * @since 2.9.2
+ */
+public class CustomScoreProvider {
+
+ protected final IndexReader reader;
+
+ /**
+ * Creates a new instance of the provider class for the given {@link IndexReader}.
+ */
+ public CustomScoreProvider(IndexReader reader) {
+ this.reader = reader;
+ }
+
+ /**
+ * Compute a custom score by the subQuery score and a number of
+ * {@link ValueSourceQuery} scores.
+ * <p>
+ * Subclasses can override this method to modify the custom score.
+ * <p>
+ * If your custom scoring is different than the default herein you
+ * should override at least one of the two customScore() methods.
+ * If the number of ValueSourceQueries is always < 2 it is
+ * sufficient to override the other
+ * {@link #customScore(int, float, float) customScore()}
+ * method, which is simpler.
+ * <p>
+ * The default computation herein is a multiplication of given scores:
+ * <pre>
+ * ModifiedScore = valSrcScore * valSrcScores[0] * valSrcScores[1] * ...
+ * </pre>
+ *
+ * @param doc id of scored doc.
+ * @param subQueryScore score of that doc by the subQuery.
+ * @param valSrcScores scores of that doc by the ValueSourceQuery.
+ * @return custom score.
+ */
+ public float customScore(int doc, float subQueryScore, float valSrcScores[]) throws IOException {
+ if (valSrcScores.length == 1) {
+ return customScore(doc, subQueryScore, valSrcScores[0]);
+ }
+ if (valSrcScores.length == 0) {
+ return customScore(doc, subQueryScore, 1);
+ }
+ float score = subQueryScore;
+ for(int i = 0; i < valSrcScores.length; i++) {
+ score *= valSrcScores[i];
+ }
+ return score;
+ }
+
+ /**
+ * Compute a custom score by the subQuery score and the ValueSourceQuery score.
+ * <p>
+ * Subclasses can override this method to modify the custom score.
+ * <p>
+ * If your custom scoring is different than the default herein you
+ * should override at least one of the two customScore() methods.
+ * If the number of ValueSourceQueries is always < 2 it is
+ * sufficient to override this customScore() method, which is simpler.
+ * <p>
+ * The default computation herein is a multiplication of the two scores:
+ * <pre>
+ * ModifiedScore = subQueryScore * valSrcScore
+ * </pre>
+ *
+ * @param doc id of scored doc.
+ * @param subQueryScore score of that doc by the subQuery.
+ * @param valSrcScore score of that doc by the ValueSourceQuery.
+ * @return custom score.
+ */
+ public float customScore(int doc, float subQueryScore, float valSrcScore) throws IOException {
+ return subQueryScore * valSrcScore;
+ }
+
+ /**
+ * Explain the custom score.
+ * Whenever overriding {@link #customScore(int, float, float[])},
+ * this method should also be overridden to provide the correct explanation
+ * for the part of the custom scoring.
+ *
+ * @param doc doc being explained.
+ * @param subQueryExpl explanation for the sub-query part.
+ * @param valSrcExpls explanation for the value source part.
+ * @return an explanation for the custom score
+ */
+ public Explanation customExplain(int doc, Explanation subQueryExpl, Explanation valSrcExpls[]) throws IOException {
+ if (valSrcExpls.length == 1) {
+ return customExplain(doc, subQueryExpl, valSrcExpls[0]);
+ }
+ if (valSrcExpls.length == 0) {
+ return subQueryExpl;
+ }
+ float valSrcScore = 1;
+ for (int i = 0; i < valSrcExpls.length; i++) {
+ valSrcScore *= valSrcExpls[i].getValue();
+ }
+ Explanation exp = new Explanation( valSrcScore * subQueryExpl.getValue(), "custom score: product of:");
+ exp.addDetail(subQueryExpl);
+ for (int i = 0; i < valSrcExpls.length; i++) {
+ exp.addDetail(valSrcExpls[i]);
+ }
+ return exp;
+ }
+
+ /**
+ * Explain the custom score.
+ * Whenever overriding {@link #customScore(int, float, float)},
+ * this method should also be overridden to provide the correct explanation
+ * for the part of the custom scoring.
+ *
+ * @param doc doc being explained.
+ * @param subQueryExpl explanation for the sub-query part.
+ * @param valSrcExpl explanation for the value source part.
+ * @return an explanation for the custom score
+ */
+ public Explanation customExplain(int doc, Explanation subQueryExpl, Explanation valSrcExpl) throws IOException {
+ float valSrcScore = 1;
+ if (valSrcExpl != null) {
+ valSrcScore *= valSrcExpl.getValue();
+ }
+ Explanation exp = new Explanation( valSrcScore * subQueryExpl.getValue(), "custom score: product of:");
+ exp.addDetail(subQueryExpl);
+ exp.addDetail(valSrcExpl);
+ return exp;
+ }
+
+}
Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/CustomScoreProvider.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/CustomScoreProvider.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Modified: lucene/java/trunk/src/java/org/apache/lucene/search/function/CustomScoreQuery.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/function/CustomScoreQuery.java?rev=912386&r1=912385&r2=912386&view=diff
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/function/CustomScoreQuery.java (original)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/function/CustomScoreQuery.java Sun Feb 21 18:27:05 2010
@@ -40,7 +40,7 @@
* For most simple/convenient use cases this query is likely to be a
* {@link org.apache.lucene.search.function.FieldScoreQuery FieldScoreQuery}</li>
* </ol>
- * Subclasses can modify the computation by overriding {@link #customScore(int, float, float)}.
+ * Subclasses can modify the computation by overriding {@link #getCustomScoreProvider}.
*
* @lucene.experimental
*/
@@ -80,7 +80,6 @@
* This parameter is optional - it can be null or even an empty array.
*/
public CustomScoreQuery(Query subQuery, ValueSourceQuery... valSrcQueries) {
- super();
this.subQuery = subQuery;
this.valSrcQueries = valSrcQueries!=null?
valSrcQueries : new ValueSourceQuery[0];
@@ -90,11 +89,23 @@
/*(non-Javadoc) @see org.apache.lucene.search.Query#rewrite(org.apache.lucene.index.IndexReader) */
@Override
public Query rewrite(IndexReader reader) throws IOException {
- subQuery = subQuery.rewrite(reader);
+ CustomScoreQuery clone = null;
+
+ final Query sq = subQuery.rewrite(reader);
+ if (sq != subQuery) {
+ clone = (CustomScoreQuery) clone();
+ clone.subQuery = sq;
+ }
+
for(int i = 0; i < valSrcQueries.length; i++) {
- valSrcQueries[i] = (ValueSourceQuery) valSrcQueries[i].rewrite(reader);
+ final ValueSourceQuery v = (ValueSourceQuery) valSrcQueries[i].rewrite(reader);
+ if (v != valSrcQueries[i]) {
+ if (clone == null) clone = (CustomScoreQuery) clone();
+ clone.valSrcQueries[i] = v;
+ }
}
- return this;
+
+ return (clone == null) ? this : clone;
}
/*(non-Javadoc) @see org.apache.lucene.search.Query#extractTerms(java.util.Set) */
@@ -139,7 +150,8 @@
}
CustomScoreQuery other = (CustomScoreQuery)o;
if (this.getBoost() != other.getBoost() ||
- !this.subQuery.equals(other.subQuery)||
+ !this.subQuery.equals(other.subQuery) ||
+ this.strict != other.strict ||
this.valSrcQueries.length != other.valSrcQueries.length) {
return false;
}
@@ -150,132 +162,17 @@
@Override
public int hashCode() {
return (getClass().hashCode() + subQuery.hashCode() + Arrays.hashCode(valSrcQueries))
- ^ Float.floatToIntBits(getBoost());
- }
-
- /**
- * Compute a custom score by the subQuery score and a number of
- * ValueSourceQuery scores.
- * <p>
- * Subclasses can override this method to modify the custom score.
- * <p>
- * If your custom scoring is different than the default herein you
- * should override at least one of the two customScore() methods.
- * If the number of ValueSourceQueries is always < 2 it is
- * sufficient to override the other
- * {@link #customScore(int, float, float) customScore()}
- * method, which is simpler.
- * <p>
- * The default computation herein is a multiplication of given scores:
- * <pre>
- * ModifiedScore = valSrcScore * valSrcScores[0] * valSrcScores[1] * ...
- * </pre>
- *
- * @param doc id of scored doc.
- * @param subQueryScore score of that doc by the subQuery.
- * @param valSrcScores scores of that doc by the ValueSourceQuery.
- * @return custom score.
- */
- public float customScore(int doc, float subQueryScore, float valSrcScores[]) {
- if (valSrcScores.length == 1) {
- return customScore(doc, subQueryScore, valSrcScores[0]);
- }
- if (valSrcScores.length == 0) {
- return customScore(doc, subQueryScore, 1);
- }
- float score = subQueryScore;
- for(int i = 0; i < valSrcScores.length; i++) {
- score *= valSrcScores[i];
- }
- return score;
- }
-
- /**
- * Compute a custom score by the subQuery score and the ValueSourceQuery score.
- * <p>
- * Subclasses can override this method to modify the custom score.
- * <p>
- * If your custom scoring is different than the default herein you
- * should override at least one of the two customScore() methods.
- * If the number of ValueSourceQueries is always < 2 it is
- * sufficient to override this customScore() method, which is simpler.
- * <p>
- * The default computation herein is a multiplication of the two scores:
- * <pre>
- * ModifiedScore = subQueryScore * valSrcScore
- * </pre>
- *
- * <p><b>NOTE</b>: The doc is relative to the current
- * reader, last passed to {@link #setNextReader}.
- *
- * @param doc id of scored doc.
- * @param subQueryScore score of that doc by the subQuery.
- * @param valSrcScore score of that doc by the ValueSourceQuery.
- * @return custom score.
- */
- public float customScore(int doc, float subQueryScore, float valSrcScore) {
- return subQueryScore * valSrcScore;
- }
-
- /**
- * Called when the scoring switches to another reader.
- *
- * @param reader
- * next IndexReader
- */
- public void setNextReader(IndexReader reader) throws IOException {
- }
-
- /**
- * Explain the custom score.
- * Whenever overriding {@link #customScore(int, float, float[])},
- * this method should also be overridden to provide the correct explanation
- * for the part of the custom scoring.
- *
- * @param doc doc being explained.
- * @param subQueryExpl explanation for the sub-query part.
- * @param valSrcExpls explanation for the value source part.
- * @return an explanation for the custom score
- */
- public Explanation customExplain(int doc, Explanation subQueryExpl, Explanation valSrcExpls[]) {
- if (valSrcExpls.length == 1) {
- return customExplain(doc, subQueryExpl, valSrcExpls[0]);
- }
- if (valSrcExpls.length == 0) {
- return subQueryExpl;
- }
- float valSrcScore = 1;
- for (int i = 0; i < valSrcExpls.length; i++) {
- valSrcScore *= valSrcExpls[i].getValue();
- }
- Explanation exp = new Explanation( valSrcScore * subQueryExpl.getValue(), "custom score: product of:");
- exp.addDetail(subQueryExpl);
- for (int i = 0; i < valSrcExpls.length; i++) {
- exp.addDetail(valSrcExpls[i]);
- }
- return exp;
+ ^ Float.floatToIntBits(getBoost()) ^ (strict ? 1234 : 4321);
}
-
+
/**
- * Explain the custom score.
- * Whenever overriding {@link #customScore(int, float, float)},
- * this method should also be overridden to provide the correct explanation
- * for the part of the custom scoring.
- *
- * @param doc doc being explained.
- * @param subQueryExpl explanation for the sub-query part.
- * @param valSrcExpl explanation for the value source part.
- * @return an explanation for the custom score
+ * Returns a {@link CustomScoreProvider} that calculates the custom scores
+ * for the given {@link IndexReader}. The default implementation returns a default
+ * implementation as specified in the docs of {@link CustomScoreProvider}.
+ * @since 2.9.2
*/
- public Explanation customExplain(int doc, Explanation subQueryExpl, Explanation valSrcExpl) {
- float valSrcScore = 1;
- if (valSrcExpl != null) {
- valSrcScore *= valSrcExpl.getValue();
- }
- Explanation exp = new Explanation( valSrcScore * subQueryExpl.getValue(), "custom score: product of:");
- exp.addDetail(subQueryExpl);
- exp.addDetail(valSrcExpl);
- return exp;
+ protected CustomScoreProvider getCustomScoreProvider(IndexReader reader) throws IOException {
+ return new CustomScoreProvider(reader);
}
//=========================== W E I G H T ============================
@@ -371,7 +268,7 @@
for(int i = 0; i < valSrcWeights.length; i++) {
valSrcExpls[i] = valSrcWeights[i].explain(reader, doc);
}
- Explanation customExp = customExplain(doc,subQueryExpl,valSrcExpls);
+ Explanation customExp = CustomScoreQuery.this.getCustomScoreProvider(reader).customExplain(doc,subQueryExpl,valSrcExpls);
float sc = getValue() * customExp.getValue();
Explanation res = new ComplexExplanation(
true, sc, CustomScoreQuery.this.toString() + ", product of:");
@@ -398,6 +295,7 @@
private Scorer subQueryScorer;
private Scorer[] valSrcScorers;
private IndexReader reader;
+ private final CustomScoreProvider provider;
private float vScores[]; // reused in score() to avoid allocating this array for each doc
// constructor
@@ -409,7 +307,7 @@
this.valSrcScorers = valSrcScorers;
this.reader = reader;
this.vScores = new float[valSrcScorers.length];
- setNextReader(reader);
+ this.provider = CustomScoreQuery.this.getCustomScoreProvider(reader);
}
@Override
@@ -434,7 +332,7 @@
for (int i = 0; i < valSrcScorers.length; i++) {
vScores[i] = valSrcScorers[i].score();
}
- return qWeight * customScore(subQueryScorer.docID(), subQueryScorer.score(), vScores);
+ return qWeight * provider.customScore(subQueryScorer.docID(), subQueryScorer.score(), vScores);
}
@Override
Modified: lucene/java/trunk/src/test/org/apache/lucene/search/function/TestCustomScoreQuery.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/test/org/apache/lucene/search/function/TestCustomScoreQuery.java?rev=912386&r1=912385&r2=912386&view=diff
==============================================================================
--- lucene/java/trunk/src/test/org/apache/lucene/search/function/TestCustomScoreQuery.java (original)
+++ lucene/java/trunk/src/test/org/apache/lucene/search/function/TestCustomScoreQuery.java Sun Feb 21 18:27:05 2010
@@ -33,7 +33,6 @@
/**
* Test CustomScoreQuery search.
*/
-@SuppressWarnings({"MagicNumber"})
public class TestCustomScoreQuery extends FunctionTestSetup {
/* @override constructor */
@@ -96,23 +95,26 @@
public String name() {
return "customAdd";
}
-
- /*(non-Javadoc) @see org.apache.lucene.search.function.CustomScoreQuery#customScore(int, float, float) */
- @Override
- public float customScore(int doc, float subQueryScore, float valSrcScore) {
- return subQueryScore + valSrcScore;
- }
-
- /* (non-Javadoc)@see org.apache.lucene.search.function.CustomScoreQuery#customExplain(int, org.apache.lucene.search.Explanation, org.apache.lucene.search.Explanation)*/
+
@Override
- public Explanation customExplain(int doc, Explanation subQueryExpl, Explanation valSrcExpl) {
- float valSrcScore = valSrcExpl == null ? 0 : valSrcExpl.getValue();
- Explanation exp = new Explanation(valSrcScore + subQueryExpl.getValue(), "custom score: sum of:");
- exp.addDetail(subQueryExpl);
- if (valSrcExpl != null) {
- exp.addDetail(valSrcExpl);
- }
- return exp;
+ protected CustomScoreProvider getCustomScoreProvider(IndexReader reader) {
+ return new CustomScoreProvider(reader) {
+ @Override
+ public float customScore(int doc, float subQueryScore, float valSrcScore) {
+ return subQueryScore + valSrcScore;
+ }
+
+ @Override
+ public Explanation customExplain(int doc, Explanation subQueryExpl, Explanation valSrcExpl) {
+ float valSrcScore = valSrcExpl == null ? 0 : valSrcExpl.getValue();
+ Explanation exp = new Explanation(valSrcScore + subQueryExpl.getValue(), "custom score: sum of:");
+ exp.addDetail(subQueryExpl);
+ if (valSrcExpl != null) {
+ exp.addDetail(valSrcExpl);
+ }
+ return exp;
+ }
+ };
}
}
@@ -130,52 +132,55 @@
return "customMulAdd";
}
- /*(non-Javadoc) @see org.apache.lucene.search.function.CustomScoreQuery#customScore(int, float, float) */
@Override
- public float customScore(int doc, float subQueryScore, float valSrcScores[]) {
- if (valSrcScores.length == 0) {
- return subQueryScore;
- }
- if (valSrcScores.length == 1) {
- return subQueryScore + valSrcScores[0];
- // confirm that skipping beyond the last doc, on the
- // previous reader, hits NO_MORE_DOCS
- }
- return (subQueryScore + valSrcScores[0]) * valSrcScores[1]; // we know there are two
- }
-
- /* (non-Javadoc)@see org.apache.lucene.search.function.CustomScoreQuery#customExplain(int, org.apache.lucene.search.Explanation, org.apache.lucene.search.Explanation)*/
- @Override
- public Explanation customExplain(int doc, Explanation subQueryExpl, Explanation valSrcExpls[]) {
- if (valSrcExpls.length == 0) {
- return subQueryExpl;
- }
- Explanation exp = new Explanation(valSrcExpls[0].getValue() + subQueryExpl.getValue(), "sum of:");
- exp.addDetail(subQueryExpl);
- exp.addDetail(valSrcExpls[0]);
- if (valSrcExpls.length == 1) {
- exp.setDescription("CustomMulAdd, sum of:");
- return exp;
- }
- Explanation exp2 = new Explanation(valSrcExpls[1].getValue() * exp.getValue(), "custom score: product of:");
- exp2.addDetail(valSrcExpls[1]);
- exp2.addDetail(exp);
- return exp2;
+ protected CustomScoreProvider getCustomScoreProvider(IndexReader reader) {
+ return new CustomScoreProvider(reader) {
+ @Override
+ public float customScore(int doc, float subQueryScore, float valSrcScores[]) {
+ if (valSrcScores.length == 0) {
+ return subQueryScore;
+ }
+ if (valSrcScores.length == 1) {
+ return subQueryScore + valSrcScores[0];
+ // confirm that skipping beyond the last doc, on the
+ // previous reader, hits NO_MORE_DOCS
+ }
+ return (subQueryScore + valSrcScores[0]) * valSrcScores[1]; // we know there are two
+ }
+
+ @Override
+ public Explanation customExplain(int doc, Explanation subQueryExpl, Explanation valSrcExpls[]) {
+ if (valSrcExpls.length == 0) {
+ return subQueryExpl;
+ }
+ Explanation exp = new Explanation(valSrcExpls[0].getValue() + subQueryExpl.getValue(), "sum of:");
+ exp.addDetail(subQueryExpl);
+ exp.addDetail(valSrcExpls[0]);
+ if (valSrcExpls.length == 1) {
+ exp.setDescription("CustomMulAdd, sum of:");
+ return exp;
+ }
+ Explanation exp2 = new Explanation(valSrcExpls[1].getValue() * exp.getValue(), "custom score: product of:");
+ exp2.addDetail(valSrcExpls[1]);
+ exp2.addDetail(exp);
+ return exp2;
+ }
+ };
}
}
private final class CustomExternalQuery extends CustomScoreQuery {
- private IndexReader reader;
- private int[] values;
- public float customScore(int doc, float subScore, float valSrcScore) {
- assertTrue(doc <= reader.maxDoc());
- return (float) values[doc];
- }
-
- public void setNextReader(IndexReader r) throws IOException {
- reader = r;
- values = FieldCache.DEFAULT.getInts(r, INT_FIELD);
+ @Override
+ protected CustomScoreProvider getCustomScoreProvider(IndexReader reader) throws IOException {
+ final int[] values = FieldCache.DEFAULT.getInts(reader, INT_FIELD);
+ return new CustomScoreProvider(reader) {
+ @Override
+ public float customScore(int doc, float subScore, float valSrcScore) throws IOException {
+ assertTrue(doc <= reader.maxDoc());
+ return (float) values[doc];
+ }
+ };
}
public CustomExternalQuery(Query q) {