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&amp;m=108058407130459&amp;w=2">http://marc.theaimsgroup.com/?l=lucene-user&amp;m=108058407130459&amp;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&amp;m=108058407130459&amp;w=2">http://marc.theaimsgroup.com/?l=lucene-user&amp;m=108058407130459&amp;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 &lt; 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 &lt; 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&amp;m=108058407130459&amp;w=2">http://marc.theaimsgroup.com/?l=lucene-user&amp;m=108058407130459&amp;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() {