You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ro...@apache.org on 2017/12/18 17:55:02 UTC
[1/3] lucene-solr:branch_7x: LUCENE-8099: Deprecate CustomScoreQuery,
BoostedQuery, BoostingQuery
Repository: lucene-solr
Updated Branches:
refs/heads/branch_7x 0b99e3a54 -> a41643285
refs/heads/master e441a9900 -> c27099b4d
LUCENE-8099: Deprecate CustomScoreQuery, BoostedQuery, BoostingQuery
Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/a4164328
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/a4164328
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/a4164328
Branch: refs/heads/branch_7x
Commit: a41643285e8ea453da2b0b7e7ebbf9070fe48db0
Parents: 0b99e3a
Author: Alan Woodward <ro...@apache.org>
Authored: Thu Dec 14 12:09:51 2017 +0000
Committer: Alan Woodward <ro...@apache.org>
Committed: Mon Dec 18 17:40:53 2017 +0000
----------------------------------------------------------------------
lucene/CHANGES.txt | 4 +
.../org/apache/lucene/search/BoostQuery.java | 3 +
.../expressions/ExpressionValueSource.java | 6 +-
.../highlight/WeightedSpanTermExtractor.java | 5 +-
.../uhighlight/MultiTermHighlighting.java | 6 +-
.../search/vectorhighlight/FieldQuery.java | 8 +-
.../search/highlight/HighlighterTest.java | 24 +++
.../FastVectorHighlighterTest.java | 32 ++++
lucene/queries/build.xml | 8 +
.../apache/lucene/queries/BoostingQuery.java | 12 ++
.../apache/lucene/queries/CustomScoreQuery.java | 12 ++
.../lucene/queries/function/BoostedQuery.java | 15 +-
.../queries/function/FunctionScoreQuery.java | 7 +
.../function/TestFunctionScoreQuery.java | 147 +++++--------------
.../apache/solr/search/BoostQParserPlugin.java | 23 ++-
.../solr/search/ExtendedDismaxQParser.java | 5 +-
.../apache/solr/search/ValueSourceParser.java | 4 +-
17 files changed, 194 insertions(+), 127 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a4164328/lucene/CHANGES.txt
----------------------------------------------------------------------
diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt
index 8002b13..af82df1 100644
--- a/lucene/CHANGES.txt
+++ b/lucene/CHANGES.txt
@@ -10,6 +10,10 @@ API Changes
* LUCENE-8051: LevensteinDistance renamed to LevenshteinDistance.
(Pulak Ghosh via Adrien Grand)
+* LUCENE-8099: Deprecate CustomScoreQuery, BoostedQuery and BoostingQuery.
+ Users should instead use FunctionScoreQuery, possibly combined with
+ a lucene expression (Alan Woodward)
+
New Features
* LUCENE-2899: Add new module analysis/opennlp, with analysis components
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a4164328/lucene/core/src/java/org/apache/lucene/search/BoostQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/BoostQuery.java b/lucene/core/src/java/org/apache/lucene/search/BoostQuery.java
index 5b05966..7574450 100644
--- a/lucene/core/src/java/org/apache/lucene/search/BoostQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/BoostQuery.java
@@ -27,6 +27,9 @@ import org.apache.lucene.index.IndexReader;
* Boost values that are less than one will give less importance to this
* query compared to other ones while values that are greater than one will
* give more importance to the scores returned by this query.
+ *
+ * More complex boosts can be applied by using FunctionScoreQuery in the
+ * lucene-queries module
*/
public final class BoostQuery extends Query {
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a4164328/lucene/expressions/src/java/org/apache/lucene/expressions/ExpressionValueSource.java
----------------------------------------------------------------------
diff --git a/lucene/expressions/src/java/org/apache/lucene/expressions/ExpressionValueSource.java b/lucene/expressions/src/java/org/apache/lucene/expressions/ExpressionValueSource.java
index 7b30b11..2bfafab 100644
--- a/lucene/expressions/src/java/org/apache/lucene/expressions/ExpressionValueSource.java
+++ b/lucene/expressions/src/java/org/apache/lucene/expressions/ExpressionValueSource.java
@@ -107,7 +107,7 @@ final class ExpressionValueSource extends DoubleValuesSource {
final int prime = 31;
int result = 1;
result = prime * result
- + ((expression == null) ? 0 : expression.hashCode());
+ + ((expression == null) ? 0 : expression.sourceText.hashCode());
result = prime * result + (needsScores ? 1231 : 1237);
result = prime * result + Arrays.hashCode(variables);
return result;
@@ -129,7 +129,7 @@ final class ExpressionValueSource extends DoubleValuesSource {
if (other.expression != null) {
return false;
}
- } else if (!expression.equals(other.expression)) {
+ } else if (!expression.sourceText.equals(other.expression.sourceText)) {
return false;
}
if (needsScores != other.needsScores) {
@@ -178,7 +178,7 @@ final class ExpressionValueSource extends DoubleValuesSource {
changed |= (rewritten[i] == variables[i]);
}
if (changed) {
- return new ExpressionValueSource(variables, expression, needsScores);
+ return new ExpressionValueSource(rewritten, expression, needsScores);
}
return this;
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a4164328/lucene/highlighter/src/java/org/apache/lucene/search/highlight/WeightedSpanTermExtractor.java
----------------------------------------------------------------------
diff --git a/lucene/highlighter/src/java/org/apache/lucene/search/highlight/WeightedSpanTermExtractor.java b/lucene/highlighter/src/java/org/apache/lucene/search/highlight/WeightedSpanTermExtractor.java
index 9fbc121..834c3a6 100644
--- a/lucene/highlighter/src/java/org/apache/lucene/search/highlight/WeightedSpanTermExtractor.java
+++ b/lucene/highlighter/src/java/org/apache/lucene/search/highlight/WeightedSpanTermExtractor.java
@@ -40,6 +40,7 @@ import org.apache.lucene.index.Terms;
import org.apache.lucene.index.memory.MemoryIndex;
import org.apache.lucene.queries.CommonTermsQuery;
import org.apache.lucene.queries.CustomScoreQuery;
+import org.apache.lucene.queries.function.FunctionScoreQuery;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.BoostQuery;
@@ -210,8 +211,10 @@ public class WeightedSpanTermExtractor {
}
} else if (query instanceof MatchAllDocsQuery) {
//nothing
- } else if (query instanceof CustomScoreQuery){
+ } else if (query instanceof CustomScoreQuery) {
extract(((CustomScoreQuery) query).getSubQuery(), boost, terms);
+ } else if (query instanceof FunctionScoreQuery) {
+ extract(((FunctionScoreQuery) query).getWrappedQuery(), boost, terms);
} else if (isQueryUnsupported(query.getClass())) {
// nothing
} else {
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a4164328/lucene/highlighter/src/java/org/apache/lucene/search/uhighlight/MultiTermHighlighting.java
----------------------------------------------------------------------
diff --git a/lucene/highlighter/src/java/org/apache/lucene/search/uhighlight/MultiTermHighlighting.java b/lucene/highlighter/src/java/org/apache/lucene/search/uhighlight/MultiTermHighlighting.java
index e745d78..57d5afa 100644
--- a/lucene/highlighter/src/java/org/apache/lucene/search/uhighlight/MultiTermHighlighting.java
+++ b/lucene/highlighter/src/java/org/apache/lucene/search/uhighlight/MultiTermHighlighting.java
@@ -23,6 +23,7 @@ import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
+import org.apache.lucene.queries.function.FunctionScoreQuery;
import org.apache.lucene.search.AutomatonQuery;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
@@ -80,8 +81,11 @@ class MultiTermHighlighting {
list.addAll(Arrays.asList(extractAutomata(((ConstantScoreQuery) query).getQuery(), fieldMatcher, lookInSpan,
preRewriteFunc)));
} else if (query instanceof BoostQuery) {
- list.addAll(Arrays.asList(extractAutomata(((BoostQuery)query).getQuery(), fieldMatcher, lookInSpan,
+ list.addAll(Arrays.asList(extractAutomata(((BoostQuery) query).getQuery(), fieldMatcher, lookInSpan,
preRewriteFunc)));
+ } else if (query instanceof FunctionScoreQuery) {
+ list.addAll(Arrays.asList(extractAutomata(((FunctionScoreQuery) query).getWrappedQuery(), fieldMatcher,
+ lookInSpan, preRewriteFunc)));
} else if (query instanceof DisjunctionMaxQuery) {
for (Query sub : ((DisjunctionMaxQuery) query).getDisjuncts()) {
list.addAll(Arrays.asList(extractAutomata(sub, fieldMatcher, lookInSpan, preRewriteFunc)));
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a4164328/lucene/highlighter/src/java/org/apache/lucene/search/vectorhighlight/FieldQuery.java
----------------------------------------------------------------------
diff --git a/lucene/highlighter/src/java/org/apache/lucene/search/vectorhighlight/FieldQuery.java b/lucene/highlighter/src/java/org/apache/lucene/search/vectorhighlight/FieldQuery.java
index 0fd336a..6daa791 100644
--- a/lucene/highlighter/src/java/org/apache/lucene/search/vectorhighlight/FieldQuery.java
+++ b/lucene/highlighter/src/java/org/apache/lucene/search/vectorhighlight/FieldQuery.java
@@ -28,6 +28,7 @@ import java.util.Set;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.queries.CustomScoreQuery;
+import org.apache.lucene.queries.function.FunctionScoreQuery;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.BoostQuery;
@@ -143,7 +144,12 @@ public class FieldQuery {
} else if (sourceQuery instanceof CustomScoreQuery) {
final Query q = ((CustomScoreQuery) sourceQuery).getSubQuery();
if (q != null) {
- flatten( q, reader, flatQueries, boost);
+ flatten(q, reader, flatQueries, boost);
+ }
+ } else if (sourceQuery instanceof FunctionScoreQuery) {
+ final Query q = ((FunctionScoreQuery)sourceQuery).getWrappedQuery();
+ if (q != null) {
+ flatten(q, reader, flatQueries, boost);
}
} else if (sourceQuery instanceof ToParentBlockJoinQuery) {
Query childQuery = ((ToParentBlockJoinQuery) sourceQuery).getChildQuery();
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a4164328/lucene/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterTest.java
----------------------------------------------------------------------
diff --git a/lucene/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterTest.java b/lucene/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterTest.java
index d03432e..cf14e27 100644
--- a/lucene/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterTest.java
+++ b/lucene/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterTest.java
@@ -59,10 +59,12 @@ import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.index.Term;
import org.apache.lucene.queries.CommonTermsQuery;
import org.apache.lucene.queries.CustomScoreQuery;
+import org.apache.lucene.queries.function.FunctionScoreQuery;
import org.apache.lucene.queries.payloads.SpanPayloadCheckQuery;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.ConstantScoreQuery;
+import org.apache.lucene.search.DoubleValuesSource;
import org.apache.lucene.search.FuzzyQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.MultiPhraseQuery;
@@ -166,6 +168,28 @@ public class HighlighterTest extends BaseTokenStreamTestCase implements Formatte
}
+ public void testFunctionScoreQuery() throws Exception {
+ TermQuery termQuery = new TermQuery(new Term(FIELD_NAME, "very"));
+ FunctionScoreQuery query = new FunctionScoreQuery(termQuery, DoubleValuesSource.constant(1));
+
+ searcher = newSearcher(reader);
+ TopDocs hits = searcher.search(query, 10, new Sort(SortField.FIELD_DOC, SortField.FIELD_SCORE));
+ assertEquals(2, hits.totalHits);
+ QueryScorer scorer = new QueryScorer(query, FIELD_NAME);
+ Highlighter highlighter = new Highlighter(scorer);
+
+ final int docId0 = hits.scoreDocs[0].doc;
+ Document doc = searcher.doc(docId0);
+ String storedField = doc.get(FIELD_NAME);
+
+ TokenStream stream = getAnyTokenStream(FIELD_NAME, docId0);
+ Fragmenter fragmenter = new SimpleSpanFragmenter(scorer);
+ highlighter.setTextFragmenter(fragmenter);
+ String fragment = highlighter.getBestFragment(stream, storedField);
+ assertEquals("Hello this is a piece of text that is <B>very</B> long and contains too much preamble and the meat is really here which says kennedy has been shot", fragment);
+
+ }
+
public void testQueryScorerHits() throws Exception {
PhraseQuery phraseQuery = new PhraseQuery(FIELD_NAME, "very", "long");
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a4164328/lucene/highlighter/src/test/org/apache/lucene/search/vectorhighlight/FastVectorHighlighterTest.java
----------------------------------------------------------------------
diff --git a/lucene/highlighter/src/test/org/apache/lucene/search/vectorhighlight/FastVectorHighlighterTest.java b/lucene/highlighter/src/test/org/apache/lucene/search/vectorhighlight/FastVectorHighlighterTest.java
index 89f46af..732f62f 100644
--- a/lucene/highlighter/src/test/org/apache/lucene/search/vectorhighlight/FastVectorHighlighterTest.java
+++ b/lucene/highlighter/src/test/org/apache/lucene/search/vectorhighlight/FastVectorHighlighterTest.java
@@ -39,10 +39,12 @@ import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.queries.CommonTermsQuery;
import org.apache.lucene.queries.CustomScoreQuery;
+import org.apache.lucene.queries.function.FunctionScoreQuery;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.BoostQuery;
+import org.apache.lucene.search.DoubleValuesSource;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.PhraseQuery;
import org.apache.lucene.search.Query;
@@ -119,6 +121,36 @@ public class FastVectorHighlighterTest extends LuceneTestCase {
writer.close();
dir.close();
}
+
+ public void testFunctionScoreQueryHighlight() throws IOException {
+ Directory dir = newDirectory();
+ IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(new MockAnalyzer(random())));
+ Document doc = new Document();
+ FieldType type = new FieldType(TextField.TYPE_STORED);
+ type.setStoreTermVectorOffsets(true);
+ type.setStoreTermVectorPositions(true);
+ type.setStoreTermVectors(true);
+ type.freeze();
+ Field field = new Field("field", "This is a test where foo is highlighed and should be highlighted", type);
+
+ doc.add(field);
+ writer.addDocument(doc);
+ FastVectorHighlighter highlighter = new FastVectorHighlighter();
+
+ IndexReader reader = DirectoryReader.open(writer);
+ int docId = 0;
+ FieldQuery fieldQuery = highlighter.getFieldQuery( new FunctionScoreQuery(new TermQuery(new Term("field", "foo")), DoubleValuesSource.constant(1)), reader );
+ String[] bestFragments = highlighter.getBestFragments(fieldQuery, reader, docId, "field", 54, 1);
+ // highlighted results are centered
+ assertEquals("This is a test where <b>foo</b> is highlighed and should be highlighted", bestFragments[0]);
+ bestFragments = highlighter.getBestFragments(fieldQuery, reader, docId, "field", 52, 1);
+ assertEquals("This is a test where <b>foo</b> is highlighed and should be", bestFragments[0]);
+ bestFragments = highlighter.getBestFragments(fieldQuery, reader, docId, "field", 30, 1);
+ assertEquals("a test where <b>foo</b> is highlighed", bestFragments[0]);
+ reader.close();
+ writer.close();
+ dir.close();
+ }
public void testPhraseHighlightLongTextTest() throws IOException {
Directory dir = newDirectory();
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a4164328/lucene/queries/build.xml
----------------------------------------------------------------------
diff --git a/lucene/queries/build.xml b/lucene/queries/build.xml
index 5edb64d..20f9c4f 100644
--- a/lucene/queries/build.xml
+++ b/lucene/queries/build.xml
@@ -21,4 +21,12 @@
</description>
<import file="../module-build.xml"/>
+
+ <path id="test.classpath">
+ <pathelement path="${expressions.jar}"/>
+ <fileset dir="../expressions/lib"/>
+ <path refid="test.base.classpath"/>
+ </path>
+
+ <target name="compile-core" depends="jar-expressions,common.compile-core" />
</project>
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a4164328/lucene/queries/src/java/org/apache/lucene/queries/BoostingQuery.java
----------------------------------------------------------------------
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/BoostingQuery.java b/lucene/queries/src/java/org/apache/lucene/queries/BoostingQuery.java
index 34fa86c..c0da720 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/BoostingQuery.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/BoostingQuery.java
@@ -47,7 +47,19 @@ import org.apache.lucene.search.Weight;
* This code was originally made available here:
* <a href="http://marc.theaimsgroup.com/?l=lucene-user&m=108058407130459&w=2">http://marc.theaimsgroup.com/?l=lucene-user&m=108058407130459&w=2</a>
* and is documented here: http://wiki.apache.org/lucene-java/CommunityContributions
+ *
+ * Clients should instead use FunctionScoreQuery and the lucene-expressions library:
+ * <pre>
+ * SimpleBindings bindings = new SimpleBindings();
+ * bindings.add("score", DoubleValuesSource.SCORES);
+ * bindings.add("context", DoubleValuesSource.fromQuery(new ConstantScoreQuery(myContextQuery, boost)));
+ * Expression expr = JavascriptCompiler.compile("score * context");
+ * FunctionScoreQuery q = new FunctionScoreQuery(inputQuery, expr.getDoubleValuesSource(bindings));
+ * </pre>
+ *
+ * @deprecated Use {@link org.apache.lucene.queries.function.FunctionScoreQuery}
*/
+@Deprecated
public class BoostingQuery extends Query {
private final float boost; // the amount to boost by
private final Query match; // query to match
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a4164328/lucene/queries/src/java/org/apache/lucene/queries/CustomScoreQuery.java
----------------------------------------------------------------------
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/CustomScoreQuery.java b/lucene/queries/src/java/org/apache/lucene/queries/CustomScoreQuery.java
index 25e892b..eb4cfc8 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/CustomScoreQuery.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/CustomScoreQuery.java
@@ -42,7 +42,19 @@ import org.apache.lucene.search.Weight;
* Subclasses can modify the computation by overriding {@link #getCustomScoreProvider}.
*
* @lucene.experimental
+ *
+ * Clients should instead use FunctionScoreQuery and the lucene-expressions library
+ * <pre>
+ * SimpleBindings bindings = new SimpleBindings();
+ * bindings.add("score", DoubleValuesSource.SCORES);
+ * bindings.add("boost", DoubleValuesSource.fromIntField("myboostfield"));
+ * Expression expr = JavascriptCompiler.compile("score * boost");
+ * FunctionScoreQuery q = new FunctionScoreQuery(inputQuery, expr.getDoubleValuesSource(bindings));
+ * </pre>
+ *
+ * @deprecated use {@link org.apache.lucene.queries.function.FunctionScoreQuery}
*/
+@Deprecated
public class CustomScoreQuery extends Query implements Cloneable {
private Query subQuery;
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a4164328/lucene/queries/src/java/org/apache/lucene/queries/function/BoostedQuery.java
----------------------------------------------------------------------
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/BoostedQuery.java b/lucene/queries/src/java/org/apache/lucene/queries/function/BoostedQuery.java
index 7dd0717..0dcb1df 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/BoostedQuery.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/BoostedQuery.java
@@ -34,9 +34,20 @@ import org.apache.lucene.search.Weight;
/**
* Query that is boosted by a ValueSource
+ *
+ * Instead of using this query, clients can use a {@link FunctionScoreQuery} and the
+ * lucene-expressions library:
+ * <pre>
+ * SimpleBindings bindings = new SimpleBindings();
+ * bindings.add("score", DoubleValuesSource.SCORES);
+ * bindings.add("boost", DoubleValuesSource.fromIntField("myboostfield"));
+ * Expression expr = JavascriptCompiler.compile("score * boost");
+ * FunctionScoreQuery q = new FunctionScoreQuery(inputQuery, expr.getDoubleValuesSource(bindings));
+ * </pre>
+ *
+ * @deprecated Use {@link FunctionScoreQuery}
*/
-// TODO: BoostedQuery and BoostingQuery in the same module?
-// something has to give
+@Deprecated
public final class BoostedQuery extends Query {
private final Query q;
private final ValueSource boostVal; // optional, can be null
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a4164328/lucene/queries/src/java/org/apache/lucene/queries/function/FunctionScoreQuery.java
----------------------------------------------------------------------
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/FunctionScoreQuery.java b/lucene/queries/src/java/org/apache/lucene/queries/function/FunctionScoreQuery.java
index d01cf36..60aa9f0 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/FunctionScoreQuery.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/FunctionScoreQuery.java
@@ -55,6 +55,13 @@ public final class FunctionScoreQuery extends Query {
this.source = source;
}
+ /**
+ * @return the wrapped Query
+ */
+ public Query getWrappedQuery() {
+ return in;
+ }
+
@Override
public Weight createWeight(IndexSearcher searcher, boolean needsScores, float boost) throws IOException {
Weight inner = in.createWeight(searcher, needsScores && source.needsScores(), 1f);
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a4164328/lucene/queries/src/test/org/apache/lucene/queries/function/TestFunctionScoreQuery.java
----------------------------------------------------------------------
diff --git a/lucene/queries/src/test/org/apache/lucene/queries/function/TestFunctionScoreQuery.java b/lucene/queries/src/test/org/apache/lucene/queries/function/TestFunctionScoreQuery.java
index 7da9ab1..3349cd8 100644
--- a/lucene/queries/src/test/org/apache/lucene/queries/function/TestFunctionScoreQuery.java
+++ b/lucene/queries/src/test/org/apache/lucene/queries/function/TestFunctionScoreQuery.java
@@ -17,18 +17,15 @@
package org.apache.lucene.queries.function;
-import java.io.IOException;
-import java.util.function.DoubleUnaryOperator;
-import java.util.function.ToDoubleBiFunction;
-
+import org.apache.lucene.expressions.Expression;
+import org.apache.lucene.expressions.SimpleBindings;
+import org.apache.lucene.expressions.js.JavascriptCompiler;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
-import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.BoostQuery;
-import org.apache.lucene.search.DoubleValues;
import org.apache.lucene.search.DoubleValuesSource;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
@@ -75,8 +72,10 @@ public class TestFunctionScoreQuery extends FunctionTestSetup {
// CustomScoreQuery and BoostedQuery equivalent
public void testScoreModifyingSource() throws Exception {
- DoubleValuesSource iii = DoubleValuesSource.fromIntField("iii");
- DoubleValuesSource score = scoringFunction(iii, (v, s) -> v * s);
+ SimpleBindings bindings = new SimpleBindings();
+ bindings.add("score", DoubleValuesSource.SCORES);
+ bindings.add("iii", DoubleValuesSource.fromIntField("iii"));
+ Expression expr = JavascriptCompiler.compile("score * iii");
BooleanQuery bq = new BooleanQuery.Builder()
.add(new TermQuery(new Term(TEXT_FIELD, "first")), BooleanClause.Occur.SHOULD)
@@ -84,7 +83,7 @@ public class TestFunctionScoreQuery extends FunctionTestSetup {
.build();
TopDocs plain = searcher.search(bq, 1);
- FunctionScoreQuery fq = new FunctionScoreQuery(bq, score);
+ FunctionScoreQuery fq = new FunctionScoreQuery(bq, expr.getDoubleValuesSource(bindings));
QueryUtils.check(random(), fq, searcher, rarely());
@@ -98,12 +97,38 @@ public class TestFunctionScoreQuery extends FunctionTestSetup {
}
+ // BoostingQuery equivalent
+ public void testCombiningMultipleQueryScores() throws Exception {
+
+ SimpleBindings bindings = new SimpleBindings();
+ bindings.add("score", DoubleValuesSource.SCORES);
+ bindings.add("testquery", DoubleValuesSource.fromQuery(new TermQuery(new Term(TEXT_FIELD, "rechecking"))));
+ Expression expr = JavascriptCompiler.compile("score + (testquery * 100)");
+
+ TermQuery q = new TermQuery(new Term(TEXT_FIELD, "text"));
+ TopDocs plain = searcher.search(q, 1);
+
+ FunctionScoreQuery fq = new FunctionScoreQuery(q, expr.getDoubleValuesSource(bindings));
+
+ QueryUtils.check(random(), fq, searcher, rarely());
+
+ int[] expectedDocs = new int[]{ 6, 1, 0, 2, 8 };
+ TopDocs docs = searcher.search(fq, 5);
+ assertEquals(plain.totalHits, docs.totalHits);
+ for (int i = 0; i < expectedDocs.length; i++) {
+ assertEquals(expectedDocs[i], docs.scoreDocs[i].doc);
+
+ }
+ }
+
// check boosts with non-distributive score source
public void testBoostsAreAppliedLast() throws Exception {
- DoubleValuesSource scores = function(DoubleValuesSource.SCORES, v -> Math.log(v + 4));
+ SimpleBindings bindings = new SimpleBindings();
+ bindings.add("score", DoubleValuesSource.SCORES);
+ Expression expr = JavascriptCompiler.compile("ln(score + 4)");
- Query q1 = new FunctionScoreQuery(new TermQuery(new Term(TEXT_FIELD, "text")), scores);
+ Query q1 = new FunctionScoreQuery(new TermQuery(new Term(TEXT_FIELD, "text")), expr.getDoubleValuesSource(bindings));
TopDocs plain = searcher.search(q1, 5);
Query boosted = new BoostQuery(q1, 2);
@@ -116,104 +141,4 @@ public class TestFunctionScoreQuery extends FunctionTestSetup {
}
- public static DoubleValuesSource function(DoubleValuesSource in, DoubleUnaryOperator function) {
- return new DoubleValuesSource() {
- @Override
- public DoubleValues getValues(LeafReaderContext ctx, DoubleValues scores) throws IOException {
- DoubleValues v = in.getValues(ctx, scores);
- return new DoubleValues() {
- @Override
- public double doubleValue() throws IOException {
- return function.applyAsDouble(v.doubleValue());
- }
-
- @Override
- public boolean advanceExact(int doc) throws IOException {
- return v.advanceExact(doc);
- }
- };
- }
-
- @Override
- public boolean needsScores() {
- return in.needsScores();
- }
-
- @Override
- public boolean isCacheable(LeafReaderContext ctx) {
- return in.isCacheable(ctx);
- }
-
- @Override
- public DoubleValuesSource rewrite(IndexSearcher searcher) throws IOException {
- return function(in.rewrite(searcher), function);
- }
-
- @Override
- public int hashCode() {
- return 0;
- }
-
- @Override
- public boolean equals(Object obj) {
- return false;
- }
-
- @Override
- public String toString() {
- return "fn";
- }
- };
- }
-
- private static DoubleValuesSource scoringFunction(DoubleValuesSource in, ToDoubleBiFunction<Double, Double> function) {
- return new DoubleValuesSource() {
- @Override
- public DoubleValues getValues(LeafReaderContext ctx, DoubleValues scores) throws IOException {
- DoubleValues v = in.getValues(ctx, scores);
- return new DoubleValues() {
- @Override
- public double doubleValue() throws IOException {
- return function.applyAsDouble(v.doubleValue(), scores.doubleValue());
- }
-
- @Override
- public boolean advanceExact(int doc) throws IOException {
- return v.advanceExact(doc);
- }
- };
- }
-
- @Override
- public boolean needsScores() {
- return true;
- }
-
- @Override
- public boolean isCacheable(LeafReaderContext ctx) {
- return in.isCacheable(ctx);
- }
-
- @Override
- public DoubleValuesSource rewrite(IndexSearcher searcher) throws IOException {
- return scoringFunction(in.rewrite(searcher), function);
- }
-
- @Override
- public int hashCode() {
- return 0;
- }
-
- @Override
- public boolean equals(Object obj) {
- return false;
- }
-
- @Override
- public String toString() {
- return "fn";
- }
- };
- }
-
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a4164328/solr/core/src/java/org/apache/solr/search/BoostQParserPlugin.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/BoostQParserPlugin.java b/solr/core/src/java/org/apache/solr/search/BoostQParserPlugin.java
index 5f7add8..7391f66 100644
--- a/solr/core/src/java/org/apache/solr/search/BoostQParserPlugin.java
+++ b/solr/core/src/java/org/apache/solr/search/BoostQParserPlugin.java
@@ -16,11 +16,18 @@
*/
package org.apache.solr.search;
-import org.apache.lucene.queries.function.BoostedQuery;
+import java.text.ParseException;
+
+import org.apache.lucene.expressions.Expression;
+import org.apache.lucene.expressions.SimpleBindings;
+import org.apache.lucene.expressions.js.JavascriptCompiler;
import org.apache.lucene.queries.function.FunctionQuery;
+import org.apache.lucene.queries.function.FunctionScoreQuery;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.queries.function.valuesource.QueryValueSource;
+import org.apache.lucene.search.DoubleValuesSource;
import org.apache.lucene.search.Query;
+import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.request.SolrQueryRequest;
@@ -60,7 +67,7 @@ public class BoostQParserPlugin extends QParserPlugin {
} else {
vs = new QueryValueSource(bq, 0.0f);
}
- return new BoostedQuery(q, vs);
+ return boostQuery(q, vs);
}
@@ -84,4 +91,16 @@ public class BoostQParserPlugin extends QParserPlugin {
};
}
+ public static Query boostQuery(Query input, ValueSource vs) {
+ try {
+ SimpleBindings bindings = new SimpleBindings();
+ bindings.add("score", DoubleValuesSource.SCORES);
+ bindings.add("vs", vs.asDoubleValuesSource());
+ Expression expr = JavascriptCompiler.compile("score * vs");
+ return new FunctionScoreQuery(input, expr.getDoubleValuesSource(bindings));
+ } catch (ParseException e) {
+ throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, e); // should never happen!
+ }
+ }
+
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a4164328/solr/core/src/java/org/apache/solr/search/ExtendedDismaxQParser.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/ExtendedDismaxQParser.java b/solr/core/src/java/org/apache/solr/search/ExtendedDismaxQParser.java
index c48d127..5e74f4a 100644
--- a/solr/core/src/java/org/apache/solr/search/ExtendedDismaxQParser.java
+++ b/solr/core/src/java/org/apache/solr/search/ExtendedDismaxQParser.java
@@ -33,7 +33,6 @@ import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.core.StopFilterFactory;
import org.apache.lucene.analysis.util.TokenFilterFactory;
import org.apache.lucene.index.Term;
-import org.apache.lucene.queries.function.BoostedQuery;
import org.apache.lucene.queries.function.FunctionQuery;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.queries.function.valuesource.ProductFloatFunction;
@@ -197,9 +196,9 @@ public class ExtendedDismaxQParser extends QParser {
List<ValueSource> boosts = getMultiplicativeBoosts();
if (boosts.size()>1) {
ValueSource prod = new ProductFloatFunction(boosts.toArray(new ValueSource[boosts.size()]));
- topQuery = new BoostedQuery(topQuery, prod);
+ topQuery = BoostQParserPlugin.boostQuery(topQuery, prod);
} else if (boosts.size() == 1) {
- topQuery = new BoostedQuery(topQuery, boosts.get(0));
+ topQuery = BoostQParserPlugin.boostQuery(topQuery, boosts.get(0));
}
return topQuery;
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a4164328/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java b/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java
index dc6411e..367eb64 100644
--- a/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java
+++ b/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java
@@ -27,7 +27,6 @@ import java.util.Map;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.Term;
-import org.apache.lucene.queries.function.BoostedQuery;
import org.apache.lucene.queries.function.FunctionValues;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.queries.function.docvalues.BoolDocValues;
@@ -326,8 +325,7 @@ public abstract class ValueSourceParser implements NamedListInitializedPlugin {
public ValueSource parse(FunctionQParser fp) throws SyntaxError {
Query q = fp.parseNestedQuery();
ValueSource vs = fp.parseValueSource();
- BoostedQuery bq = new BoostedQuery(q, vs);
- return new QueryValueSource(bq, 0.0f);
+ return new QueryValueSource(BoostQParserPlugin.boostQuery(q, vs), 0.0f);
}
});
addParser("joindf", new ValueSourceParser() {
[2/3] lucene-solr:master: LUCENE-8099: Remove deprecated
CustomScoreQuery, BoostedQuery, BoostingQuery
Posted by ro...@apache.org.
LUCENE-8099: Remove deprecated CustomScoreQuery, BoostedQuery, BoostingQuery
Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/c27099b4
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/c27099b4
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/c27099b4
Branch: refs/heads/master
Commit: c27099b4d1578dd37c284a4c23f3f812d98fe939
Parents: b01e602
Author: Alan Woodward <ro...@apache.org>
Authored: Thu Dec 14 13:47:47 2017 +0000
Committer: Alan Woodward <ro...@apache.org>
Committed: Mon Dec 18 17:47:03 2017 +0000
----------------------------------------------------------------------
lucene/CHANGES.txt | 3 +
lucene/MIGRATE.txt | 13 +
.../highlight/WeightedSpanTermExtractor.java | 3 -
.../search/vectorhighlight/FieldQuery.java | 6 -
.../search/highlight/HighlighterTest.java | 23 --
.../FastVectorHighlighterTest.java | 31 --
.../apache/lucene/queries/BoostingQuery.java | 198 ----------
.../lucene/queries/CustomScoreProvider.java | 162 ---------
.../apache/lucene/queries/CustomScoreQuery.java | 334 -----------------
.../lucene/queries/function/BoostedQuery.java | 195 ----------
.../lucene/queries/BoostingQueryTest.java | 56 ---
.../queries/TestCustomScoreExplanations.java | 91 -----
.../lucene/queries/TestCustomScoreQuery.java | 361 -------------------
.../queries/function/TestBoostedQuery.java | 98 -----
.../queryparser/xml/CorePlusQueriesParser.java | 2 -
.../xml/builders/BoostingQueryBuilder.java | 58 ---
16 files changed, 16 insertions(+), 1618 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/c27099b4/lucene/CHANGES.txt
----------------------------------------------------------------------
diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt
index ac70c4e..d8e1237 100644
--- a/lucene/CHANGES.txt
+++ b/lucene/CHANGES.txt
@@ -26,6 +26,9 @@ API Changes
* LUCENE-7996: Queries are now required to produce positive scores.
(Adrien Grand)
+* LUCENE-8099: CustomScoreQuery, BoostedQuery and BoostingQuery have been
+ removed (Alan Woodward)
+
Changes in Runtime Behavior
* LUCENE-7837: Indices that were created before the previous major version
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/c27099b4/lucene/MIGRATE.txt
----------------------------------------------------------------------
diff --git a/lucene/MIGRATE.txt b/lucene/MIGRATE.txt
index 6151abd..9d02db8 100644
--- a/lucene/MIGRATE.txt
+++ b/lucene/MIGRATE.txt
@@ -15,3 +15,16 @@ negative scores.
As a side-effect of this change, negative boosts are now rejected and
FunctionScoreQuery maps negative values to 0.
+
+
+## CustomScoreQuery, BoostedQuery and BoostingQuery removed (LUCENE-8099) ##
+
+Instead use FunctionScoreQuery and a DoubleValuesSource implementation. For example,
+to replace the functionality of BoostedQuery, you could do the following, using
+the lucene-expressions module:
+
+SimpleBindings bindings = new SimpleBindings();
+bindings.add("score", DoubleValuesSource.SCORES);
+bindings.add("boost", DoubleValuesSource.fromIntField("myboostfield"));
+Expression expr = JavascriptCompiler.compile("score * boost");
+FunctionScoreQuery q = new FunctionScoreQuery(inputQuery, expr.getDoubleValuesSource(bindings));
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/c27099b4/lucene/highlighter/src/java/org/apache/lucene/search/highlight/WeightedSpanTermExtractor.java
----------------------------------------------------------------------
diff --git a/lucene/highlighter/src/java/org/apache/lucene/search/highlight/WeightedSpanTermExtractor.java b/lucene/highlighter/src/java/org/apache/lucene/search/highlight/WeightedSpanTermExtractor.java
index 8e6bf24..004c06e 100644
--- a/lucene/highlighter/src/java/org/apache/lucene/search/highlight/WeightedSpanTermExtractor.java
+++ b/lucene/highlighter/src/java/org/apache/lucene/search/highlight/WeightedSpanTermExtractor.java
@@ -39,7 +39,6 @@ import org.apache.lucene.index.Term;
import org.apache.lucene.index.Terms;
import org.apache.lucene.index.memory.MemoryIndex;
import org.apache.lucene.queries.CommonTermsQuery;
-import org.apache.lucene.queries.CustomScoreQuery;
import org.apache.lucene.queries.function.FunctionScoreQuery;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
@@ -212,8 +211,6 @@ public class WeightedSpanTermExtractor {
}
} else if (query instanceof MatchAllDocsQuery) {
//nothing
- } else if (query instanceof CustomScoreQuery) {
- extract(((CustomScoreQuery) query).getSubQuery(), boost, terms);
} else if (query instanceof FunctionScoreQuery) {
extract(((FunctionScoreQuery) query).getWrappedQuery(), boost, terms);
} else if (isQueryUnsupported(query.getClass())) {
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/c27099b4/lucene/highlighter/src/java/org/apache/lucene/search/vectorhighlight/FieldQuery.java
----------------------------------------------------------------------
diff --git a/lucene/highlighter/src/java/org/apache/lucene/search/vectorhighlight/FieldQuery.java b/lucene/highlighter/src/java/org/apache/lucene/search/vectorhighlight/FieldQuery.java
index 6daa791..cb502343 100644
--- a/lucene/highlighter/src/java/org/apache/lucene/search/vectorhighlight/FieldQuery.java
+++ b/lucene/highlighter/src/java/org/apache/lucene/search/vectorhighlight/FieldQuery.java
@@ -27,7 +27,6 @@ import java.util.Set;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
-import org.apache.lucene.queries.CustomScoreQuery;
import org.apache.lucene.queries.function.FunctionScoreQuery;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
@@ -141,11 +140,6 @@ public class FieldQuery {
if (q != null) {
flatten( q, reader, flatQueries, boost);
}
- } else if (sourceQuery instanceof CustomScoreQuery) {
- final Query q = ((CustomScoreQuery) sourceQuery).getSubQuery();
- if (q != null) {
- flatten(q, reader, flatQueries, boost);
- }
} else if (sourceQuery instanceof FunctionScoreQuery) {
final Query q = ((FunctionScoreQuery)sourceQuery).getWrappedQuery();
if (q != null) {
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/c27099b4/lucene/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterTest.java
----------------------------------------------------------------------
diff --git a/lucene/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterTest.java b/lucene/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterTest.java
index cf14e27..5c2fe35 100644
--- a/lucene/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterTest.java
+++ b/lucene/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterTest.java
@@ -58,7 +58,6 @@ import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.index.Term;
import org.apache.lucene.queries.CommonTermsQuery;
-import org.apache.lucene.queries.CustomScoreQuery;
import org.apache.lucene.queries.function.FunctionScoreQuery;
import org.apache.lucene.queries.payloads.SpanPayloadCheckQuery;
import org.apache.lucene.search.BooleanClause.Occur;
@@ -146,28 +145,6 @@ public class HighlighterTest extends BaseTokenStreamTestCase implements Formatte
searcher.doc(docId).get(fieldName), analyzer, -1);
}
- public void testCustomScoreQueryHighlight() throws Exception{
- TermQuery termQuery = new TermQuery(new Term(FIELD_NAME, "very"));
- CustomScoreQuery query = new CustomScoreQuery(termQuery);
-
- searcher = newSearcher(reader);
- TopDocs hits = searcher.search(query, 10, new Sort(SortField.FIELD_DOC, SortField.FIELD_SCORE));
- assertEquals(2, hits.totalHits);
- QueryScorer scorer = new QueryScorer(query, FIELD_NAME);
- Highlighter highlighter = new Highlighter(scorer);
-
- final int docId0 = hits.scoreDocs[0].doc;
- Document doc = searcher.doc(docId0);
- String storedField = doc.get(FIELD_NAME);
-
- TokenStream stream = getAnyTokenStream(FIELD_NAME, docId0);
- Fragmenter fragmenter = new SimpleSpanFragmenter(scorer);
- highlighter.setTextFragmenter(fragmenter);
- String fragment = highlighter.getBestFragment(stream, storedField);
- assertEquals("Hello this is a piece of text that is <B>very</B> long and contains too much preamble and the meat is really here which says kennedy has been shot", fragment);
-
- }
-
public void testFunctionScoreQuery() throws Exception {
TermQuery termQuery = new TermQuery(new Term(FIELD_NAME, "very"));
FunctionScoreQuery query = new FunctionScoreQuery(termQuery, DoubleValuesSource.constant(1));
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/c27099b4/lucene/highlighter/src/test/org/apache/lucene/search/vectorhighlight/FastVectorHighlighterTest.java
----------------------------------------------------------------------
diff --git a/lucene/highlighter/src/test/org/apache/lucene/search/vectorhighlight/FastVectorHighlighterTest.java b/lucene/highlighter/src/test/org/apache/lucene/search/vectorhighlight/FastVectorHighlighterTest.java
index 732f62f..0683e8d 100644
--- a/lucene/highlighter/src/test/org/apache/lucene/search/vectorhighlight/FastVectorHighlighterTest.java
+++ b/lucene/highlighter/src/test/org/apache/lucene/search/vectorhighlight/FastVectorHighlighterTest.java
@@ -38,7 +38,6 @@ import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.queries.CommonTermsQuery;
-import org.apache.lucene.queries.CustomScoreQuery;
import org.apache.lucene.queries.function.FunctionScoreQuery;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanClause;
@@ -92,36 +91,6 @@ public class FastVectorHighlighterTest extends LuceneTestCase {
dir.close();
}
- public void testCustomScoreQueryHighlight() throws IOException {
- Directory dir = newDirectory();
- IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(new MockAnalyzer(random())));
- Document doc = new Document();
- FieldType type = new FieldType(TextField.TYPE_STORED);
- type.setStoreTermVectorOffsets(true);
- type.setStoreTermVectorPositions(true);
- type.setStoreTermVectors(true);
- type.freeze();
- Field field = new Field("field", "This is a test where foo is highlighed and should be highlighted", type);
-
- doc.add(field);
- writer.addDocument(doc);
- FastVectorHighlighter highlighter = new FastVectorHighlighter();
-
- IndexReader reader = DirectoryReader.open(writer);
- int docId = 0;
- FieldQuery fieldQuery = highlighter.getFieldQuery( new CustomScoreQuery(new TermQuery(new Term("field", "foo"))), reader );
- String[] bestFragments = highlighter.getBestFragments(fieldQuery, reader, docId, "field", 54, 1);
- // highlighted results are centered
- assertEquals("This is a test where <b>foo</b> is highlighed and should be highlighted", bestFragments[0]);
- bestFragments = highlighter.getBestFragments(fieldQuery, reader, docId, "field", 52, 1);
- assertEquals("This is a test where <b>foo</b> is highlighed and should be", bestFragments[0]);
- bestFragments = highlighter.getBestFragments(fieldQuery, reader, docId, "field", 30, 1);
- assertEquals("a test where <b>foo</b> is highlighed", bestFragments[0]);
- reader.close();
- writer.close();
- dir.close();
- }
-
public void testFunctionScoreQueryHighlight() throws IOException {
Directory dir = newDirectory();
IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(new MockAnalyzer(random())));
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/c27099b4/lucene/queries/src/java/org/apache/lucene/queries/BoostingQuery.java
----------------------------------------------------------------------
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/BoostingQuery.java b/lucene/queries/src/java/org/apache/lucene/queries/BoostingQuery.java
deleted file mode 100644
index 452cbe6..0000000
--- a/lucene/queries/src/java/org/apache/lucene/queries/BoostingQuery.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.queries;
-
-import java.io.IOException;
-import java.util.Objects;
-import java.util.Set;
-
-import org.apache.lucene.index.IndexReader;
-import org.apache.lucene.index.LeafReaderContext;
-import org.apache.lucene.index.Term;
-import org.apache.lucene.search.DocIdSetIterator;
-import org.apache.lucene.search.Explanation;
-import org.apache.lucene.search.FilterScorer;
-import org.apache.lucene.search.IndexSearcher;
-import org.apache.lucene.search.Query;
-import org.apache.lucene.search.ScoreMode;
-import org.apache.lucene.search.Scorer;
-import org.apache.lucene.search.TwoPhaseIterator;
-import org.apache.lucene.search.Weight;
-
-/**
- * The BoostingQuery class can be used to effectively demote results that match a given query.
- * Unlike the "NOT" clause, this still selects documents that contain undesirable terms,
- * but reduces their overall score:
- *
- * Query balancedQuery = new BoostingQuery(positiveQuery, negativeQuery, 0.01f);
- * In this scenario the positiveQuery contains the mandatory, desirable criteria which is used to
- * select all matching documents, and the negativeQuery contains the undesirable elements which
- * are simply used to lessen the scores. Documents that match the negativeQuery have their score
- * multiplied by the supplied "boost" parameter, so this should be less than 1 to achieve a
- * demoting effect
- *
- * This code was originally made available here:
- * <a href="http://marc.theaimsgroup.com/?l=lucene-user&m=108058407130459&w=2">http://marc.theaimsgroup.com/?l=lucene-user&m=108058407130459&w=2</a>
- * and is documented here: http://wiki.apache.org/lucene-java/CommunityContributions
- *
- * Clients should instead use FunctionScoreQuery and the lucene-expressions library:
- * <pre>
- * SimpleBindings bindings = new SimpleBindings();
- * bindings.add("score", DoubleValuesSource.SCORES);
- * bindings.add("context", DoubleValuesSource.fromQuery(new ConstantScoreQuery(myContextQuery, boost)));
- * Expression expr = JavascriptCompiler.compile("score * context");
- * FunctionScoreQuery q = new FunctionScoreQuery(inputQuery, expr.getDoubleValuesSource(bindings));
- * </pre>
- *
- * @deprecated Use {@link org.apache.lucene.queries.function.FunctionScoreQuery}
- */
-@Deprecated
-public class BoostingQuery extends Query {
- private final float boost; // the amount to boost by
- private final Query match; // query to match
- private final Query context; // boost when matches too
-
- public BoostingQuery(Query match, Query context, float boost) {
- this.match = match;
- this.context = context; // ignore context-only matches
- if (Float.isFinite(boost) == false || Float.compare(boost, 0f) < 0) {
- // otherwise scores could be negative
- throw new IllegalArgumentException("boost must be a non-negative float, got " + boost);
- }
- this.boost = boost;
- }
-
- @Override
- public Query rewrite(IndexReader reader) throws IOException {
- Query matchRewritten = match.rewrite(reader);
- Query contextRewritten = context.rewrite(reader);
- if (match != matchRewritten || context != contextRewritten) {
- return new BoostingQuery(matchRewritten, contextRewritten, boost);
- }
- return super.rewrite(reader);
- }
-
- @Override
- public Weight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
- if (scoreMode.needsScores() == false) {
- return match.createWeight(searcher, scoreMode, boost);
- }
- final Weight matchWeight = searcher.createWeight(match, scoreMode, boost);
- final Weight contextWeight = searcher.createWeight(context, ScoreMode.COMPLETE_NO_SCORES, boost);
- return new Weight(this) {
-
- @Override
- public void extractTerms(Set<Term> terms) {
- matchWeight.extractTerms(terms);
- if (boost >= 1) {
- contextWeight.extractTerms(terms);
- }
- }
-
- @Override
- public Explanation explain(LeafReaderContext context, int doc) throws IOException {
- final Explanation matchExplanation = matchWeight.explain(context, doc);
- final Explanation contextExplanation = contextWeight.explain(context, doc);
- if (matchExplanation.isMatch() == false || contextExplanation.isMatch() == false) {
- return matchExplanation;
- }
- return Explanation.match(matchExplanation.getValue() * boost, "product of:",
- matchExplanation,
- Explanation.match(boost, "boost"));
- }
-
- @Override
- public Scorer scorer(LeafReaderContext context) throws IOException {
- final Scorer matchScorer = matchWeight.scorer(context);
- if (matchScorer == null) {
- return null;
- }
- final Scorer contextScorer = contextWeight.scorer(context);
- if (contextScorer == null) {
- return matchScorer;
- }
- TwoPhaseIterator contextTwoPhase = contextScorer.twoPhaseIterator();
- DocIdSetIterator contextApproximation = contextTwoPhase == null
- ? contextScorer.iterator()
- : contextTwoPhase.approximation();
- return new FilterScorer(matchScorer) {
- @Override
- public float score() throws IOException {
- if (contextApproximation.docID() < docID()) {
- contextApproximation.advance(docID());
- }
- assert contextApproximation.docID() >= docID();
- float score = super.score();
- if (contextApproximation.docID() == docID()
- && (contextTwoPhase == null || contextTwoPhase.matches())) {
- score *= boost;
- }
- return score;
- }
- @Override
- public float maxScore() {
- float maxScore = matchScorer.maxScore();
- if (boost > 1) {
- maxScore *= boost;
- }
- return maxScore;
- }
- };
- }
-
- @Override
- public boolean isCacheable(LeafReaderContext ctx) {
- return matchWeight.isCacheable(ctx) && contextWeight.isCacheable(ctx);
- }
-
- };
- }
-
- public Query getMatch() {
- return match;
- }
-
- public Query getContext() {
- return context;
- }
-
- public float getBoost() {
- return boost;
- }
-
- @Override
- public int hashCode() {
- return 31 * classHash() + Objects.hash(match, context, boost);
- }
-
- @Override
- public boolean equals(Object other) {
- return sameClassAs(other) &&
- equalsTo(getClass().cast(other));
- }
-
- private boolean equalsTo(BoostingQuery other) {
- return match.equals(other.match)
- && context.equals(other.context)
- && Float.floatToIntBits(boost) == Float.floatToIntBits(other.boost);
- }
-
- @Override
- public String toString(String field) {
- return match.toString(field) + "/" + context.toString(field);
- }
- }
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/c27099b4/lucene/queries/src/java/org/apache/lucene/queries/CustomScoreProvider.java
----------------------------------------------------------------------
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/CustomScoreProvider.java b/lucene/queries/src/java/org/apache/lucene/queries/CustomScoreProvider.java
deleted file mode 100644
index db67b94..0000000
--- a/lucene/queries/src/java/org/apache/lucene/queries/CustomScoreProvider.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.queries;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.lucene.index.IndexReader; // for javadocs
-import org.apache.lucene.index.LeafReaderContext;
-import org.apache.lucene.queries.function.FunctionQuery;
-import org.apache.lucene.search.Explanation;
-
-/**
- * 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 #context} 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 DocValues.
- *
- * @lucene.experimental
- * @since 2.9.2
- */
-public class CustomScoreProvider {
-
- protected final LeafReaderContext context;
-
- /**
- * Creates a new instance of the provider class for the given {@link IndexReader}.
- */
- public CustomScoreProvider(LeafReaderContext context) {
- this.context = context;
- }
-
- /**
- * Compute a custom score by the subQuery score and a number of
- * {@link org.apache.lucene.queries.function.FunctionQuery} 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 {@link FunctionQuery function queries} 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 {@link FunctionQuery}.
- * @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 (float valSrcScore : valSrcScores) {
- score *= valSrcScore;
- }
- return score;
- }
-
- /**
- * Compute a custom score by the subQuery score and the {@link FunctionQuery} 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 {@link FunctionQuery function queries} 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 {@link FunctionQuery}.
- * @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 (Explanation valSrcExpl : valSrcExpls) {
- valSrcScore *= valSrcExpl.getValue();
- }
-
- List<Explanation> subs = new ArrayList<>();
- subs.add(subQueryExpl);
- for (Explanation valSrcExpl : valSrcExpls) {
- subs.add(valSrcExpl);
- }
- return Explanation.match(valSrcScore * subQueryExpl.getValue(), "custom score: product of:", subs);
- }
-
- /**
- * 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();
- }
- return Explanation.match(valSrcScore * subQueryExpl.getValue(), "custom score: product of:", subQueryExpl, valSrcExpl);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/c27099b4/lucene/queries/src/java/org/apache/lucene/queries/CustomScoreQuery.java
----------------------------------------------------------------------
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/CustomScoreQuery.java b/lucene/queries/src/java/org/apache/lucene/queries/CustomScoreQuery.java
deleted file mode 100644
index f82cf50..0000000
--- a/lucene/queries/src/java/org/apache/lucene/queries/CustomScoreQuery.java
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.queries;
-
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Set;
-
-import org.apache.lucene.index.IndexReader;
-import org.apache.lucene.index.LeafReaderContext;
-import org.apache.lucene.index.Term;
-import org.apache.lucene.queries.function.FunctionQuery;
-import org.apache.lucene.search.Explanation;
-import org.apache.lucene.search.FilterScorer;
-import org.apache.lucene.search.IndexSearcher;
-import org.apache.lucene.search.Query;
-import org.apache.lucene.search.ScoreMode;
-import org.apache.lucene.search.Scorer;
-import org.apache.lucene.search.Weight;
-
-/**
- * Query that sets document score as a programmatic function of several (sub) scores:
- * <ol>
- * <li>the score of its subQuery (any query)</li>
- * <li>(optional) the score of its {@link FunctionQuery} (or queries).</li>
- * </ol>
- * Subclasses can modify the computation by overriding {@link #getCustomScoreProvider}.
- *
- * @lucene.experimental
- *
- * Clients should instead use FunctionScoreQuery and the lucene-expressions library
- * <pre>
- * SimpleBindings bindings = new SimpleBindings();
- * bindings.add("score", DoubleValuesSource.SCORES);
- * bindings.add("boost", DoubleValuesSource.fromIntField("myboostfield"));
- * Expression expr = JavascriptCompiler.compile("score * boost");
- * FunctionScoreQuery q = new FunctionScoreQuery(inputQuery, expr.getDoubleValuesSource(bindings));
- * </pre>
- *
- * @deprecated use {@link org.apache.lucene.queries.function.FunctionScoreQuery}
- */
-@Deprecated
-public class CustomScoreQuery extends Query implements Cloneable {
-
- private Query subQuery;
- private Query[] scoringQueries; // never null (empty array if there are no valSrcQueries).
-
- /**
- * Create a CustomScoreQuery over input subQuery.
- * @param subQuery the sub query whose scored is being customized. Must not be null.
- */
- public CustomScoreQuery(Query subQuery) {
- this(subQuery, new FunctionQuery[0]);
- }
-
- /**
- * Create a CustomScoreQuery over input subQuery and a {@link org.apache.lucene.queries.function.FunctionQuery}.
- * @param subQuery the sub query whose score is being customized. Must not be null.
- * @param scoringQuery a value source query whose scores are used in the custom score
- * computation. This parameter is optional - it can be null.
- */
- public CustomScoreQuery(Query subQuery, FunctionQuery scoringQuery) {
- this(subQuery, scoringQuery!=null ? // don't want an array that contains a single null..
- new FunctionQuery[] {scoringQuery} : new FunctionQuery[0]);
- }
-
- /**
- * Create a CustomScoreQuery over input subQuery and a {@link org.apache.lucene.queries.function.FunctionQuery}.
- * @param subQuery the sub query whose score is being customized. Must not be null.
- * @param scoringQueries value source queries whose scores are used in the custom score
- * computation. This parameter is optional - it can be null or even an empty array.
- */
- public CustomScoreQuery(Query subQuery, FunctionQuery... scoringQueries) {
- this.subQuery = subQuery;
- this.scoringQueries = scoringQueries !=null?
- scoringQueries : new Query[0];
- if (subQuery == null) throw new IllegalArgumentException("<subquery> must not be null!");
- }
-
- /*(non-Javadoc) @see org.apache.lucene.search.Query#rewrite(org.apache.lucene.index.IndexReader) */
- @Override
- public Query rewrite(IndexReader reader) throws IOException {
- CustomScoreQuery clone = null;
-
- final Query sq = subQuery.rewrite(reader);
- if (sq != subQuery) {
- clone = clone();
- clone.subQuery = sq;
- }
-
- for(int i = 0; i < scoringQueries.length; i++) {
- final Query v = scoringQueries[i].rewrite(reader);
- if (v != scoringQueries[i]) {
- if (clone == null) clone = clone();
- clone.scoringQueries[i] = v;
- }
- }
-
- return (clone == null) ? this : clone;
- }
-
- /*(non-Javadoc) @see org.apache.lucene.search.Query#clone() */
- @Override
- public CustomScoreQuery clone() {
- CustomScoreQuery clone;
- try {
- clone = (CustomScoreQuery)super.clone();
- } catch (CloneNotSupportedException bogus) {
- // cannot happen
- throw new Error(bogus);
- }
- clone.subQuery = subQuery;
- clone.scoringQueries = new Query[scoringQueries.length];
- for(int i = 0; i < scoringQueries.length; i++) {
- clone.scoringQueries[i] = scoringQueries[i];
- }
- return clone;
- }
-
- /* (non-Javadoc) @see org.apache.lucene.search.Query#toString(java.lang.String) */
- @Override
- public String toString(String field) {
- StringBuilder sb = new StringBuilder(name()).append("(");
- sb.append(subQuery.toString(field));
- for (Query scoringQuery : scoringQueries) {
- sb.append(", ").append(scoringQuery.toString(field));
- }
- sb.append(")");
- return sb.toString();
- }
-
- /** Returns true if <code>o</code> is equal to this. */
- @Override
- public boolean equals(Object other) {
- return sameClassAs(other) &&
- equalsTo(getClass().cast(other));
- }
-
- private boolean equalsTo(CustomScoreQuery other) {
- return subQuery.equals(other.subQuery) &&
- scoringQueries.length == other.scoringQueries.length &&
- Arrays.equals(scoringQueries, other.scoringQueries);
- }
-
- /** Returns a hash code value for this object. */
- @Override
- public int hashCode() {
- // Didn't change this hashcode, but it looks suspicious.
- return (classHash() +
- subQuery.hashCode() +
- Arrays.hashCode(scoringQueries));
- }
-
- /**
- * 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
- */
- protected CustomScoreProvider getCustomScoreProvider(LeafReaderContext context) throws IOException {
- return new CustomScoreProvider(context);
- }
-
- //=========================== W E I G H T ============================
-
- private class CustomWeight extends Weight {
- final Weight subQueryWeight;
- final Weight[] valSrcWeights;
- final float queryWeight;
-
- public CustomWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
- super(CustomScoreQuery.this);
- // note we DONT incorporate our boost, nor pass down any boost
- // (e.g. from outer BQ), as there is no guarantee that the CustomScoreProvider's
- // function obeys the distributive law... it might call sqrt() on the subQuery score
- // or some other arbitrary function other than multiplication.
- // so, instead boosts are applied directly in score()
- this.subQueryWeight = subQuery.createWeight(searcher, scoreMode, 1f);
- this.valSrcWeights = new Weight[scoringQueries.length];
- for(int i = 0; i < scoringQueries.length; i++) {
- this.valSrcWeights[i] = scoringQueries[i].createWeight(searcher, scoreMode, 1f);
- }
- this.queryWeight = boost;
- }
-
- @Override
- public void extractTerms(Set<Term> terms) {
- subQueryWeight.extractTerms(terms);
- for (Weight scoringWeight : valSrcWeights) {
- scoringWeight.extractTerms(terms);
- }
- }
-
- @Override
- public Scorer scorer(LeafReaderContext context) throws IOException {
- Scorer subQueryScorer = subQueryWeight.scorer(context);
- if (subQueryScorer == null) {
- return null;
- }
- Scorer[] valSrcScorers = new Scorer[valSrcWeights.length];
- for(int i = 0; i < valSrcScorers.length; i++) {
- valSrcScorers[i] = valSrcWeights[i].scorer(context);
- }
- return new CustomScorer(CustomScoreQuery.this.getCustomScoreProvider(context), this, queryWeight, subQueryScorer, valSrcScorers);
- }
-
- @Override
- public boolean isCacheable(LeafReaderContext ctx) {
- if (subQueryWeight.isCacheable(ctx) == false)
- return false;
- for (Weight w : valSrcWeights) {
- if (w.isCacheable(ctx) == false)
- return false;
- }
- return true;
- }
-
- @Override
- public Explanation explain(LeafReaderContext context, int doc) throws IOException {
- Explanation explain = doExplain(context, doc);
- return explain == null ? Explanation.noMatch("no matching docs") : explain;
- }
-
- private Explanation doExplain(LeafReaderContext info, int doc) throws IOException {
- Explanation subQueryExpl = subQueryWeight.explain(info, doc);
- if (!subQueryExpl.isMatch()) {
- return subQueryExpl;
- }
- // match
- Explanation[] valSrcExpls = new Explanation[valSrcWeights.length];
- for(int i = 0; i < valSrcWeights.length; i++) {
- valSrcExpls[i] = valSrcWeights[i].explain(info, doc);
- }
- Explanation customExp = CustomScoreQuery.this.getCustomScoreProvider(info).customExplain(doc,subQueryExpl,valSrcExpls);
- float sc = queryWeight * customExp.getValue();
- return Explanation.match(
- sc, CustomScoreQuery.this.toString() + ", product of:",
- customExp, Explanation.match(queryWeight, "queryWeight"));
- }
-
- }
-
-
- //=========================== S C O R E R ============================
-
- /**
- * A scorer that applies a (callback) function on scores of the subQuery.
- */
- private static class CustomScorer extends FilterScorer {
- private final float qWeight;
- private final Scorer subQueryScorer;
- private final Scorer[] valSrcScorers;
- private final CustomScoreProvider provider;
- private final float[] vScores; // reused in score() to avoid allocating this array for each doc
- private int valSrcDocID = -1; // we lazily advance subscorers.
-
- // constructor
- private CustomScorer(CustomScoreProvider provider, CustomWeight w, float qWeight,
- Scorer subQueryScorer, Scorer[] valSrcScorers) {
- super(subQueryScorer, w);
- this.qWeight = qWeight;
- this.subQueryScorer = subQueryScorer;
- this.valSrcScorers = valSrcScorers;
- this.vScores = new float[valSrcScorers.length];
- this.provider = provider;
- }
-
- @Override
- public float score() throws IOException {
- // lazily advance to current doc.
- int doc = docID();
- if (doc > valSrcDocID) {
- for (Scorer valSrcScorer : valSrcScorers) {
- valSrcScorer.iterator().advance(doc);
- }
- valSrcDocID = doc;
- }
- // TODO: this thing technically takes any Query, so what about when subs don't match?
- for (int i = 0; i < valSrcScorers.length; i++) {
- vScores[i] = valSrcScorers[i].score();
- }
- return qWeight * provider.customScore(subQueryScorer.docID(), subQueryScorer.score(), vScores);
- }
-
- @Override
- public float maxScore() {
- return Float.POSITIVE_INFINITY;
- }
-
- @Override
- public Collection<ChildScorer> getChildren() {
- return Collections.singleton(new ChildScorer(subQueryScorer, "CUSTOM"));
- }
- }
-
- @Override
- public Weight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
- return new CustomWeight(searcher, scoreMode, boost);
- }
-
- /** The sub-query that CustomScoreQuery wraps, affecting both the score and which documents match. */
- public Query getSubQuery() {
- return subQuery;
- }
-
- /** The scoring queries that only affect the score of CustomScoreQuery. */
- public Query[] getScoringQueries() {
- return scoringQueries;
- }
-
- /**
- * A short name of this query, used in {@link #toString(String)}.
- */
- public String name() {
- return "custom";
- }
-
-}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/c27099b4/lucene/queries/src/java/org/apache/lucene/queries/function/BoostedQuery.java
----------------------------------------------------------------------
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/BoostedQuery.java b/lucene/queries/src/java/org/apache/lucene/queries/function/BoostedQuery.java
deleted file mode 100644
index ddb261a..0000000
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/BoostedQuery.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.queries.function;
-
-import java.io.IOException;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.lucene.index.IndexReader;
-import org.apache.lucene.index.LeafReaderContext;
-import org.apache.lucene.index.Term;
-import org.apache.lucene.search.Explanation;
-import org.apache.lucene.search.FilterScorer;
-import org.apache.lucene.search.IndexSearcher;
-import org.apache.lucene.search.Query;
-import org.apache.lucene.search.ScoreMode;
-import org.apache.lucene.search.Scorer;
-import org.apache.lucene.search.Weight;
-
-/**
- * Query that is boosted by a ValueSource
- *
- * Instead of using this query, clients can use a {@link FunctionScoreQuery} and the
- * lucene-expressions library:
- * <pre>
- * SimpleBindings bindings = new SimpleBindings();
- * bindings.add("score", DoubleValuesSource.SCORES);
- * bindings.add("boost", DoubleValuesSource.fromIntField("myboostfield"));
- * Expression expr = JavascriptCompiler.compile("score * boost");
- * FunctionScoreQuery q = new FunctionScoreQuery(inputQuery, expr.getDoubleValuesSource(bindings));
- * </pre>
- *
- * @deprecated Use {@link FunctionScoreQuery}
- */
-@Deprecated
-public final class BoostedQuery extends Query {
- private final Query q;
- private final ValueSource boostVal; // optional, can be null
-
- public BoostedQuery(Query subQuery, ValueSource boostVal) {
- this.q = subQuery;
- this.boostVal = boostVal;
- }
-
- public Query getQuery() { return q; }
- public ValueSource getValueSource() { return boostVal; }
-
- @Override
- public Query rewrite(IndexReader reader) throws IOException {
- Query newQ = q.rewrite(reader);
- if (newQ != q) {
- return new BoostedQuery(newQ, boostVal);
- }
- return super.rewrite(reader);
- }
-
- @Override
- public Weight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
- return new BoostedQuery.BoostedWeight(searcher, scoreMode, boost);
- }
-
- private class BoostedWeight extends Weight {
- Weight qWeight;
- Map fcontext;
-
- public BoostedWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
- super(BoostedQuery.this);
- this.qWeight = searcher.createWeight(q, scoreMode, boost);
- this.fcontext = ValueSource.newContext(searcher);
- boostVal.createWeight(fcontext,searcher);
- }
-
- @Override
- public void extractTerms(Set<Term> terms) {
- qWeight.extractTerms(terms);
- }
-
- @Override
- public Scorer scorer(LeafReaderContext context) throws IOException {
- Scorer subQueryScorer = qWeight.scorer(context);
- if (subQueryScorer == null) {
- return null;
- }
- return new BoostedQuery.CustomScorer(context, this, subQueryScorer, boostVal);
- }
-
- @Override
- public boolean isCacheable(LeafReaderContext ctx) {
- return false;
- }
-
- @Override
- public Explanation explain(LeafReaderContext readerContext, int doc) throws IOException {
- Explanation subQueryExpl = qWeight.explain(readerContext,doc);
- if (!subQueryExpl.isMatch()) {
- return subQueryExpl;
- }
- FunctionValues vals = boostVal.getValues(fcontext, readerContext);
- float factor = vals.floatVal(doc);
- Explanation factorExpl = vals.explain(doc);
- if (factor < 0) {
- factor = 0;
- factorExpl = Explanation.match(0, "truncated score, max of:",
- Explanation.match(0f, "minimum score"), factorExpl);
- } else if (Float.isNaN(factor)) {
- factor = 0;
- factorExpl = Explanation.match(0, "score, computed as (score == NaN ? 0 : score) since NaN is an illegal score from:", factorExpl);
- }
-
- float sc = subQueryExpl.getValue() * factor;
- return Explanation.match(sc, BoostedQuery.this.toString() + ", product of:",
- subQueryExpl, factorExpl);
- }
- }
-
-
- private class CustomScorer extends FilterScorer {
- private final BoostedQuery.BoostedWeight weight;
- private final ValueSource vs;
- private final FunctionValues vals;
- private final LeafReaderContext readerContext;
-
- private CustomScorer(LeafReaderContext readerContext, BoostedQuery.BoostedWeight w,
- Scorer scorer, ValueSource vs) throws IOException {
- super(scorer);
- this.weight = w;
- this.readerContext = readerContext;
- this.vs = vs;
- this.vals = vs.getValues(weight.fcontext, readerContext);
- }
-
- @Override
- public float score() throws IOException {
- float factor = vals.floatVal(in.docID());
- if (factor >= 0 == false) { // covers NaN as well
- factor = 0;
- }
- return in.score() * factor;
- }
-
- @Override
- public float maxScore() {
- return Float.POSITIVE_INFINITY;
- }
-
- @Override
- public Collection<ChildScorer> getChildren() {
- return Collections.singleton(new ChildScorer(in, "CUSTOM"));
- }
- }
-
-
- @Override
- public String toString(String field) {
- StringBuilder sb = new StringBuilder();
- sb.append("boost(").append(q.toString(field)).append(',').append(boostVal).append(')');
- return sb.toString();
- }
-
- @Override
- public boolean equals(Object other) {
- return sameClassAs(other) &&
- equalsTo(getClass().cast(other));
- }
-
- private boolean equalsTo(BoostedQuery other) {
- return q.equals(other.q) &&
- boostVal.equals(other.boostVal);
- }
-
- @Override
- public int hashCode() {
- int h = classHash();
- h = 31 * h + q.hashCode();
- h = 31 * h + boostVal.hashCode();
- return h;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/c27099b4/lucene/queries/src/test/org/apache/lucene/queries/BoostingQueryTest.java
----------------------------------------------------------------------
diff --git a/lucene/queries/src/test/org/apache/lucene/queries/BoostingQueryTest.java b/lucene/queries/src/test/org/apache/lucene/queries/BoostingQueryTest.java
deleted file mode 100644
index a224bda..0000000
--- a/lucene/queries/src/test/org/apache/lucene/queries/BoostingQueryTest.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.queries;
-
-import java.io.IOException;
-
-import org.apache.lucene.index.IndexReader;
-import org.apache.lucene.index.MultiReader;
-import org.apache.lucene.index.Term;
-import org.apache.lucene.search.BooleanQuery;
-import org.apache.lucene.search.IndexSearcher;
-import org.apache.lucene.search.MatchAllDocsQuery;
-import org.apache.lucene.search.MatchNoDocsQuery;
-import org.apache.lucene.search.Query;
-import org.apache.lucene.search.QueryUtils;
-import org.apache.lucene.search.TermQuery;
-import org.apache.lucene.util.LuceneTestCase;
-
-public class BoostingQueryTest extends LuceneTestCase {
- // TODO: this suite desperately needs more tests!
- // ... like ones that actually run the query
-
- public void testBoostingQueryEquals() {
- TermQuery q1 = new TermQuery(new Term("subject:", "java"));
- TermQuery q2 = new TermQuery(new Term("subject:", "java"));
- assertEquals("Two TermQueries with same attributes should be equal", q1, q2);
- BoostingQuery bq1 = new BoostingQuery(q1, q2, 0.1f);
- QueryUtils.check(bq1);
- BoostingQuery bq2 = new BoostingQuery(q1, q2, 0.1f);
- assertEquals("BoostingQuery with same attributes is not equal", bq1, bq2);
- }
-
- public void testRewrite() throws IOException {
- IndexReader reader = new MultiReader();
- BoostingQuery q = new BoostingQuery(new BooleanQuery.Builder().build(), new MatchAllDocsQuery(), 3);
- Query rewritten = new IndexSearcher(reader).rewrite(q);
- Query expectedRewritten = new BoostingQuery(new MatchNoDocsQuery(), new MatchAllDocsQuery(), 3);
- assertEquals(expectedRewritten, rewritten);
- assertSame(rewritten, rewritten.rewrite(reader));
- }
-
-}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/c27099b4/lucene/queries/src/test/org/apache/lucene/queries/TestCustomScoreExplanations.java
----------------------------------------------------------------------
diff --git a/lucene/queries/src/test/org/apache/lucene/queries/TestCustomScoreExplanations.java b/lucene/queries/src/test/org/apache/lucene/queries/TestCustomScoreExplanations.java
deleted file mode 100644
index ab3cced..0000000
--- a/lucene/queries/src/test/org/apache/lucene/queries/TestCustomScoreExplanations.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.queries;
-
-import java.io.IOException;
-
-import org.apache.lucene.index.Term;
-import org.apache.lucene.queries.function.FunctionQuery;
-import org.apache.lucene.queries.function.valuesource.ConstValueSource;
-import org.apache.lucene.search.BaseExplanationTestCase;
-import org.apache.lucene.search.BooleanClause;
-import org.apache.lucene.search.BooleanQuery;
-import org.apache.lucene.search.BoostQuery;
-import org.apache.lucene.search.Explanation;
-import org.apache.lucene.search.IndexSearcher;
-import org.apache.lucene.search.MatchAllDocsQuery;
-import org.apache.lucene.search.Query;
-import org.apache.lucene.search.TermQuery;
-import org.apache.lucene.search.similarities.BM25Similarity;
-import org.apache.lucene.search.similarities.ClassicSimilarity;
-
-public class TestCustomScoreExplanations extends BaseExplanationTestCase {
- public void testOneTerm() throws Exception {
- Query q = new TermQuery(new Term(FIELD, "w1"));
- CustomScoreQuery csq = new CustomScoreQuery(q, new FunctionQuery(new ConstValueSource(5)));
- qtest(csq, new int[] { 0,1,2,3 });
- }
-
- public void testBoost() throws Exception {
- Query q = new TermQuery(new Term(FIELD, "w1"));
- CustomScoreQuery csq = new CustomScoreQuery(q, new FunctionQuery(new ConstValueSource(5)));
- qtest(new BoostQuery(csq, 4), new int[] { 0,1,2,3 });
- }
-
- public void testTopLevelBoost() throws Exception {
- Query q = new TermQuery(new Term(FIELD, "w1"));
- CustomScoreQuery csq = new CustomScoreQuery(q, new FunctionQuery(new ConstValueSource(5)));
- BooleanQuery.Builder bqB = new BooleanQuery.Builder();
- bqB.add(new MatchAllDocsQuery(), BooleanClause.Occur.MUST);
- bqB.add(csq, BooleanClause.Occur.MUST);
- BooleanQuery bq = bqB.build();
- qtest(new BoostQuery(bq, 6), new int[] { 0,1,2,3 });
- }
-
- public void testSubExplanations() throws IOException {
- Query query = new FunctionQuery(new ConstValueSource(5));
- IndexSearcher searcher = newSearcher(BaseExplanationTestCase.searcher.getIndexReader());
- searcher.setSimilarity(new BM25Similarity());
-
- Explanation expl = searcher.explain(query, 0);
- assertEquals(2, expl.getDetails().length);
- // function
- assertEquals(5f, expl.getDetails()[0].getValue(), 0f);
- // boost
- assertEquals("boost", expl.getDetails()[1].getDescription());
- assertEquals(1f, expl.getDetails()[1].getValue(), 0f);
-
- query = new BoostQuery(query, 2);
- expl = searcher.explain(query, 0);
- assertEquals(2, expl.getDetails().length);
- // function
- assertEquals(5f, expl.getDetails()[0].getValue(), 0f);
- // boost
- assertEquals("boost", expl.getDetails()[1].getDescription());
- assertEquals(2f, expl.getDetails()[1].getValue(), 0f);
-
- searcher.setSimilarity(new ClassicSimilarity()); // in order to have a queryNorm != 1
- expl = searcher.explain(query, 0);
- assertEquals(2, expl.getDetails().length);
- // function
- assertEquals(5f, expl.getDetails()[0].getValue(), 0f);
- // boost
- assertEquals("boost", expl.getDetails()[1].getDescription());
- assertEquals(2f, expl.getDetails()[1].getValue(), 0f);
- }
-}
-
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/c27099b4/lucene/queries/src/test/org/apache/lucene/queries/TestCustomScoreQuery.java
----------------------------------------------------------------------
diff --git a/lucene/queries/src/test/org/apache/lucene/queries/TestCustomScoreQuery.java b/lucene/queries/src/test/org/apache/lucene/queries/TestCustomScoreQuery.java
deleted file mode 100644
index d65e646..0000000
--- a/lucene/queries/src/test/org/apache/lucene/queries/TestCustomScoreQuery.java
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.queries;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.lucene.index.DirectoryReader;
-import org.apache.lucene.index.DocValues;
-import org.apache.lucene.index.IndexReader;
-import org.apache.lucene.index.LeafReaderContext;
-import org.apache.lucene.index.NumericDocValues;
-import org.apache.lucene.index.Term;
-import org.apache.lucene.queries.function.FunctionQuery;
-import org.apache.lucene.queries.function.FunctionTestSetup;
-import org.apache.lucene.queries.function.ValueSource;
-import org.apache.lucene.search.BooleanClause;
-import org.apache.lucene.search.BooleanQuery;
-import org.apache.lucene.search.BoostQuery;
-import org.apache.lucene.search.Explanation;
-import org.apache.lucene.search.IndexSearcher;
-import org.apache.lucene.search.Query;
-import org.apache.lucene.search.QueryUtils;
-import org.apache.lucene.search.TermQuery;
-import org.apache.lucene.search.TermRangeQuery;
-import org.apache.lucene.search.TopDocs;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-/**
- * Test CustomScoreQuery search.
- */
-public class TestCustomScoreQuery extends FunctionTestSetup {
-
- @BeforeClass
- public static void beforeClass() throws Exception {
- createIndex(true);
- }
-
- /**
- * Test that CustomScoreQuery of Type.INT returns the expected scores.
- */
- @Test
- public void testCustomScoreInt() throws Exception {
- doTestCustomScore(INT_VALUESOURCE, 1f);
- doTestCustomScore(INT_VALUESOURCE, 4f);
- }
-
- /**
- * Test that CustomScoreQuery of Type.FLOAT returns the expected scores.
- */
- @Test
- public void testCustomScoreFloat() throws Exception {
- doTestCustomScore(FLOAT_VALUESOURCE, 1f);
- doTestCustomScore(FLOAT_VALUESOURCE, 6f);
- }
-
- // must have static class otherwise serialization tests fail
- private static class CustomAddQuery extends CustomScoreQuery {
- // constructor
- CustomAddQuery(Query q, FunctionQuery qValSrc) {
- super(q, qValSrc);
- }
-
- /*(non-Javadoc) @see org.apache.lucene.search.function.CustomScoreQuery#name() */
- @Override
- public String name() {
- return "customAdd";
- }
-
- @Override
- protected CustomScoreProvider getCustomScoreProvider(LeafReaderContext context) {
- return new CustomScoreProvider(context) {
- @Override
- public float customScore(int doc, float subQueryScore, float valSrcScore) {
- return subQueryScore + valSrcScore;
- }
-
- @Override
- public Explanation customExplain(int doc, Explanation subQueryExpl, Explanation valSrcExpl) {
- List<Explanation> subs = new ArrayList<>();
- subs.add(subQueryExpl);
- if (valSrcExpl != null) {
- subs.add(valSrcExpl);
- }
- float valSrcScore = valSrcExpl == null ? 0 : valSrcExpl.getValue();
- return Explanation.match(valSrcScore + subQueryExpl.getValue(), "custom score: sum of:", subs);
- }
- };
- }
- }
-
- // must have static class otherwise serialization tests fail
- private static class CustomMulAddQuery extends CustomScoreQuery {
- // constructor
- CustomMulAddQuery(Query q, FunctionQuery qValSrc1, FunctionQuery qValSrc2) {
- super(q, qValSrc1, qValSrc2);
- }
-
- /*(non-Javadoc) @see org.apache.lucene.search.function.CustomScoreQuery#name() */
- @Override
- public String name() {
- return "customMulAdd";
- }
-
- @Override
- protected CustomScoreProvider getCustomScoreProvider(LeafReaderContext context) {
- return new CustomScoreProvider(context) {
- @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;
- }
- if (valSrcExpls.length == 1) {
- return Explanation.match(valSrcExpls[0].getValue() + subQueryExpl.getValue(), "CustomMulAdd, sum of:", subQueryExpl, valSrcExpls[0]);
- } else {
- Explanation exp = Explanation.match(valSrcExpls[0].getValue() + subQueryExpl.getValue(), "sum of:", subQueryExpl, valSrcExpls[0]);
- return Explanation.match(valSrcExpls[1].getValue() * exp.getValue(), "custom score: product of:", valSrcExpls[1], exp);
- }
- }
- };
- }
- }
-
- private static final class CustomExternalQuery extends CustomScoreQuery {
-
- @Override
- protected CustomScoreProvider getCustomScoreProvider(LeafReaderContext context) throws IOException {
- final NumericDocValues values = DocValues.getNumeric(context.reader(), INT_FIELD);
- return new CustomScoreProvider(context) {
- @Override
- public float customScore(int doc, float subScore, float valSrcScore) throws IOException {
- assertTrue(doc <= context.reader().maxDoc());
- if (values.docID() < doc) {
- values.advance(doc);
- }
- if (doc == values.docID()) {
- return values.longValue();
- } else {
- return 0;
- }
- }
- };
- }
-
- public CustomExternalQuery(Query q) {
- super(q);
- }
- }
-
- @Test
- public void testCustomExternalQuery() throws Exception {
- BooleanQuery.Builder q1 = new BooleanQuery.Builder();
- q1.add(new TermQuery(new Term(TEXT_FIELD, "first")), BooleanClause.Occur.SHOULD);
- q1.add(new TermQuery(new Term(TEXT_FIELD, "aid")), BooleanClause.Occur.SHOULD);
- q1.add(new TermQuery(new Term(TEXT_FIELD, "text")), BooleanClause.Occur.SHOULD);
-
- final Query q = new CustomExternalQuery(q1.build());
- log(q);
-
- IndexReader r = DirectoryReader.open(dir);
- IndexSearcher s = newSearcher(r);
- TopDocs hits = s.search(q, 1000);
- assertEquals(N_DOCS, hits.totalHits);
- for(int i=0;i<N_DOCS;i++) {
- final int doc = hits.scoreDocs[i].doc;
- final float score = hits.scoreDocs[i].score;
- assertEquals("doc=" + doc, (float) 1+(4*doc) % N_DOCS, score, 0.0001);
- }
- r.close();
- }
-
- @Test
- public void testRewrite() throws Exception {
- IndexReader r = DirectoryReader.open(dir);
- final IndexSearcher s = newSearcher(r);
-
- Query q = new TermQuery(new Term(TEXT_FIELD, "first"));
- CustomScoreQuery original = new CustomScoreQuery(q);
- CustomScoreQuery rewritten = (CustomScoreQuery) original.rewrite(s.getIndexReader());
- assertTrue("rewritten query should be identical, as TermQuery does not rewrite", original == rewritten);
- assertTrue("no hits for query", s.search(rewritten,1).totalHits > 0);
- assertEquals(s.search(q,1).totalHits, s.search(rewritten,1).totalHits);
-
- q = new TermRangeQuery(TEXT_FIELD, null, null, true, true); // everything
- original = new CustomScoreQuery(q);
- rewritten = (CustomScoreQuery) original.rewrite(s.getIndexReader());
- assertTrue("rewritten query should not be identical, as TermRangeQuery rewrites", original != rewritten);
- assertTrue("no hits for query", s.search(rewritten,1).totalHits > 0);
- assertEquals(s.search(q,1).totalHits, s.search(original,1).totalHits);
- assertEquals(s.search(q,1).totalHits, s.search(rewritten,1).totalHits);
-
- r.close();
- }
-
- // Test that FieldScoreQuery returns docs with expected score.
- private void doTestCustomScore(ValueSource valueSource, float boost) throws Exception {
- FunctionQuery functionQuery = new FunctionQuery(valueSource);
- IndexReader r = DirectoryReader.open(dir);
- IndexSearcher s = newSearcher(r);
-
- // regular (boolean) query.
- BooleanQuery.Builder q1b = new BooleanQuery.Builder();
- q1b.add(new TermQuery(new Term(TEXT_FIELD, "first")), BooleanClause.Occur.SHOULD);
- q1b.add(new TermQuery(new Term(TEXT_FIELD, "aid")), BooleanClause.Occur.SHOULD);
- q1b.add(new TermQuery(new Term(TEXT_FIELD, "text")), BooleanClause.Occur.SHOULD);
- Query q1 = q1b.build();
- log(q1);
-
- // custom query, that should score the same as q1.
- BooleanQuery.Builder q2CustomNeutralB = new BooleanQuery.Builder();
- Query q2CustomNeutralInner = new CustomScoreQuery(q1);
- q2CustomNeutralB.add(new BoostQuery(q2CustomNeutralInner, (float)Math.sqrt(boost)), BooleanClause.Occur.SHOULD);
- // a little tricky: we split the boost across an outer BQ and CustomScoreQuery
- // this ensures boosting is correct across all these functions (see LUCENE-4935)
- Query q2CustomNeutral = q2CustomNeutralB.build();
- q2CustomNeutral = new BoostQuery(q2CustomNeutral, (float)Math.sqrt(boost));
- log(q2CustomNeutral);
-
- // custom query, that should (by default) multiply the scores of q1 by that of the field
- Query q3CustomMul;
- {
- CustomScoreQuery csq = new CustomScoreQuery(q1, functionQuery);
- q3CustomMul = csq;
- }
- q3CustomMul = new BoostQuery(q3CustomMul, boost);
- log(q3CustomMul);
-
- // custom query, that should add the scores of q1 to that of the field
- Query q4CustomAdd;
- {
- CustomScoreQuery csq = new CustomAddQuery(q1, functionQuery);
- q4CustomAdd = csq;
- }
- q4CustomAdd = new BoostQuery(q4CustomAdd, boost);
- log(q4CustomAdd);
-
- // custom query, that multiplies and adds the field score to that of q1
- Query q5CustomMulAdd;
- {
- CustomScoreQuery csq = new CustomMulAddQuery(q1, functionQuery, functionQuery);
- q5CustomMulAdd = csq;
- }
- q5CustomMulAdd = new BoostQuery(q5CustomMulAdd, boost);
- log(q5CustomMulAdd);
-
- // do al the searches
- TopDocs td1 = s.search(q1, 1000);
- TopDocs td2CustomNeutral = s.search(q2CustomNeutral, 1000);
- TopDocs td3CustomMul = s.search(q3CustomMul, 1000);
- TopDocs td4CustomAdd = s.search(q4CustomAdd, 1000);
- TopDocs td5CustomMulAdd = s.search(q5CustomMulAdd, 1000);
-
- // put results in map so we can verify the scores although they have changed
- Map<Integer,Float> h1 = topDocsToMap(td1);
- Map<Integer,Float> h2CustomNeutral = topDocsToMap(td2CustomNeutral);
- Map<Integer,Float> h3CustomMul = topDocsToMap(td3CustomMul);
- Map<Integer,Float> h4CustomAdd = topDocsToMap(td4CustomAdd);
- Map<Integer,Float> h5CustomMulAdd = topDocsToMap(td5CustomMulAdd);
-
- verifyResults(boost, s,
- h1, h2CustomNeutral, h3CustomMul, h4CustomAdd, h5CustomMulAdd,
- q1, q2CustomNeutral, q3CustomMul, q4CustomAdd, q5CustomMulAdd);
- r.close();
- }
-
- // verify results are as expected.
- private void verifyResults(float boost, IndexSearcher s,
- Map<Integer,Float> h1, Map<Integer,Float> h2customNeutral, Map<Integer,Float> h3CustomMul, Map<Integer,Float> h4CustomAdd, Map<Integer,Float> h5CustomMulAdd,
- Query q1, Query q2, Query q3, Query q4, Query q5) throws Exception {
-
- // verify numbers of matches
- log("#hits = "+h1.size());
- assertEquals("queries should have same #hits",h1.size(),h2customNeutral.size());
- assertEquals("queries should have same #hits",h1.size(),h3CustomMul.size());
- assertEquals("queries should have same #hits",h1.size(),h4CustomAdd.size());
- assertEquals("queries should have same #hits",h1.size(),h5CustomMulAdd.size());
-
- QueryUtils.check(random(), q1, s, rarely());
- QueryUtils.check(random(), q2, s, rarely());
- QueryUtils.check(random(), q3, s, rarely());
- QueryUtils.check(random(), q4, s, rarely());
- QueryUtils.check(random(), q5, s, rarely());
-
- // verify scores ratios
- for (final Integer doc : h1.keySet()) {
-
- log("doc = "+doc);
-
- float fieldScore = expectedFieldScore(s.getIndexReader().document(doc).get(ID_FIELD));
- log("fieldScore = " + fieldScore);
- assertTrue("fieldScore should not be 0", fieldScore > 0);
-
- float score1 = h1.get(doc);
- logResult("score1=", s, q1, doc, score1);
-
- float score2 = h2customNeutral.get(doc);
- logResult("score2=", s, q2, doc, score2);
- assertEquals("same score (just boosted) for neutral", boost * score1, score2, Math.scalb(score2, -15));
-
- float score3 = h3CustomMul.get(doc);
- logResult("score3=", s, q3, doc, score3);
- assertEquals("new score for custom mul", boost * fieldScore * score1, score3, Math.scalb(score3, -15));
-
- float score4 = h4CustomAdd.get(doc);
- logResult("score4=", s, q4, doc, score4);
- assertEquals("new score for custom add", boost * (fieldScore + score1), score4, Math.scalb(score4, -15));
-
- float score5 = h5CustomMulAdd.get(doc);
- logResult("score5=", s, q5, doc, score5);
- assertEquals("new score for custom mul add", boost * fieldScore * (score1 + fieldScore), score5, Math.scalb(score5, -15));
- }
- }
-
- private void logResult(String msg, IndexSearcher s, Query q, int doc, float score1) throws IOException {
- log(msg+" "+score1);
- log("Explain by: "+q);
- log(s.explain(q,doc));
- }
-
- // since custom scoring modifies the order of docs, map results
- // by doc ids so that we can later compare/verify them
- private Map<Integer,Float> topDocsToMap(TopDocs td) {
- Map<Integer,Float> h = new HashMap<>();
- for (int i=0; i<td.totalHits; i++) {
- h.put(td.scoreDocs[i].doc, td.scoreDocs[i].score);
- }
- return h;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/c27099b4/lucene/queries/src/test/org/apache/lucene/queries/function/TestBoostedQuery.java
----------------------------------------------------------------------
diff --git a/lucene/queries/src/test/org/apache/lucene/queries/function/TestBoostedQuery.java b/lucene/queries/src/test/org/apache/lucene/queries/function/TestBoostedQuery.java
deleted file mode 100644
index a870366..0000000
--- a/lucene/queries/src/test/org/apache/lucene/queries/function/TestBoostedQuery.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.queries.function;
-
-
-import org.apache.lucene.analysis.MockAnalyzer;
-import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
-import org.apache.lucene.document.SortedDocValuesField;
-import org.apache.lucene.index.IndexReader;
-import org.apache.lucene.index.IndexWriterConfig;
-import org.apache.lucene.index.RandomIndexWriter;
-import org.apache.lucene.queries.function.valuesource.ConstValueSource;
-import org.apache.lucene.search.CheckHits;
-import org.apache.lucene.search.IndexSearcher;
-import org.apache.lucene.search.MatchAllDocsQuery;
-import org.apache.lucene.search.Query;
-import org.apache.lucene.search.ScoreDoc;
-import org.apache.lucene.search.Sort;
-import org.apache.lucene.search.SortField;
-import org.apache.lucene.search.TopDocs;
-import org.apache.lucene.store.Directory;
-import org.apache.lucene.util.BytesRef;
-import org.apache.lucene.util.LuceneTestCase;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-
-/**
- * Basic tests for {@link BoostedQuery}
- */
-// TODO: more tests
-public class TestBoostedQuery extends LuceneTestCase {
- static Directory dir;
- static IndexReader ir;
- static IndexSearcher is;
-
- @BeforeClass
- public static void beforeClass() throws Exception {
- dir = newDirectory();
- IndexWriterConfig iwConfig = newIndexWriterConfig(new MockAnalyzer(random()));
- iwConfig.setMergePolicy(newLogMergePolicy());
- RandomIndexWriter iw = new RandomIndexWriter(random(), dir, iwConfig);
- Document document = new Document();
- Field idField = new SortedDocValuesField("id", new BytesRef());
- document.add(idField);
- iw.addDocument(document);
- ir = iw.getReader();
- is = newSearcher(ir);
- iw.close();
- }
-
- @AfterClass
- public static void afterClass() throws Exception {
- is = null;
- ir.close();
- ir = null;
- dir.close();
- dir = null;
- }
-
- public void testBasic() throws Exception {
- Query q = new MatchAllDocsQuery();
- TopDocs docs = is.search(q, 10);
- assertEquals(1, docs.totalHits);
- float score = docs.scoreDocs[0].score;
-
- Query boostedQ = new BoostedQuery(q, new ConstValueSource(2.0f));
- assertHits(boostedQ, new float[] { score*2 });
- }
-
- void assertHits(Query q, float scores[]) throws Exception {
- ScoreDoc expected[] = new ScoreDoc[scores.length];
- int expectedDocs[] = new int[scores.length];
- for (int i = 0; i < expected.length; i++) {
- expectedDocs[i] = i;
- expected[i] = new ScoreDoc(i, scores[i]);
- }
- TopDocs docs = is.search(q, 10,
- new Sort(new SortField("id", SortField.Type.STRING)));
- CheckHits.checkHits(random(), q, "", is, expectedDocs);
- CheckHits.checkHitsQuery(q, expected, docs.scoreDocs, expectedDocs);
- CheckHits.checkExplanations(q, "", is);
- }
-}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/c27099b4/lucene/queryparser/src/java/org/apache/lucene/queryparser/xml/CorePlusQueriesParser.java
----------------------------------------------------------------------
diff --git a/lucene/queryparser/src/java/org/apache/lucene/queryparser/xml/CorePlusQueriesParser.java b/lucene/queryparser/src/java/org/apache/lucene/queryparser/xml/CorePlusQueriesParser.java
index 87b5f8f..3243928 100644
--- a/lucene/queryparser/src/java/org/apache/lucene/queryparser/xml/CorePlusQueriesParser.java
+++ b/lucene/queryparser/src/java/org/apache/lucene/queryparser/xml/CorePlusQueriesParser.java
@@ -19,7 +19,6 @@ package org.apache.lucene.queryparser.xml;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.queryparser.xml.builders.LikeThisQueryBuilder;
-import org.apache.lucene.queryparser.xml.builders.BoostingQueryBuilder;
/**
* Assembles a QueryBuilder which uses Query objects from
@@ -50,7 +49,6 @@ public class CorePlusQueriesParser extends CoreParser {
super(defaultField, analyzer, parser);
String fields[] = {"contents"};
queryFactory.addBuilder("LikeThisQuery", new LikeThisQueryBuilder(analyzer, fields));
- queryFactory.addBuilder("BoostingQuery", new BoostingQueryBuilder(queryFactory));
}
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/c27099b4/lucene/queryparser/src/java/org/apache/lucene/queryparser/xml/builders/BoostingQueryBuilder.java
----------------------------------------------------------------------
diff --git a/lucene/queryparser/src/java/org/apache/lucene/queryparser/xml/builders/BoostingQueryBuilder.java b/lucene/queryparser/src/java/org/apache/lucene/queryparser/xml/builders/BoostingQueryBuilder.java
deleted file mode 100644
index f58804b..0000000
--- a/lucene/queryparser/src/java/org/apache/lucene/queryparser/xml/builders/BoostingQueryBuilder.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.queryparser.xml.builders;
-
-import org.apache.lucene.queries.BoostingQuery;
-import org.apache.lucene.search.BoostQuery;
-import org.apache.lucene.search.Query;
-import org.apache.lucene.queryparser.xml.DOMUtils;
-import org.apache.lucene.queryparser.xml.ParserException;
-import org.apache.lucene.queryparser.xml.QueryBuilder;
-import org.w3c.dom.Element;
-/**
- * Builder for {@link BoostingQuery}
- */
-public class BoostingQueryBuilder implements QueryBuilder {
-
- private static float DEFAULT_BOOST = 0.01f;
-
- private final QueryBuilder factory;
-
- public BoostingQueryBuilder(QueryBuilder factory) {
- this.factory = factory;
- }
-
- @Override
- public Query getQuery(Element e) throws ParserException {
- Element mainQueryElem = DOMUtils.getChildByTagOrFail(e, "Query");
- mainQueryElem = DOMUtils.getFirstChildOrFail(mainQueryElem);
- Query mainQuery = factory.getQuery(mainQueryElem);
-
- Element boostQueryElem = DOMUtils.getChildByTagOrFail(e, "BoostQuery");
- float boost = DOMUtils.getAttribute(boostQueryElem, "boost", DEFAULT_BOOST);
- boostQueryElem = DOMUtils.getFirstChildOrFail(boostQueryElem);
- Query boostQuery = factory.getQuery(boostQueryElem);
-
- Query bq = new BoostingQuery(mainQuery, boostQuery, boost);
-
- boost = DOMUtils.getAttribute(e, "boost", 1.0f);
- if (boost != 1f) {
- return new BoostQuery(bq, boost);
- }
- return bq;
- }
-}
[3/3] lucene-solr:master: LUCENE-8099: Deprecate CustomScoreQuery,
BoostedQuery, BoostingQuery
Posted by ro...@apache.org.
LUCENE-8099: Deprecate CustomScoreQuery, BoostedQuery, BoostingQuery
Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/b01e6023
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/b01e6023
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/b01e6023
Branch: refs/heads/master
Commit: b01e6023e1cd3c62260b38c05c8d145ba143a2ac
Parents: e441a99
Author: Alan Woodward <ro...@apache.org>
Authored: Thu Dec 14 12:09:51 2017 +0000
Committer: Alan Woodward <ro...@apache.org>
Committed: Mon Dec 18 17:47:03 2017 +0000
----------------------------------------------------------------------
lucene/CHANGES.txt | 4 +
.../org/apache/lucene/search/BoostQuery.java | 3 +
.../expressions/ExpressionValueSource.java | 6 +-
.../highlight/WeightedSpanTermExtractor.java | 5 +-
.../uhighlight/MultiTermHighlighting.java | 6 +-
.../search/vectorhighlight/FieldQuery.java | 8 +-
.../search/highlight/HighlighterTest.java | 24 +++
.../FastVectorHighlighterTest.java | 32 ++++
lucene/queries/build.xml | 8 +
.../apache/lucene/queries/BoostingQuery.java | 12 ++
.../apache/lucene/queries/CustomScoreQuery.java | 12 ++
.../lucene/queries/function/BoostedQuery.java | 15 +-
.../queries/function/FunctionScoreQuery.java | 7 +
.../function/TestFunctionScoreQuery.java | 145 +++++--------------
.../apache/solr/search/BoostQParserPlugin.java | 23 ++-
.../solr/search/ExtendedDismaxQParser.java | 5 +-
.../apache/solr/search/ValueSourceParser.java | 4 +-
17 files changed, 194 insertions(+), 125 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b01e6023/lucene/CHANGES.txt
----------------------------------------------------------------------
diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt
index db8aaab..ac70c4e 100644
--- a/lucene/CHANGES.txt
+++ b/lucene/CHANGES.txt
@@ -65,6 +65,10 @@ API Changes
* LUCENE-8051: LevensteinDistance renamed to LevenshteinDistance.
(Pulak Ghosh via Adrien Grand)
+* LUCENE-8099: Deprecate CustomScoreQuery, BoostedQuery and BoostingQuery.
+ Users should instead use FunctionScoreQuery, possibly combined with
+ a lucene expression (Alan Woodward)
+
New Features
* LUCENE-2899: Add new module analysis/opennlp, with analysis components
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b01e6023/lucene/core/src/java/org/apache/lucene/search/BoostQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/BoostQuery.java b/lucene/core/src/java/org/apache/lucene/search/BoostQuery.java
index 2c2cb78..4e4649c 100644
--- a/lucene/core/src/java/org/apache/lucene/search/BoostQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/BoostQuery.java
@@ -27,6 +27,9 @@ import org.apache.lucene.index.IndexReader;
* Boost values that are less than one will give less importance to this
* query compared to other ones while values that are greater than one will
* give more importance to the scores returned by this query.
+ *
+ * More complex boosts can be applied by using FunctionScoreQuery in the
+ * lucene-queries module
*/
public final class BoostQuery extends Query {
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b01e6023/lucene/expressions/src/java/org/apache/lucene/expressions/ExpressionValueSource.java
----------------------------------------------------------------------
diff --git a/lucene/expressions/src/java/org/apache/lucene/expressions/ExpressionValueSource.java b/lucene/expressions/src/java/org/apache/lucene/expressions/ExpressionValueSource.java
index 7b30b11..2bfafab 100644
--- a/lucene/expressions/src/java/org/apache/lucene/expressions/ExpressionValueSource.java
+++ b/lucene/expressions/src/java/org/apache/lucene/expressions/ExpressionValueSource.java
@@ -107,7 +107,7 @@ final class ExpressionValueSource extends DoubleValuesSource {
final int prime = 31;
int result = 1;
result = prime * result
- + ((expression == null) ? 0 : expression.hashCode());
+ + ((expression == null) ? 0 : expression.sourceText.hashCode());
result = prime * result + (needsScores ? 1231 : 1237);
result = prime * result + Arrays.hashCode(variables);
return result;
@@ -129,7 +129,7 @@ final class ExpressionValueSource extends DoubleValuesSource {
if (other.expression != null) {
return false;
}
- } else if (!expression.equals(other.expression)) {
+ } else if (!expression.sourceText.equals(other.expression.sourceText)) {
return false;
}
if (needsScores != other.needsScores) {
@@ -178,7 +178,7 @@ final class ExpressionValueSource extends DoubleValuesSource {
changed |= (rewritten[i] == variables[i]);
}
if (changed) {
- return new ExpressionValueSource(variables, expression, needsScores);
+ return new ExpressionValueSource(rewritten, expression, needsScores);
}
return this;
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b01e6023/lucene/highlighter/src/java/org/apache/lucene/search/highlight/WeightedSpanTermExtractor.java
----------------------------------------------------------------------
diff --git a/lucene/highlighter/src/java/org/apache/lucene/search/highlight/WeightedSpanTermExtractor.java b/lucene/highlighter/src/java/org/apache/lucene/search/highlight/WeightedSpanTermExtractor.java
index a05e9c6..8e6bf24 100644
--- a/lucene/highlighter/src/java/org/apache/lucene/search/highlight/WeightedSpanTermExtractor.java
+++ b/lucene/highlighter/src/java/org/apache/lucene/search/highlight/WeightedSpanTermExtractor.java
@@ -40,6 +40,7 @@ import org.apache.lucene.index.Terms;
import org.apache.lucene.index.memory.MemoryIndex;
import org.apache.lucene.queries.CommonTermsQuery;
import org.apache.lucene.queries.CustomScoreQuery;
+import org.apache.lucene.queries.function.FunctionScoreQuery;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.BoostQuery;
@@ -211,8 +212,10 @@ public class WeightedSpanTermExtractor {
}
} else if (query instanceof MatchAllDocsQuery) {
//nothing
- } else if (query instanceof CustomScoreQuery){
+ } else if (query instanceof CustomScoreQuery) {
extract(((CustomScoreQuery) query).getSubQuery(), boost, terms);
+ } else if (query instanceof FunctionScoreQuery) {
+ extract(((FunctionScoreQuery) query).getWrappedQuery(), boost, terms);
} else if (isQueryUnsupported(query.getClass())) {
// nothing
} else {
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b01e6023/lucene/highlighter/src/java/org/apache/lucene/search/uhighlight/MultiTermHighlighting.java
----------------------------------------------------------------------
diff --git a/lucene/highlighter/src/java/org/apache/lucene/search/uhighlight/MultiTermHighlighting.java b/lucene/highlighter/src/java/org/apache/lucene/search/uhighlight/MultiTermHighlighting.java
index e745d78..57d5afa 100644
--- a/lucene/highlighter/src/java/org/apache/lucene/search/uhighlight/MultiTermHighlighting.java
+++ b/lucene/highlighter/src/java/org/apache/lucene/search/uhighlight/MultiTermHighlighting.java
@@ -23,6 +23,7 @@ import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
+import org.apache.lucene.queries.function.FunctionScoreQuery;
import org.apache.lucene.search.AutomatonQuery;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
@@ -80,8 +81,11 @@ class MultiTermHighlighting {
list.addAll(Arrays.asList(extractAutomata(((ConstantScoreQuery) query).getQuery(), fieldMatcher, lookInSpan,
preRewriteFunc)));
} else if (query instanceof BoostQuery) {
- list.addAll(Arrays.asList(extractAutomata(((BoostQuery)query).getQuery(), fieldMatcher, lookInSpan,
+ list.addAll(Arrays.asList(extractAutomata(((BoostQuery) query).getQuery(), fieldMatcher, lookInSpan,
preRewriteFunc)));
+ } else if (query instanceof FunctionScoreQuery) {
+ list.addAll(Arrays.asList(extractAutomata(((FunctionScoreQuery) query).getWrappedQuery(), fieldMatcher,
+ lookInSpan, preRewriteFunc)));
} else if (query instanceof DisjunctionMaxQuery) {
for (Query sub : ((DisjunctionMaxQuery) query).getDisjuncts()) {
list.addAll(Arrays.asList(extractAutomata(sub, fieldMatcher, lookInSpan, preRewriteFunc)));
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b01e6023/lucene/highlighter/src/java/org/apache/lucene/search/vectorhighlight/FieldQuery.java
----------------------------------------------------------------------
diff --git a/lucene/highlighter/src/java/org/apache/lucene/search/vectorhighlight/FieldQuery.java b/lucene/highlighter/src/java/org/apache/lucene/search/vectorhighlight/FieldQuery.java
index 0fd336a..6daa791 100644
--- a/lucene/highlighter/src/java/org/apache/lucene/search/vectorhighlight/FieldQuery.java
+++ b/lucene/highlighter/src/java/org/apache/lucene/search/vectorhighlight/FieldQuery.java
@@ -28,6 +28,7 @@ import java.util.Set;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.queries.CustomScoreQuery;
+import org.apache.lucene.queries.function.FunctionScoreQuery;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.BoostQuery;
@@ -143,7 +144,12 @@ public class FieldQuery {
} else if (sourceQuery instanceof CustomScoreQuery) {
final Query q = ((CustomScoreQuery) sourceQuery).getSubQuery();
if (q != null) {
- flatten( q, reader, flatQueries, boost);
+ flatten(q, reader, flatQueries, boost);
+ }
+ } else if (sourceQuery instanceof FunctionScoreQuery) {
+ final Query q = ((FunctionScoreQuery)sourceQuery).getWrappedQuery();
+ if (q != null) {
+ flatten(q, reader, flatQueries, boost);
}
} else if (sourceQuery instanceof ToParentBlockJoinQuery) {
Query childQuery = ((ToParentBlockJoinQuery) sourceQuery).getChildQuery();
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b01e6023/lucene/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterTest.java
----------------------------------------------------------------------
diff --git a/lucene/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterTest.java b/lucene/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterTest.java
index d03432e..cf14e27 100644
--- a/lucene/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterTest.java
+++ b/lucene/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterTest.java
@@ -59,10 +59,12 @@ import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.index.Term;
import org.apache.lucene.queries.CommonTermsQuery;
import org.apache.lucene.queries.CustomScoreQuery;
+import org.apache.lucene.queries.function.FunctionScoreQuery;
import org.apache.lucene.queries.payloads.SpanPayloadCheckQuery;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.ConstantScoreQuery;
+import org.apache.lucene.search.DoubleValuesSource;
import org.apache.lucene.search.FuzzyQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.MultiPhraseQuery;
@@ -166,6 +168,28 @@ public class HighlighterTest extends BaseTokenStreamTestCase implements Formatte
}
+ public void testFunctionScoreQuery() throws Exception {
+ TermQuery termQuery = new TermQuery(new Term(FIELD_NAME, "very"));
+ FunctionScoreQuery query = new FunctionScoreQuery(termQuery, DoubleValuesSource.constant(1));
+
+ searcher = newSearcher(reader);
+ TopDocs hits = searcher.search(query, 10, new Sort(SortField.FIELD_DOC, SortField.FIELD_SCORE));
+ assertEquals(2, hits.totalHits);
+ QueryScorer scorer = new QueryScorer(query, FIELD_NAME);
+ Highlighter highlighter = new Highlighter(scorer);
+
+ final int docId0 = hits.scoreDocs[0].doc;
+ Document doc = searcher.doc(docId0);
+ String storedField = doc.get(FIELD_NAME);
+
+ TokenStream stream = getAnyTokenStream(FIELD_NAME, docId0);
+ Fragmenter fragmenter = new SimpleSpanFragmenter(scorer);
+ highlighter.setTextFragmenter(fragmenter);
+ String fragment = highlighter.getBestFragment(stream, storedField);
+ assertEquals("Hello this is a piece of text that is <B>very</B> long and contains too much preamble and the meat is really here which says kennedy has been shot", fragment);
+
+ }
+
public void testQueryScorerHits() throws Exception {
PhraseQuery phraseQuery = new PhraseQuery(FIELD_NAME, "very", "long");
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b01e6023/lucene/highlighter/src/test/org/apache/lucene/search/vectorhighlight/FastVectorHighlighterTest.java
----------------------------------------------------------------------
diff --git a/lucene/highlighter/src/test/org/apache/lucene/search/vectorhighlight/FastVectorHighlighterTest.java b/lucene/highlighter/src/test/org/apache/lucene/search/vectorhighlight/FastVectorHighlighterTest.java
index 89f46af..732f62f 100644
--- a/lucene/highlighter/src/test/org/apache/lucene/search/vectorhighlight/FastVectorHighlighterTest.java
+++ b/lucene/highlighter/src/test/org/apache/lucene/search/vectorhighlight/FastVectorHighlighterTest.java
@@ -39,10 +39,12 @@ import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.queries.CommonTermsQuery;
import org.apache.lucene.queries.CustomScoreQuery;
+import org.apache.lucene.queries.function.FunctionScoreQuery;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.BoostQuery;
+import org.apache.lucene.search.DoubleValuesSource;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.PhraseQuery;
import org.apache.lucene.search.Query;
@@ -119,6 +121,36 @@ public class FastVectorHighlighterTest extends LuceneTestCase {
writer.close();
dir.close();
}
+
+ public void testFunctionScoreQueryHighlight() throws IOException {
+ Directory dir = newDirectory();
+ IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(new MockAnalyzer(random())));
+ Document doc = new Document();
+ FieldType type = new FieldType(TextField.TYPE_STORED);
+ type.setStoreTermVectorOffsets(true);
+ type.setStoreTermVectorPositions(true);
+ type.setStoreTermVectors(true);
+ type.freeze();
+ Field field = new Field("field", "This is a test where foo is highlighed and should be highlighted", type);
+
+ doc.add(field);
+ writer.addDocument(doc);
+ FastVectorHighlighter highlighter = new FastVectorHighlighter();
+
+ IndexReader reader = DirectoryReader.open(writer);
+ int docId = 0;
+ FieldQuery fieldQuery = highlighter.getFieldQuery( new FunctionScoreQuery(new TermQuery(new Term("field", "foo")), DoubleValuesSource.constant(1)), reader );
+ String[] bestFragments = highlighter.getBestFragments(fieldQuery, reader, docId, "field", 54, 1);
+ // highlighted results are centered
+ assertEquals("This is a test where <b>foo</b> is highlighed and should be highlighted", bestFragments[0]);
+ bestFragments = highlighter.getBestFragments(fieldQuery, reader, docId, "field", 52, 1);
+ assertEquals("This is a test where <b>foo</b> is highlighed and should be", bestFragments[0]);
+ bestFragments = highlighter.getBestFragments(fieldQuery, reader, docId, "field", 30, 1);
+ assertEquals("a test where <b>foo</b> is highlighed", bestFragments[0]);
+ reader.close();
+ writer.close();
+ dir.close();
+ }
public void testPhraseHighlightLongTextTest() throws IOException {
Directory dir = newDirectory();
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b01e6023/lucene/queries/build.xml
----------------------------------------------------------------------
diff --git a/lucene/queries/build.xml b/lucene/queries/build.xml
index 5edb64d..20f9c4f 100644
--- a/lucene/queries/build.xml
+++ b/lucene/queries/build.xml
@@ -21,4 +21,12 @@
</description>
<import file="../module-build.xml"/>
+
+ <path id="test.classpath">
+ <pathelement path="${expressions.jar}"/>
+ <fileset dir="../expressions/lib"/>
+ <path refid="test.base.classpath"/>
+ </path>
+
+ <target name="compile-core" depends="jar-expressions,common.compile-core" />
</project>
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b01e6023/lucene/queries/src/java/org/apache/lucene/queries/BoostingQuery.java
----------------------------------------------------------------------
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/BoostingQuery.java b/lucene/queries/src/java/org/apache/lucene/queries/BoostingQuery.java
index dfebd98..452cbe6 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/BoostingQuery.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/BoostingQuery.java
@@ -48,7 +48,19 @@ import org.apache.lucene.search.Weight;
* This code was originally made available here:
* <a href="http://marc.theaimsgroup.com/?l=lucene-user&m=108058407130459&w=2">http://marc.theaimsgroup.com/?l=lucene-user&m=108058407130459&w=2</a>
* and is documented here: http://wiki.apache.org/lucene-java/CommunityContributions
+ *
+ * Clients should instead use FunctionScoreQuery and the lucene-expressions library:
+ * <pre>
+ * SimpleBindings bindings = new SimpleBindings();
+ * bindings.add("score", DoubleValuesSource.SCORES);
+ * bindings.add("context", DoubleValuesSource.fromQuery(new ConstantScoreQuery(myContextQuery, boost)));
+ * Expression expr = JavascriptCompiler.compile("score * context");
+ * FunctionScoreQuery q = new FunctionScoreQuery(inputQuery, expr.getDoubleValuesSource(bindings));
+ * </pre>
+ *
+ * @deprecated Use {@link org.apache.lucene.queries.function.FunctionScoreQuery}
*/
+@Deprecated
public class BoostingQuery extends Query {
private final float boost; // the amount to boost by
private final Query match; // query to match
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b01e6023/lucene/queries/src/java/org/apache/lucene/queries/CustomScoreQuery.java
----------------------------------------------------------------------
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/CustomScoreQuery.java b/lucene/queries/src/java/org/apache/lucene/queries/CustomScoreQuery.java
index 62a1787..f82cf50 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/CustomScoreQuery.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/CustomScoreQuery.java
@@ -43,7 +43,19 @@ import org.apache.lucene.search.Weight;
* Subclasses can modify the computation by overriding {@link #getCustomScoreProvider}.
*
* @lucene.experimental
+ *
+ * Clients should instead use FunctionScoreQuery and the lucene-expressions library
+ * <pre>
+ * SimpleBindings bindings = new SimpleBindings();
+ * bindings.add("score", DoubleValuesSource.SCORES);
+ * bindings.add("boost", DoubleValuesSource.fromIntField("myboostfield"));
+ * Expression expr = JavascriptCompiler.compile("score * boost");
+ * FunctionScoreQuery q = new FunctionScoreQuery(inputQuery, expr.getDoubleValuesSource(bindings));
+ * </pre>
+ *
+ * @deprecated use {@link org.apache.lucene.queries.function.FunctionScoreQuery}
*/
+@Deprecated
public class CustomScoreQuery extends Query implements Cloneable {
private Query subQuery;
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b01e6023/lucene/queries/src/java/org/apache/lucene/queries/function/BoostedQuery.java
----------------------------------------------------------------------
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/BoostedQuery.java b/lucene/queries/src/java/org/apache/lucene/queries/function/BoostedQuery.java
index df3ab47..ddb261a 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/BoostedQuery.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/BoostedQuery.java
@@ -35,9 +35,20 @@ import org.apache.lucene.search.Weight;
/**
* Query that is boosted by a ValueSource
+ *
+ * Instead of using this query, clients can use a {@link FunctionScoreQuery} and the
+ * lucene-expressions library:
+ * <pre>
+ * SimpleBindings bindings = new SimpleBindings();
+ * bindings.add("score", DoubleValuesSource.SCORES);
+ * bindings.add("boost", DoubleValuesSource.fromIntField("myboostfield"));
+ * Expression expr = JavascriptCompiler.compile("score * boost");
+ * FunctionScoreQuery q = new FunctionScoreQuery(inputQuery, expr.getDoubleValuesSource(bindings));
+ * </pre>
+ *
+ * @deprecated Use {@link FunctionScoreQuery}
*/
-// TODO: BoostedQuery and BoostingQuery in the same module?
-// something has to give
+@Deprecated
public final class BoostedQuery extends Query {
private final Query q;
private final ValueSource boostVal; // optional, can be null
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b01e6023/lucene/queries/src/java/org/apache/lucene/queries/function/FunctionScoreQuery.java
----------------------------------------------------------------------
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/FunctionScoreQuery.java b/lucene/queries/src/java/org/apache/lucene/queries/function/FunctionScoreQuery.java
index 649ba6e..d264267 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/FunctionScoreQuery.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/FunctionScoreQuery.java
@@ -56,6 +56,13 @@ public final class FunctionScoreQuery extends Query {
this.source = source;
}
+ /**
+ * @return the wrapped Query
+ */
+ public Query getWrappedQuery() {
+ return in;
+ }
+
@Override
public Weight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
Weight inner = in.createWeight(searcher, scoreMode.needsScores() && source.needsScores() ? scoreMode : ScoreMode.COMPLETE_NO_SCORES, 1f);
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b01e6023/lucene/queries/src/test/org/apache/lucene/queries/function/TestFunctionScoreQuery.java
----------------------------------------------------------------------
diff --git a/lucene/queries/src/test/org/apache/lucene/queries/function/TestFunctionScoreQuery.java b/lucene/queries/src/test/org/apache/lucene/queries/function/TestFunctionScoreQuery.java
index d70d5f3..301dce7 100644
--- a/lucene/queries/src/test/org/apache/lucene/queries/function/TestFunctionScoreQuery.java
+++ b/lucene/queries/src/test/org/apache/lucene/queries/function/TestFunctionScoreQuery.java
@@ -18,20 +18,19 @@
package org.apache.lucene.queries.function;
import java.io.IOException;
-import java.util.function.DoubleUnaryOperator;
-import java.util.function.ToDoubleBiFunction;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.NumericDocValuesField;
+import org.apache.lucene.expressions.Expression;
+import org.apache.lucene.expressions.SimpleBindings;
+import org.apache.lucene.expressions.js.JavascriptCompiler;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
-import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.BoostQuery;
-import org.apache.lucene.search.DoubleValues;
import org.apache.lucene.search.DoubleValuesSource;
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.IndexSearcher;
@@ -81,8 +80,10 @@ public class TestFunctionScoreQuery extends FunctionTestSetup {
// CustomScoreQuery and BoostedQuery equivalent
public void testScoreModifyingSource() throws Exception {
- DoubleValuesSource iii = DoubleValuesSource.fromIntField("iii");
- DoubleValuesSource score = scoringFunction(iii, (v, s) -> v * s);
+ SimpleBindings bindings = new SimpleBindings();
+ bindings.add("score", DoubleValuesSource.SCORES);
+ bindings.add("iii", DoubleValuesSource.fromIntField("iii"));
+ Expression expr = JavascriptCompiler.compile("score * iii");
BooleanQuery bq = new BooleanQuery.Builder()
.add(new TermQuery(new Term(TEXT_FIELD, "first")), BooleanClause.Occur.SHOULD)
@@ -90,7 +91,7 @@ public class TestFunctionScoreQuery extends FunctionTestSetup {
.build();
TopDocs plain = searcher.search(bq, 1);
- FunctionScoreQuery fq = new FunctionScoreQuery(bq, score);
+ FunctionScoreQuery fq = new FunctionScoreQuery(bq, expr.getDoubleValuesSource(bindings));
QueryUtils.check(random(), fq, searcher, rarely());
@@ -104,12 +105,38 @@ public class TestFunctionScoreQuery extends FunctionTestSetup {
}
+ // BoostingQuery equivalent
+ public void testCombiningMultipleQueryScores() throws Exception {
+
+ SimpleBindings bindings = new SimpleBindings();
+ bindings.add("score", DoubleValuesSource.SCORES);
+ bindings.add("testquery", DoubleValuesSource.fromQuery(new TermQuery(new Term(TEXT_FIELD, "rechecking"))));
+ Expression expr = JavascriptCompiler.compile("score + (testquery * 100)");
+
+ TermQuery q = new TermQuery(new Term(TEXT_FIELD, "text"));
+ TopDocs plain = searcher.search(q, 1);
+
+ FunctionScoreQuery fq = new FunctionScoreQuery(q, expr.getDoubleValuesSource(bindings));
+
+ QueryUtils.check(random(), fq, searcher, rarely());
+
+ int[] expectedDocs = new int[]{ 6, 1, 0, 2, 8 };
+ TopDocs docs = searcher.search(fq, 5);
+ assertEquals(plain.totalHits, docs.totalHits);
+ for (int i = 0; i < expectedDocs.length; i++) {
+ assertEquals(expectedDocs[i], docs.scoreDocs[i].doc);
+
+ }
+ }
+
// check boosts with non-distributive score source
public void testBoostsAreAppliedLast() throws Exception {
- DoubleValuesSource scores = function(DoubleValuesSource.SCORES, v -> Math.log(v + 4));
+ SimpleBindings bindings = new SimpleBindings();
+ bindings.add("score", DoubleValuesSource.SCORES);
+ Expression expr = JavascriptCompiler.compile("ln(score + 4)");
- Query q1 = new FunctionScoreQuery(new TermQuery(new Term(TEXT_FIELD, "text")), scores);
+ Query q1 = new FunctionScoreQuery(new TermQuery(new Term(TEXT_FIELD, "text")), expr.getDoubleValuesSource(bindings));
TopDocs plain = searcher.search(q1, 5);
Query boosted = new BoostQuery(q1, 2);
@@ -122,106 +149,6 @@ public class TestFunctionScoreQuery extends FunctionTestSetup {
}
- public static DoubleValuesSource function(DoubleValuesSource in, DoubleUnaryOperator function) {
- return new DoubleValuesSource() {
- @Override
- public DoubleValues getValues(LeafReaderContext ctx, DoubleValues scores) throws IOException {
- DoubleValues v = in.getValues(ctx, scores);
- return new DoubleValues() {
- @Override
- public double doubleValue() throws IOException {
- return function.applyAsDouble(v.doubleValue());
- }
-
- @Override
- public boolean advanceExact(int doc) throws IOException {
- return v.advanceExact(doc);
- }
- };
- }
-
- @Override
- public boolean needsScores() {
- return in.needsScores();
- }
-
- @Override
- public boolean isCacheable(LeafReaderContext ctx) {
- return in.isCacheable(ctx);
- }
-
- @Override
- public DoubleValuesSource rewrite(IndexSearcher searcher) throws IOException {
- return function(in.rewrite(searcher), function);
- }
-
- @Override
- public int hashCode() {
- return 0;
- }
-
- @Override
- public boolean equals(Object obj) {
- return false;
- }
-
- @Override
- public String toString() {
- return "fn";
- }
- };
- }
-
- private static DoubleValuesSource scoringFunction(DoubleValuesSource in, ToDoubleBiFunction<Double, Double> function) {
- return new DoubleValuesSource() {
- @Override
- public DoubleValues getValues(LeafReaderContext ctx, DoubleValues scores) throws IOException {
- DoubleValues v = in.getValues(ctx, scores);
- return new DoubleValues() {
- @Override
- public double doubleValue() throws IOException {
- return function.applyAsDouble(v.doubleValue(), scores.doubleValue());
- }
-
- @Override
- public boolean advanceExact(int doc) throws IOException {
- return v.advanceExact(doc);
- }
- };
- }
-
- @Override
- public boolean needsScores() {
- return true;
- }
-
- @Override
- public boolean isCacheable(LeafReaderContext ctx) {
- return in.isCacheable(ctx);
- }
-
- @Override
- public DoubleValuesSource rewrite(IndexSearcher searcher) throws IOException {
- return scoringFunction(in.rewrite(searcher), function);
- }
-
- @Override
- public int hashCode() {
- return 0;
- }
-
- @Override
- public boolean equals(Object obj) {
- return false;
- }
-
- @Override
- public String toString() {
- return "fn";
- }
- };
- }
-
public void testTruncateNegativeScores() throws IOException {
Directory dir = newDirectory();
IndexWriter w = new IndexWriter(dir, newIndexWriterConfig());
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b01e6023/solr/core/src/java/org/apache/solr/search/BoostQParserPlugin.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/BoostQParserPlugin.java b/solr/core/src/java/org/apache/solr/search/BoostQParserPlugin.java
index 5f7add8..7391f66 100644
--- a/solr/core/src/java/org/apache/solr/search/BoostQParserPlugin.java
+++ b/solr/core/src/java/org/apache/solr/search/BoostQParserPlugin.java
@@ -16,11 +16,18 @@
*/
package org.apache.solr.search;
-import org.apache.lucene.queries.function.BoostedQuery;
+import java.text.ParseException;
+
+import org.apache.lucene.expressions.Expression;
+import org.apache.lucene.expressions.SimpleBindings;
+import org.apache.lucene.expressions.js.JavascriptCompiler;
import org.apache.lucene.queries.function.FunctionQuery;
+import org.apache.lucene.queries.function.FunctionScoreQuery;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.queries.function.valuesource.QueryValueSource;
+import org.apache.lucene.search.DoubleValuesSource;
import org.apache.lucene.search.Query;
+import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.request.SolrQueryRequest;
@@ -60,7 +67,7 @@ public class BoostQParserPlugin extends QParserPlugin {
} else {
vs = new QueryValueSource(bq, 0.0f);
}
- return new BoostedQuery(q, vs);
+ return boostQuery(q, vs);
}
@@ -84,4 +91,16 @@ public class BoostQParserPlugin extends QParserPlugin {
};
}
+ public static Query boostQuery(Query input, ValueSource vs) {
+ try {
+ SimpleBindings bindings = new SimpleBindings();
+ bindings.add("score", DoubleValuesSource.SCORES);
+ bindings.add("vs", vs.asDoubleValuesSource());
+ Expression expr = JavascriptCompiler.compile("score * vs");
+ return new FunctionScoreQuery(input, expr.getDoubleValuesSource(bindings));
+ } catch (ParseException e) {
+ throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, e); // should never happen!
+ }
+ }
+
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b01e6023/solr/core/src/java/org/apache/solr/search/ExtendedDismaxQParser.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/ExtendedDismaxQParser.java b/solr/core/src/java/org/apache/solr/search/ExtendedDismaxQParser.java
index c48d127..5e74f4a 100644
--- a/solr/core/src/java/org/apache/solr/search/ExtendedDismaxQParser.java
+++ b/solr/core/src/java/org/apache/solr/search/ExtendedDismaxQParser.java
@@ -33,7 +33,6 @@ import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.core.StopFilterFactory;
import org.apache.lucene.analysis.util.TokenFilterFactory;
import org.apache.lucene.index.Term;
-import org.apache.lucene.queries.function.BoostedQuery;
import org.apache.lucene.queries.function.FunctionQuery;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.queries.function.valuesource.ProductFloatFunction;
@@ -197,9 +196,9 @@ public class ExtendedDismaxQParser extends QParser {
List<ValueSource> boosts = getMultiplicativeBoosts();
if (boosts.size()>1) {
ValueSource prod = new ProductFloatFunction(boosts.toArray(new ValueSource[boosts.size()]));
- topQuery = new BoostedQuery(topQuery, prod);
+ topQuery = BoostQParserPlugin.boostQuery(topQuery, prod);
} else if (boosts.size() == 1) {
- topQuery = new BoostedQuery(topQuery, boosts.get(0));
+ topQuery = BoostQParserPlugin.boostQuery(topQuery, boosts.get(0));
}
return topQuery;
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b01e6023/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java b/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java
index dc6411e..367eb64 100644
--- a/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java
+++ b/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java
@@ -27,7 +27,6 @@ import java.util.Map;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.Term;
-import org.apache.lucene.queries.function.BoostedQuery;
import org.apache.lucene.queries.function.FunctionValues;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.queries.function.docvalues.BoolDocValues;
@@ -326,8 +325,7 @@ public abstract class ValueSourceParser implements NamedListInitializedPlugin {
public ValueSource parse(FunctionQParser fp) throws SyntaxError {
Query q = fp.parseNestedQuery();
ValueSource vs = fp.parseValueSource();
- BoostedQuery bq = new BoostedQuery(q, vs);
- return new QueryValueSource(bq, 0.0f);
+ return new QueryValueSource(BoostQParserPlugin.boostQuery(q, vs), 0.0f);
}
});
addParser("joindf", new ValueSourceParser() {