lucene-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From romseyg...@apache.org
Subject [2/2] lucene-solr:branch_7x: LUCENE-8099: Add some static methods to FunctionScoreQuery to replace Boosting/BoostedQuery
Date Fri, 05 Jan 2018 10:06:11 GMT
LUCENE-8099: Add some static methods to FunctionScoreQuery to replace Boosting/BoostedQuery


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/42154387
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/42154387
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/42154387

Branch: refs/heads/branch_7x
Commit: 42154387d4f2a6060da09c4236e2a8dbb575c59e
Parents: b09ee29
Author: Alan Woodward <romseygeek@apache.org>
Authored: Wed Jan 3 15:28:23 2018 +0000
Committer: Alan Woodward <romseygeek@apache.org>
Committed: Fri Jan 5 09:47:22 2018 +0000

----------------------------------------------------------------------
 .../apache/lucene/queries/BoostingQuery.java    |  11 +-
 .../apache/lucene/queries/CustomScoreQuery.java |  11 +-
 .../lucene/queries/function/BoostedQuery.java   |  13 +-
 .../queries/function/FunctionScoreQuery.java    | 151 +++++++++++++++++++
 .../function/TestFunctionScoreQuery.java        |  19 +--
 5 files changed, 167 insertions(+), 38 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/42154387/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 c0da720..4f0cb09 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/BoostingQuery.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/BoostingQuery.java
