You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by cp...@apache.org on 2020/11/12 13:15:14 UTC

[lucene-solr] branch master updated: SOLR-14983: Fix response returning original score instead of reranked score due to query and filter combining. (Krishan Goyal, Jason Baik, Christine Poerschke)

This is an automated email from the ASF dual-hosted git repository.

cpoerschke pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git


The following commit(s) were added to refs/heads/master by this push:
     new 2f02040  SOLR-14983: Fix response returning original score instead of reranked score due to query and filter combining. (Krishan Goyal, Jason Baik, Christine Poerschke)
2f02040 is described below

commit 2f02040a4c45e4dfdb1f569ae05637c86f0f001b
Author: Christine Poerschke <cp...@apache.org>
AuthorDate: Thu Nov 12 12:51:21 2020 +0000

    SOLR-14983: Fix response returning original score instead of reranked score due to query and filter combining.
    (Krishan Goyal, Jason Baik, Christine Poerschke)
---
 solr/CHANGES.txt                                   |   3 +
 .../org/apache/solr/search/SolrIndexSearcher.java  |   4 +-
 .../apache/solr/search/SolrIndexSearcherTest.java  | 123 +++++++++++++++++++++
 3 files changed, 128 insertions(+), 2 deletions(-)

diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index d566549..28c9ab4 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -194,6 +194,9 @@ Bug Fixes
 
 * SOLR-14971: AtomicUpdate 'remove', 'add-distinct' operations now works on numeric, date fields in uncommitted docs (Jason Gerlowski)
 
+* SOLR-14983: Fix response returning original score instead of reranked score due to query and filter combining.
+  (Krishan Goyal, Jason Baik, Christine Poerschke)
+
 Other Changes
 ---------------------
 
diff --git a/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java b/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java
index b511207..9a5ac70 100644
--- a/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java
+++ b/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java
@@ -1605,7 +1605,7 @@ public class SolrIndexSearcher extends IndexSearcher implements Closeable, SolrI
       } else {
         hitsRelation = topDocs.totalHits.relation;
       }
-      if (cmd.getSort() != null && query instanceof RankQuery == false && (cmd.getFlags() & GET_SCORES) != 0) {
+      if (cmd.getSort() != null && cmd.getQuery() instanceof RankQuery == false && (cmd.getFlags() & GET_SCORES) != 0) {
         TopFieldCollector.populateScores(topDocs.scoreDocs, this, query);
       }
       populateNextCursorMarkFromTopDocs(qr, cmd, topDocs);
@@ -1714,7 +1714,7 @@ public class SolrIndexSearcher extends IndexSearcher implements Closeable, SolrI
       assert (totalHits == set.size()) || qr.isPartialResults();
 
       TopDocs topDocs = topCollector.topDocs(0, len);
-      if (cmd.getSort() != null && query instanceof RankQuery == false && (cmd.getFlags() & GET_SCORES) != 0) {
+      if (cmd.getSort() != null && cmd.getQuery() instanceof RankQuery == false && (cmd.getFlags() & GET_SCORES) != 0) {
         TopFieldCollector.populateScores(topDocs.scoreDocs, this, query);
       }
       populateNextCursorMarkFromTopDocs(qr, cmd, topDocs);
diff --git a/solr/core/src/test/org/apache/solr/search/SolrIndexSearcherTest.java b/solr/core/src/test/org/apache/solr/search/SolrIndexSearcherTest.java
index cb418e6..58b1901 100644
--- a/solr/core/src/test/org/apache/solr/search/SolrIndexSearcherTest.java
+++ b/solr/core/src/test/org/apache/solr/search/SolrIndexSearcherTest.java
@@ -19,12 +19,21 @@ package org.apache.solr.search;
 import java.io.IOException;
 
 import org.apache.lucene.index.Term;
+import org.apache.lucene.search.Explanation;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Query;
+import org.apache.lucene.search.QueryVisitor;
+import org.apache.lucene.search.Rescorer;
+import org.apache.lucene.search.ScoreDoc;
 import org.apache.lucene.search.ScoreMode;
+import org.apache.lucene.search.Sort;
+import org.apache.lucene.search.SortField;
 import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.TopDocs;
+import org.apache.lucene.search.TopDocsCollector;
 import org.apache.lucene.search.TotalHits;
 import org.apache.lucene.search.Weight;
+import org.apache.solr.handler.component.MergeStrategy;
 import org.apache.solr.SolrTestCaseJ4;
 import org.junit.Before;
 import org.junit.BeforeClass;
@@ -187,6 +196,120 @@ public class SolrIndexSearcherTest extends SolrTestCaseJ4 {
     });
   }
   
