blob: 92a3ef326ae48998435ffc57e57cc260a6d2b0ee [file] [log] [blame]
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<orCount;i++) {
while (true) {
String value = dimValues[dim][random().nextInt(dimValues[dim].length)];
@@ -749,6 +751,22 @@
}
}, fsp);
+ // Also separately verify that DS respects the
+ // scoreSubDocsAtOnce method, to ensure that all
+ // subScorers are on the same docID:
+ if (!anyMultiValuedDrillDowns) {
+ // Can only do this test when there are no OR'd
+ // drill-down values, beacuse in that case it's
+ // easily possible for one of the DD terms to be on
+ // a future docID:
+ new DrillSideways(s, tr) {
+ @Override
+ protected boolean scoreSubDocsAtOnce() {
+ return true;
+ }
+ }.search(ddq, new AssertingSubDocsAtOnceCollector(), fsp);
+ }
+
SimpleFacetResult expected = slowDrillSidewaysSearch(s, requests, docs, contentToken, drillDowns, dimValues, filter);
Sort sort = new Sort(new SortField("id", SortField.Type.STRING));
Index: lucene/facet/src/test/org/apache/lucene/facet/search/AssertingSubDocsAtOnceCollector.java
===================================================================
--- lucene/facet/src/test/org/apache/lucene/facet/search/AssertingSubDocsAtOnceCollector.java (revision 0)
+++ lucene/facet/src/test/org/apache/lucene/facet/search/AssertingSubDocsAtOnceCollector.java (working copy)
@@ -0,0 +1,67 @@
+package org.apache.lucene.facet.search;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.lucene.index.AtomicReaderContext;
+import org.apache.lucene.search.Collector;
+import org.apache.lucene.search.Scorer.ChildScorer;
+import org.apache.lucene.search.Scorer;
+
+/** Verifies in collect() that all child subScorers are on
+ * the collected doc. */
+class AssertingSubDocsAtOnceCollector extends Collector {
+
+ // TODO: allow wrapping another Collector
+
+ List<Scorer> allScorers;
+
+ @Override
+ public void setScorer(Scorer s) {
+ // Gathers all scorers, including s and "under":
+ allScorers = new ArrayList<Scorer>();
+ 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);
}
}