You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by us...@apache.org on 2013/09/26 08:46:19 UTC

svn commit: r1526399 - in /lucene/dev/trunk/lucene: ./ core/src/java/org/apache/lucene/search/ core/src/test/org/apache/lucene/search/

Author: uschindler
Date: Thu Sep 26 06:46:19 2013
New Revision: 1526399

URL: http://svn.apache.org/r1526399
Log:
LUCENE-5245: Fix MultiTermQuery's constant score rewrites to always return a ConstantScoreQuery to make scoring consistent. Previously it returned an empty unwrapped BooleanQuery, if no terms were available, which has a different query norm

Modified:
    lucene/dev/trunk/lucene/CHANGES.txt
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/ConstantScoreAutoRewrite.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/ScoringRewrite.java
    lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestMultiTermConstantScore.java

Modified: lucene/dev/trunk/lucene/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/CHANGES.txt?rev=1526399&r1=1526398&r2=1526399&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/CHANGES.txt (original)
+++ lucene/dev/trunk/lucene/CHANGES.txt Thu Sep 26 06:46:19 2013
@@ -89,6 +89,11 @@ Bug Fixes
   its state, which could result in exceptions being thrown, as well as
   incorrect ordinals returned from getParent. (Shai Erera)
 
+* LUCENE-5245: Fix MultiTermQuery's constant score rewrites to always
+  return a ConstantScoreQuery to make scoring consistent. Previously it
+  returned an empty unwrapped BooleanQuery, if no terms were available,
+  which has a different query norm.  (Nik Everett, Uwe Schindler)
+
 API Changes:
 
 * LUCENE-5222: Add SortField.needsScores(). Previously it was not possible

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/ConstantScoreAutoRewrite.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/ConstantScoreAutoRewrite.java?rev=1526399&r1=1526398&r2=1526399&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/ConstantScoreAutoRewrite.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/ConstantScoreAutoRewrite.java Thu Sep 26 06:46:19 2013
@@ -96,17 +96,17 @@ class ConstantScoreAutoRewrite extends T
     final int size = col.pendingTerms.size();
     if (col.hasCutOff) {
       return MultiTermQuery.CONSTANT_SCORE_FILTER_REWRITE.rewrite(reader, query);
-    } else if (size == 0) {
-      return getTopLevelQuery();
     } else {
       final BooleanQuery bq = getTopLevelQuery();
-      final BytesRefHash pendingTerms = col.pendingTerms;
-      final int sort[] = pendingTerms.sort(BytesRef.getUTF8SortedAsUnicodeComparator());
-      for(int i = 0; i < size; i++) {
-        final int pos = sort[i];
-        // docFreq is not used for constant score here, we pass 1
-        // to explicitely set a fake value, so it's not calculated
-        addClause(bq, new Term(query.field, pendingTerms.get(pos, new BytesRef())), 1, 1.0f, col.array.termState[pos]);
+      if (size > 0) {
+        final BytesRefHash pendingTerms = col.pendingTerms;
+        final int sort[] = pendingTerms.sort(BytesRef.getUTF8SortedAsUnicodeComparator());
+        for(int i = 0; i < size; i++) {
+          final int pos = sort[i];
+          // docFreq is not used for constant score here, we pass 1
+          // to explicitely set a fake value, so it's not calculated
+          addClause(bq, new Term(query.field, pendingTerms.get(pos, new BytesRef())), 1, 1.0f, col.array.termState[pos]);
+        }
       }
       // Strip scores
       final Query result = new ConstantScoreQuery(bq);

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/ScoringRewrite.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/ScoringRewrite.java?rev=1526399&r1=1526398&r2=1526399&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/ScoringRewrite.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/ScoringRewrite.java Thu Sep 26 06:46:19 2013
@@ -87,9 +87,6 @@ public abstract class ScoringRewrite<Q e
     @Override
     public Query rewrite(IndexReader reader, MultiTermQuery query) throws IOException {
       final BooleanQuery bq = SCORING_BOOLEAN_QUERY_REWRITE.rewrite(reader, query);
-      // TODO: if empty boolean query return NullQuery?
-      if (bq.clauses().isEmpty())
-        return bq;
       // strip the scores off
       final Query result = new ConstantScoreQuery(bq);
       result.setBoost(query.getBoost());

Modified: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestMultiTermConstantScore.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestMultiTermConstantScore.java?rev=1526399&r1=1526398&r2=1526399&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestMultiTermConstantScore.java (original)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestMultiTermConstantScore.java Thu Sep 26 06:46:19 2013
@@ -160,6 +160,58 @@ public class TestMultiTermConstantScore 
           result[i].score, SCORE_COMP_THRESH);
     }
 
+    result = search.search(csrq("data", "1", "6", T, T, MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT), null, 1000).scoreDocs;
+    numHits = result.length;
+    assertEquals("wrong number of results", 6, numHits);
+    for (int i = 0; i < numHits; i++) {
+      assertEquals("score for " + i + " was not the same", score,
+          result[i].score, SCORE_COMP_THRESH);
+    }
+  }
+
+  @Test // Test for LUCENE-5245: Empty MTQ rewrites should have a consistent norm, so always need to return a CSQ!
+  public void testEqualScoresWhenNoHits() throws IOException {
+    // NOTE: uses index build in *this* setUp
+
+    IndexSearcher search = newSearcher(reader);
+
+    ScoreDoc[] result;
+
+    TermQuery dummyTerm = new TermQuery(new Term("data", "1"));
+
+    BooleanQuery bq = new BooleanQuery();
+    bq.add(dummyTerm, BooleanClause.Occur.SHOULD); // hits one doc
+    bq.add(csrq("data", "#", "#", T, T), BooleanClause.Occur.SHOULD); // hits no docs
+    result = search.search(bq, null, 1000).scoreDocs;
+    int numHits = result.length;
+    assertEquals("wrong number of results", 1, numHits);
+    float score = result[0].score;
+    for (int i = 1; i < numHits; i++) {
+      assertEquals("score for " + i + " was not the same", score,
+          result[i].score, SCORE_COMP_THRESH);
+    }
+
+    bq = new BooleanQuery();
+    bq.add(dummyTerm, BooleanClause.Occur.SHOULD); // hits one doc
+    bq.add(csrq("data", "#", "#", T, T, MultiTermQuery.CONSTANT_SCORE_BOOLEAN_QUERY_REWRITE), BooleanClause.Occur.SHOULD); // hits no docs
+    result = search.search(bq, null, 1000).scoreDocs;
+    numHits = result.length;
+    assertEquals("wrong number of results", 1, numHits);
+    for (int i = 0; i < numHits; i++) {
+      assertEquals("score for " + i + " was not the same", score,
+          result[i].score, SCORE_COMP_THRESH);
+    }
+
+    bq = new BooleanQuery();
+    bq.add(dummyTerm, BooleanClause.Occur.SHOULD); // hits one doc
+    bq.add(csrq("data", "#", "#", T, T, MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT), BooleanClause.Occur.SHOULD); // hits no docs
+    result = search.search(bq, null, 1000).scoreDocs;
+    numHits = result.length;
+    assertEquals("wrong number of results", 1, numHits);
+    for (int i = 0; i < numHits; i++) {
+      assertEquals("score for " + i + " was not the same", score,
+          result[i].score, SCORE_COMP_THRESH);
+    }
   }
 
   @Test