You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by da...@apache.org on 2018/01/11 08:00:45 UTC
[09/50] [abbrv] lucene-solr:jira/solr-11702: LUCENE-8099: Add some
static methods to FunctionScoreQuery to replace Boosting/BoostedQuery
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/79bd05da
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/79bd05da
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/79bd05da
Branch: refs/heads/jira/solr-11702
Commit: 79bd05da4dcbb584fffaf62bea683c00d3ac432c
Parents: 5a08fa8
Author: Alan Woodward <ro...@apache.org>
Authored: Wed Jan 3 15:28:23 2018 +0000
Committer: Alan Woodward <ro...@apache.org>
Committed: Fri Jan 5 09:32:05 2018 +0000
----------------------------------------------------------------------
.../queries/function/FunctionScoreQuery.java | 151 +++++++++++++++++++
.../function/TestFunctionScoreQuery.java | 19 +--
2 files changed, 156 insertions(+), 14 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/79bd05da/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 d264267..09a592b 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
@@ -63,6 +63,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, ScoreMode scoreMode, float boost) throws IOException {
Weight inner = in.createWeight(searcher, scoreMode.needsScores() && source.needsScores() ? scoreMode : ScoreMode.COMPLETE_NO_SCORES, 1f);
@@ -189,4 +221,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/79bd05da/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 c0560bc..4e82eb2 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
@@ -80,18 +80,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());
@@ -108,20 +103,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);