@@ -48,16 +48,7 @@ import org.apache.lucene.search.Weight;
  *   <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 Use {@link org.apache.lucene.queries.function.FunctionScoreQuery#boostByQuery(Query,
Query, float)}
  */
 @Deprecated
 public class BoostingQuery extends Query {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/42154387/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 eb4cfc8..3d4bcad 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/CustomScoreQuery.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/CustomScoreQuery.java
@@ -26,6 +26,8 @@ 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.queries.function.FunctionScoreQuery;
+import org.apache.lucene.search.DoubleValuesSource;
 import org.apache.lucene.search.Explanation;
 import org.apache.lucene.search.FilterScorer;
 import org.apache.lucene.search.IndexSearcher;
@@ -43,12 +45,15 @@ import org.apache.lucene.search.Weight;
  * 
  * @lucene.experimental
  *
- * Clients should instead use FunctionScoreQuery and the lucene-expressions library
+ * Clients should instead use FunctionScoreQuery.  For simple multiplicative boosts, use
+ * {@link FunctionScoreQuery#boostByValue(Query, DoubleValuesSource)}.  For more complex
+ * custom scores, use 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");
+ *   bindings.add("boost1", DoubleValuesSource.fromIntField("myboostfield"));
+ *   bindings.add("boost2", DoubleValuesSource.fromIntField("myotherboostfield"));
+ *   Expression expr = JavascriptCompiler.compile("score * (boost1 + ln(boost2))");
  *   FunctionScoreQuery q = new FunctionScoreQuery(inputQuery, expr.getDoubleValuesSource(bindings));
  * </pre>
  *

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/42154387/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 0dcb1df..4288198 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
@@ -25,6 +25,7 @@ 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.DoubleValuesSource;
 import org.apache.lucene.search.Explanation;
 import org.apache.lucene.search.FilterScorer;
 import org.apache.lucene.search.IndexSearcher;
@@ -35,17 +36,7 @@ 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 Use {@link FunctionScoreQuery#boostByValue(Query, DoubleValuesSource)}
  */
 @Deprecated
 public final class BoostedQuery extends Query {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/42154387/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 60aa9f0..174fded 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
@@ -62,6 +62,38 @@ public final class FunctionScoreQuery extends Query {
     return in;
   }
 
+  /**
+   * Returns a FunctionScoreQuery where the scores of a wrapped query are multiplied by
+   * the value of a DoubleValuesSource.
+   *
+   * If the source has no value for a particular document, the score for that document
+   * is preserved as-is.
+   *
+   * @param in    the query to boost
+   * @param boost a {@link DoubleValuesSource} containing the boost values
+   */
+  public static FunctionScoreQuery boostByValue(Query in, DoubleValuesSource boost) {
+    return new FunctionScoreQuery(in, new MultiplicativeBoostValuesSource(boost));
+  }
+
+  /**
+   * Returns a FunctionScoreQuery where the scores of a wrapped query are multiplied by
+   * a boost factor if the document being scored also matches a separate boosting query.
+   *
+   * Documents that do not match the boosting query have their scores preserved.
+   *
+   * This may be used to 'demote' documents that match the boosting query, by passing in
+   * a boostValue between 0 and 1.
+   *
+   * @param in          the query to boost
+   * @param boostMatch  the boosting query
+   * @param boostValue  the amount to boost documents which match the boosting query
+   */
+  public static FunctionScoreQuery boostByQuery(Query in, Query boostMatch, float boostValue)
{
+    return new FunctionScoreQuery(in,
+        new MultiplicativeBoostValuesSource(new QueryBoostValuesSource(DoubleValuesSource.fromQuery(boostMatch),
boostValue)));
+  }
+
   @Override
   public Weight createWeight(IndexSearcher searcher, boolean needsScores, float boost) throws
IOException {
     Weight inner = in.createWeight(searcher, needsScores && source.needsScores(),
1f);
@@ -149,4 +181,123 @@ public final class FunctionScoreQuery extends Query {
     }
 
   }
+
+  private static class MultiplicativeBoostValuesSource extends DoubleValuesSource {
+
+    private final DoubleValuesSource boost;
+
+    private MultiplicativeBoostValuesSource(DoubleValuesSource boost) {
+      this.boost = boost;
+    }
+
+    @Override
+    public DoubleValues getValues(LeafReaderContext ctx, DoubleValues scores) throws IOException
{
+      DoubleValues in = DoubleValues.withDefault(boost.getValues(ctx, scores), 1);
+      return new DoubleValues() {
+        @Override
+        public double doubleValue() throws IOException {
+          return scores.doubleValue() * in.doubleValue();
+        }
+
+        @Override
+        public boolean advanceExact(int doc) throws IOException {
+          return in.advanceExact(doc);
+        }
+      };
+    }
+
+    @Override
+    public boolean needsScores() {
+      return true;
+    }
+
+    @Override
+    public DoubleValuesSource rewrite(IndexSearcher reader) throws IOException {
+      return new MultiplicativeBoostValuesSource(boost.rewrite(reader));
+    }
+
+    @Override
+    public boolean equals(Object o) {
+      if (this == o) return true;
+      if (o == null || getClass() != o.getClass()) return false;
+      MultiplicativeBoostValuesSource that = (MultiplicativeBoostValuesSource) o;
+      return Objects.equals(boost, that.boost);
+    }
+
+    @Override
+    public int hashCode() {
+      return Objects.hash(boost);
+    }
+
+    @Override
+    public String toString() {
+      return "boost(" + boost.toString() + ")";
+    }
+
+    @Override
+    public boolean isCacheable(LeafReaderContext ctx) {
+      return boost.isCacheable(ctx);
+    }
+  }
+
+  private static class QueryBoostValuesSource extends DoubleValuesSource {
+
+    private final DoubleValuesSource query;
+    private final float boost;
+
+    QueryBoostValuesSource(DoubleValuesSource query, float boost) {
+      this.query = query;
+      this.boost = boost;
+    }
+
+    @Override
+    public DoubleValues getValues(LeafReaderContext ctx, DoubleValues scores) throws IOException
{
+      DoubleValues in = query.getValues(ctx, null);
+      return DoubleValues.withDefault(new DoubleValues() {
+        @Override
+        public double doubleValue() {
+          return boost;
+        }
+
+        @Override
+        public boolean advanceExact(int doc) throws IOException {
+          return in.advanceExact(doc);
+        }
+      }, 1);
+    }
+
+    @Override
+    public boolean needsScores() {
+      return false;
+    }
+
+    @Override
+    public DoubleValuesSource rewrite(IndexSearcher reader) throws IOException {
+      return new QueryBoostValuesSource(query.rewrite(reader), boost);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+      if (this == o) return true;
+      if (o == null || getClass() != o.getClass()) return false;
+      QueryBoostValuesSource that = (QueryBoostValuesSource) o;
+      return Float.compare(that.boost, boost) == 0 &&
+          Objects.equals(query, that.query);
+    }
+
+    @Override
+    public int hashCode() {
+      return Objects.hash(query, boost);
+    }
+
+    @Override
+    public String toString() {
+      return "queryboost(" + query + ")^" + boost;
+    }
+
+    @Override
+    public boolean isCacheable(LeafReaderContext ctx) {
+      return query.isCacheable(ctx);
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/42154387/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 3349cd8..5803189 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
@@ -72,18 +72,13 @@ public class TestFunctionScoreQuery extends FunctionTestSetup {
   // CustomScoreQuery and BoostedQuery equivalent
   public void testScoreModifyingSource() throws Exception {
 
-    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)
         .add(new TermQuery(new Term(TEXT_FIELD, "text")), BooleanClause.Occur.SHOULD)
         .build();
     TopDocs plain = searcher.search(bq, 1);
 
-    FunctionScoreQuery fq = new FunctionScoreQuery(bq, expr.getDoubleValuesSource(bindings));
+    FunctionScoreQuery fq = FunctionScoreQuery.boostByValue(bq, DoubleValuesSource.fromIntField("iii"));
 
     QueryUtils.check(random(), fq, searcher, rarely());
 
@@ -100,20 +95,16 @@ 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));
+    FunctionScoreQuery fq
+        = FunctionScoreQuery.boostByQuery(q, new TermQuery(new Term(TEXT_FIELD, "rechecking")),
100f);
 
     QueryUtils.check(random(), fq, searcher, rarely());
 
-    int[] expectedDocs = new int[]{  6, 1, 0, 2, 8 };
-    TopDocs docs = searcher.search(fq, 5);
+    int[] expectedDocs = new int[]{ 6, 1, 0, 2, 8 };
+    TopDocs docs = searcher.search(fq, 20);
     assertEquals(plain.totalHits, docs.totalHits);
     for (int i = 0; i < expectedDocs.length; i++) {
       assertEquals(expectedDocs[i], docs.scoreDocs[i].doc);


Mime
View raw message