Index: lucene/facet/src/test/org/apache/lucene/facet/search/TestDrillSideways.java =================================================================== --- lucene/facet/src/test/org/apache/lucene/facet/search/TestDrillSideways.java (revision 1470728) +++ lucene/facet/src/test/org/apache/lucene/facet/search/TestDrillSideways.java (working copy) @@ -642,6 +642,7 @@ String[][] drillDowns = new String[numDims][]; int count = 0; + boolean anyMultiValuedDrillDowns = false; while (count < numDrillDown) { int dim = random().nextInt(numDims); if (drillDowns[dim] == null) { @@ -651,6 +652,7 @@ } else { int orCount = _TestUtil.nextInt(random(), 1, Math.min(5, dimValues[dim].length)); drillDowns[dim] = new String[orCount]; + anyMultiValuedDrillDowns |= orCount > 1; for(int i=0;i allScorers; + + @Override + public void setScorer(Scorer s) { + // Gathers all scorers, including s and "under": + allScorers = new ArrayList(); + allScorers.add(s); + int upto = 0; + while(upto < allScorers.size()) { + s = allScorers.get(upto++); + for (ChildScorer sub : s.getChildren()) { + allScorers.add(sub.child); + } + } + } + + @Override + public void collect(int docID) { + for(Scorer s : allScorers) { + if (docID != s.docID()) { + throw new IllegalStateException("subScorer=" + s + " has docID=" + s.docID() + " != collected docID=" + docID); + } + } + } + + @Override + public void setNextReader(AtomicReaderContext context) { + } + + @Override + public boolean acceptsDocsOutOfOrder() { + return false; + } +} Property changes on: lucene/facet/src/test/org/apache/lucene/facet/search/AssertingSubDocsAtOnceCollector.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lucene/facet/src/java/org/apache/lucene/facet/search/DrillSidewaysQuery.java =================================================================== --- lucene/facet/src/java/org/apache/lucene/facet/search/DrillSidewaysQuery.java (revision 1470728) +++ lucene/facet/src/java/org/apache/lucene/facet/search/DrillSidewaysQuery.java (working copy) @@ -39,12 +39,14 @@ final Collector drillDownCollector; final Collector[] drillSidewaysCollectors; final Term[][] drillDownTerms; + final boolean scoreSubDocsAtOnce; - DrillSidewaysQuery(Query baseQuery, Collector drillDownCollector, Collector[] drillSidewaysCollectors, Term[][] drillDownTerms) { + DrillSidewaysQuery(Query baseQuery, Collector drillDownCollector, Collector[] drillSidewaysCollectors, Term[][] drillDownTerms, boolean scoreSubDocsAtOnce) { this.baseQuery = baseQuery; this.drillDownCollector = drillDownCollector; this.drillSidewaysCollectors = drillSidewaysCollectors; this.drillDownTerms = drillDownTerms; + this.scoreSubDocsAtOnce = scoreSubDocsAtOnce; } @Override @@ -65,7 +67,7 @@ if (newQuery == baseQuery) { return this; } else { - return new DrillSidewaysQuery(newQuery, drillDownCollector, drillSidewaysCollectors, drillDownTerms); + return new DrillSidewaysQuery(newQuery, drillDownCollector, drillSidewaysCollectors, drillDownTerms, scoreSubDocsAtOnce); } } @@ -152,7 +154,7 @@ return new DrillSidewaysScorer(this, context, baseScorer, - drillDownCollector, dims); + drillDownCollector, dims, scoreSubDocsAtOnce); } }; } Index: lucene/facet/src/java/org/apache/lucene/facet/search/DrillSideways.java =================================================================== --- lucene/facet/src/java/org/apache/lucene/facet/search/DrillSideways.java (revision 1470728) +++ lucene/facet/src/java/org/apache/lucene/facet/search/DrillSideways.java (working copy) @@ -209,7 +209,7 @@ drillSidewaysCollectors[idx++] = FacetsCollector.create(getDrillSidewaysAccumulator(dim, new FacetSearchParams(fsp.indexingParams, requests))); } - DrillSidewaysQuery dsq = new DrillSidewaysQuery(baseQuery, drillDownCollector, drillSidewaysCollectors, drillDownTerms); + DrillSidewaysQuery dsq = new DrillSidewaysQuery(baseQuery, drillDownCollector, drillSidewaysCollectors, drillDownTerms, scoreSubDocsAtOnce()); searcher.search(dsq, hitCollector); @@ -300,6 +300,19 @@ return FacetsAccumulator.create(fsp, searcher.getIndexReader(), taxoReader); } + /** Override this and return true if your collector + * (e.g., ToParentBlockJoinCollector) expects all + * sub-scorers to be positioned on the document being + * collected. This will cause some performance loss; + * default is false. Note that if you return true from + * this method (in a subclass) be sure your collector + * also returns false from {@link + * Collector#acceptsDocsOutOfOrder}: this will trick + * BooleanQuery into also scoring all subDocs at once. */ + protected boolean scoreSubDocsAtOnce() { + return false; + } + /** Represents the returned result from a drill sideways * search. */ public static class DrillSidewaysResult { Index: lucene/facet/src/java/org/apache/lucene/facet/search/DrillSidewaysScorer.java =================================================================== --- lucene/facet/src/java/org/apache/lucene/facet/search/DrillSidewaysScorer.java (revision 1470728) +++ lucene/facet/src/java/org/apache/lucene/facet/search/DrillSidewaysScorer.java (working copy) @@ -43,17 +43,19 @@ private static final int CHUNK = 2048; private static final int MASK = CHUNK-1; + private final boolean scoreSubDocsAtOnce; private int collectDocID = -1; private float collectScore; DrillSidewaysScorer(Weight w, AtomicReaderContext context, Scorer baseScorer, Collector drillDownCollector, - DocsEnumsAndFreq[] dims) { + DocsEnumsAndFreq[] dims, boolean scoreSubDocsAtOnce) { super(w); this.dims = dims; this.context = context; this.baseScorer = baseScorer; this.drillDownCollector = drillDownCollector; + this.scoreSubDocsAtOnce = scoreSubDocsAtOnce; } @Override @@ -77,7 +79,6 @@ // Position all scorers to their first matching doc: int baseDocID = baseScorer.nextDoc(); - for(DocsEnumsAndFreq dim : dims) { for(DocsEnum docsEnum : dim.docsEnums) { if (docsEnum != null) { @@ -101,7 +102,7 @@ int estBaseHitCount = context.reader().maxDoc() / (1+baseDocID); /* - System.out.println("\nbaseDocID=" + baseDocID + " est=" + estBaseHitCount); + System.out.println("\nbaseDocID=" + baseScorer.docID() + " est=" + estBaseHitCount); System.out.println(" maxDoc=" + context.reader().maxDoc()); System.out.println(" maxFreq=" + maxFreq); System.out.println(" dims[0].freq=" + dims[0].freq); @@ -110,15 +111,22 @@ } */ - if (estBaseHitCount < maxFreq/10) { + //System.out.println("DS score " + scoreSubDocsAtOnce); + if (!scoreSubDocsAtOnce) { + if (estBaseHitCount < maxFreq/10) { + //System.out.println("baseAdvance"); + doBaseAdvanceScoring(collector, docsEnums, sidewaysCollectors); + } else if (numDims > 1 && (dims[1].freq < estBaseHitCount/10)) { + //System.out.println("drillDownAdvance"); + doDrillDownAdvanceScoring(collector, docsEnums, sidewaysCollectors); + } else { + //System.out.println("union"); + doUnionScoring(collector, docsEnums, sidewaysCollectors); + } + } else { + // TODO: we should fallback to BS2 ReqOptSum scorer here //System.out.println("baseAdvance"); doBaseAdvanceScoring(collector, docsEnums, sidewaysCollectors); - } else if (numDims > 1 && (dims[1].freq < estBaseHitCount/10)) { - //System.out.println("drillDownAdvance"); - doDrillDownAdvanceScoring(collector, docsEnums, sidewaysCollectors); - } else { - //System.out.println("union"); - doUnionScoring(collector, docsEnums, sidewaysCollectors); } }