+  public void testReranking() throws Exception {
+    float fixedScore = 1.23f;
+    for (boolean doFilter : new boolean[]{ false, true }) {
+      for (boolean doSort : new boolean[]{ false, true }) {
+        for (int getDocSetFlag : new int[]{ 0, SolrIndexSearcher.GET_DOCSET }) {
+          implTestReranking(doFilter, doSort, getDocSetFlag, null); // don't fix score i.e. no re-ranking
+          implTestReranking(doFilter, doSort, getDocSetFlag, fixedScore); // fix score to be non-zero and non-one
+          fixedScore *= 2;
+        }
+      }
+    }
+  }
+
+  private void implTestReranking(boolean doFilter, boolean doSort, int getDocSetFlag, Float fixedScore) throws Exception {
+    h.getCore().withSearcher(searcher -> {
+
+      final QueryCommand cmd = new QueryCommand();
+      cmd.setFlags(SolrIndexSearcher.GET_SCORES | getDocSetFlag);
+
+      if (doSort) {
+        cmd.setSort(new Sort(SortField.FIELD_SCORE, new SortField("id", SortField.Type.STRING)));
+      }
+
+      if (doFilter) {
+        cmd.setFilterList(new TermQuery(new Term("field4_t", Integer.toString(NUM_DOCS - 1))));
+      }
+
+      cmd.setQuery(new TermQuery(new Term("field1_s", "foo")));
+
+      final float expectedScore;
+      if (fixedScore == null) {
+        expectedScore = 1f;
+      } else {
+        expectedScore = fixedScore.floatValue();
+        cmd.setQuery(new FixedScoreReRankQuery(cmd.getQuery(), expectedScore));
+      }
+
+      final QueryResult qr = new QueryResult();
+      searcher.search(qr, cmd);
+
+      // check score for the first document
+      final DocIterator iter = qr.getDocList().iterator();
+      iter.next();
+      assertEquals(expectedScore, iter.score(), 0);
+
+      return null;
+    });
+
+  }
+
+  private static final class FixedScoreReRankQuery extends RankQuery {
+
+    private Query q;
+    final private float fixedScore;
+
+    public FixedScoreReRankQuery(Query q, float fixedScore) {
+      this.q = q;
+      this.fixedScore = fixedScore;
+    }
+
+    public Weight createWeight(IndexSearcher indexSearcher, ScoreMode scoreMode, float boost) throws IOException {
+      return q.createWeight(indexSearcher, scoreMode, boost);
+    }
+
+    @Override
+    public void visit(QueryVisitor visitor) {
+      q.visit(visitor);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+      return this == obj;
+    }
+
+    @Override
+    public int hashCode() {
+      return q.hashCode();
+    }
+
+    @Override
+    public String toString(String field) {
+      return q.toString(field);
+    }
+
+    @Override
+    @SuppressWarnings({"rawtypes"})
+    public TopDocsCollector getTopDocsCollector(int len, QueryCommand cmd, IndexSearcher searcher) throws IOException {
+      return new ReRankCollector(len, len, new Rescorer() {
+        @Override
+        public TopDocs rescore(IndexSearcher searcher, TopDocs firstPassTopDocs, int topN) {
+          for (ScoreDoc scoreDoc : firstPassTopDocs.scoreDocs) {
+            scoreDoc.score = fixedScore;
+          }
+          return firstPassTopDocs;
+        }
+
+        @Override
+        public Explanation explain(IndexSearcher searcher, Explanation firstPassExplanation, int docID) {
+          return firstPassExplanation;
+        }
+      }, cmd, searcher, null);
+    }
+
+    @Override
+    public MergeStrategy getMergeStrategy() {
+      return null;
+    }
+
+    public RankQuery wrap(Query q) {
+      this.q = q;
+      return this;
+    }
+  }
+
   public void testMinExactWithFilters() throws Exception {
     
     h.getCore().withSearcher(searcher -> {