You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by jp...@apache.org on 2015/02/21 15:32:52 UTC

svn commit: r1661369 - in /lucene/dev/trunk/lucene: CHANGES.txt core/src/java/org/apache/lucene/search/MultiCollector.java core/src/test/org/apache/lucene/search/MultiCollectorTest.java

Author: jpountz
Date: Sat Feb 21 14:32:52 2015
New Revision: 1661369

URL: http://svn.apache.org/r1661369
Log:
LUCENE-6263: MultiCollector automatically caches scores when several collectors need them.

Modified:
    lucene/dev/trunk/lucene/CHANGES.txt
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/MultiCollector.java
    lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/MultiCollectorTest.java

Modified: lucene/dev/trunk/lucene/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/CHANGES.txt?rev=1661369&r1=1661368&r2=1661369&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/CHANGES.txt (original)
+++ lucene/dev/trunk/lucene/CHANGES.txt Sat Feb 21 14:32:52 2015
@@ -101,6 +101,9 @@ Optimizations
 * LUCENE-6262: ConstantScoreQuery does not wrap the inner weight anymore when
   scores are not required. (Adrien Grand)
 
+* LUCENE-6263: MultiCollector automatically caches scores when several
+  collectors need them. (Adrien Grand)
+
 API Changes
 
 * LUCENE-6204, LUCENE-6208: Simplify CompoundFormat: remove files()

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/MultiCollector.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/MultiCollector.java?rev=1661369&r1=1661368&r2=1661369&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/MultiCollector.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/MultiCollector.java Sat Feb 21 14:32:52 2015
@@ -86,10 +86,18 @@ public class MultiCollector implements C
     }
   }
   
+  private final boolean cacheScores;
   private final Collector[] collectors;
 
   private MultiCollector(Collector... collectors) {
     this.collectors = collectors;
+    int numNeedsScores = 0;
+    for (Collector collector : collectors) {
+      if (collector.needsScores()) {
+        numNeedsScores += 1;
+      }
+    }
+    this.cacheScores = numNeedsScores >= 2;
   }
 
   @Override
@@ -108,19 +116,24 @@ public class MultiCollector implements C
     for (int i = 0; i < collectors.length; ++i) {
       leafCollectors[i] = collectors[i].getLeafCollector(context);
     }
-    return new MultiLeafCollector(leafCollectors);
+    return new MultiLeafCollector(leafCollectors, cacheScores);
   }
 
   private static class MultiLeafCollector implements LeafCollector {
 
+    private final boolean cacheScores;
     private final LeafCollector[] collectors;
 
-    private MultiLeafCollector(LeafCollector[] collectors) {
+    private MultiLeafCollector(LeafCollector[] collectors, boolean cacheScores) {
       this.collectors = collectors;
+      this.cacheScores = cacheScores;
     }
 
     @Override
     public void setScorer(Scorer scorer) throws IOException {
+      if (cacheScores) {
+        scorer = new ScoreCachingWrappingScorer(scorer);
+      }
       for (LeafCollector c : collectors) {
         c.setScorer(scorer);
       }

Modified: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/MultiCollectorTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/MultiCollectorTest.java?rev=1661369&r1=1661368&r2=1661369&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/MultiCollectorTest.java (original)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/MultiCollectorTest.java Sat Feb 21 14:32:52 2015
@@ -19,7 +19,11 @@ package org.apache.lucene.search;
 
 import java.io.IOException;
 
+import org.apache.lucene.document.Document;
+import org.apache.lucene.index.DirectoryReader;
 import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.RandomIndexWriter;
+import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.LuceneTestCase;
 import org.junit.Test;
 
@@ -69,7 +73,7 @@ public class MultiCollectorTest extends
     final LeafCollector ac = c.getLeafCollector(null);
     ac.collect(1);
     c.getLeafCollector(null);
-    c.getLeafCollector(null).setScorer(null);
+    c.getLeafCollector(null).setScorer(new FakeScorer());
   }
 
   @Test
@@ -91,7 +95,7 @@ public class MultiCollectorTest extends
     LeafCollector ac = c.getLeafCollector(null);
     ac.collect(1);
     ac = c.getLeafCollector(null);
-    ac.setScorer(null);
+    ac.setScorer(new FakeScorer());
 
     for (DummyCollector dc : dcs) {
       assertTrue(dc.collectCalled);
@@ -101,4 +105,65 @@ public class MultiCollectorTest extends
 
   }
 
+  private static Collector collector(boolean needsScores, Class<?> expectedScorer) {
+    return new Collector() {
+
+      @Override
+      public LeafCollector getLeafCollector(LeafReaderContext context) throws IOException {
+        return new LeafCollector() {
+
+          @Override
+          public void setScorer(Scorer scorer) throws IOException {
+            assertEquals(expectedScorer, scorer.getClass());
+          }
+
+          @Override
+          public void collect(int doc) throws IOException {}
+          
+        };
+      }
+
+      @Override
+      public boolean needsScores() {
+        return needsScores;
+      }
+      
+    };
+  }
+
+  public void testCacheScoresIfNecessary() throws IOException {
+    Directory dir = newDirectory();
+    RandomIndexWriter iw = new RandomIndexWriter(random(), dir);
+    iw.addDocument(new Document());
+    iw.commit();
+    DirectoryReader reader = iw.getReader();
+    iw.close();
+    
+    final LeafReaderContext ctx = reader.leaves().get(0);
+
+    try {
+      collector(false, ScoreCachingWrappingScorer.class).getLeafCollector(ctx).setScorer(new FakeScorer());
+      fail("The collector was configured to expect a ScoreCachingWrappingScorer and did not fail when pass in a FakeScorer");
+    } catch (AssertionError e) {
+      // expected
+    }
+
+    // no collector needs scores => no caching
+    Collector c1 = collector(false, FakeScorer.class);
+    Collector c2 = collector(false, FakeScorer.class);
+    MultiCollector.wrap(c1, c2).getLeafCollector(ctx).setScorer(new FakeScorer());
+
+    // only one collector needs scores => no caching
+    c1 = collector(true, FakeScorer.class);
+    c2 = collector(false, FakeScorer.class);
+    MultiCollector.wrap(c1, c2).getLeafCollector(ctx).setScorer(new FakeScorer());
+
+    // several collectors need scores => caching
+    c1 = collector(true, ScoreCachingWrappingScorer.class);
+    c2 = collector(true, ScoreCachingWrappingScorer.class);
+    MultiCollector.wrap(c1, c2).getLeafCollector(ctx).setScorer(new FakeScorer());
+
+    reader.close();
+    dir.close();
+  }
 }