Index: lucene/src/java/org/apache/lucene/search/NoOpCollector.java =================================================================== --- lucene/src/java/org/apache/lucene/search/NoOpCollector.java (revision ) +++ lucene/src/java/org/apache/lucene/search/NoOpCollector.java (revision ) @@ -0,0 +1,51 @@ +package org.apache.lucene.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 org.apache.lucene.index.IndexReader; + +import java.io.IOException; + +/** + * A collector that does nothing. Can only be retrieved using {@link #INSTANCE} as a singleton. + */ +public class NoOpCollector extends Collector { + + public static final NoOpCollector INSTANCE = new NoOpCollector(); + + private NoOpCollector() { + + } + + @Override + public void setScorer(Scorer scorer) throws IOException { + } + + @Override + public void collect(int doc) throws IOException { + } + + @Override + public void setNextReader(IndexReader reader, int docBase) throws IOException { + } + + @Override + public boolean acceptsDocsOutOfOrder() { + return true; + } +} \ No newline at end of file Index: lucene/contrib/join/src/java/org/apache/lucene/search/join/BlockJoinQuery.java =================================================================== --- lucene/contrib/join/src/java/org/apache/lucene/search/join/BlockJoinQuery.java (revision 1140874) +++ lucene/contrib/join/src/java/org/apache/lucene/search/join/BlockJoinQuery.java (revision ) @@ -23,15 +23,7 @@ import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.IndexWriter; // javadocs import org.apache.lucene.index.Term; -import org.apache.lucene.search.BooleanClause; -import org.apache.lucene.search.DocIdSet; -import org.apache.lucene.search.DocIdSetIterator; -import org.apache.lucene.search.Explanation; -import org.apache.lucene.search.Filter; -import org.apache.lucene.search.Query; -import org.apache.lucene.search.Scorer; -import org.apache.lucene.search.Searcher; -import org.apache.lucene.search.Weight; +import org.apache.lucene.search.*; import org.apache.lucene.search.grouping.TopGroups; import org.apache.lucene.util.ArrayUtil; import org.apache.lucene.util.OpenBitSet; @@ -91,6 +83,8 @@ private final Query origChildQuery; private final ScoreMode scoreMode; + private Collector childCollector = NoOpCollector.INSTANCE; + public BlockJoinQuery(Query childQuery, Filter parentsFilter, ScoreMode scoreMode) { super(); this.origChildQuery = childQuery; @@ -107,23 +101,40 @@ this.scoreMode = scoreMode; } + /** + * Sets a child collector that will be called on matching child documented. + */ + public BlockJoinQuery setChildCollector(Collector childCollector) { + this.childCollector = childCollector; + return this; + } + + protected OpenBitSet convertOpenBitSet(DocIdSet parents) { + if (!(parents instanceof OpenBitSet)) { + throw new IllegalStateException("parentFilter must return OpenBitSet; got " + parents); + } + return (OpenBitSet) parents; + } + @Override public Weight createWeight(Searcher searcher) throws IOException { - return new BlockJoinWeight(this, childQuery.createWeight(searcher), parentsFilter, scoreMode); + return new BlockJoinWeight(this, childQuery.createWeight(searcher), parentsFilter, scoreMode, childCollector); } private static class BlockJoinWeight extends Weight { - private final Query joinQuery; + private final BlockJoinQuery joinQuery; private final Weight childWeight; private final Filter parentsFilter; private final ScoreMode scoreMode; + private final Collector childCollector; - public BlockJoinWeight(Query joinQuery, Weight childWeight, Filter parentsFilter, ScoreMode scoreMode) { + public BlockJoinWeight(BlockJoinQuery joinQuery, Weight childWeight, Filter parentsFilter, ScoreMode scoreMode, Collector childCollector) { super(); this.joinQuery = joinQuery; this.childWeight = childWeight; this.parentsFilter = parentsFilter; this.scoreMode = scoreMode; + this.childCollector = childCollector; } @Override @@ -169,11 +180,11 @@ // No matches return null; } - if (!(parents instanceof OpenBitSet)) { - throw new IllegalStateException("parentFilter must return OpenBitSet; got " + parents); - } - return new BlockJoinScorer(this, childScorer, (OpenBitSet) parents, firstChildDoc, scoreMode); + childCollector.setNextReader(reader, 0); + childCollector.setScorer(childScorer); + + return new BlockJoinScorer(this, childScorer, joinQuery.convertOpenBitSet(parents), firstChildDoc, scoreMode, childCollector); } @Override @@ -193,6 +204,7 @@ private final Scorer childScorer; private final OpenBitSet parentBits; private final ScoreMode scoreMode; + private final Collector childCollector; private int parentDoc; private float parentScore; private int nextChildDoc; @@ -201,12 +213,13 @@ private float[] pendingChildScores; private int childDocUpto; - public BlockJoinScorer(Weight weight, Scorer childScorer, OpenBitSet parentBits, int firstChildDoc, ScoreMode scoreMode) { + public BlockJoinScorer(Weight weight, Scorer childScorer, OpenBitSet parentBits, int firstChildDoc, ScoreMode scoreMode, Collector childCollector) { super(weight); //System.out.println("Q.init firstChildDoc=" + firstChildDoc); this.parentBits = parentBits; this.childScorer = childScorer; this.scoreMode = scoreMode; + this.childCollector = childCollector; if (scoreMode != ScoreMode.None) { pendingChildScores = new float[5]; } @@ -282,6 +295,7 @@ maxScore = Math.max(childScore, maxScore); totalScore += childScore; } + childCollector.collect(nextChildDoc); childDocUpto++; nextChildDoc = childScorer.nextDoc(); } while (nextChildDoc < parentDoc); @@ -358,7 +372,7 @@ return new BlockJoinQuery(childQuery, childRewrite, parentsFilter, - scoreMode); + scoreMode).setChildCollector(childCollector); } else { return this; } @@ -405,6 +419,6 @@ public Object clone() { return new BlockJoinQuery((Query) origChildQuery.clone(), parentsFilter, - scoreMode); + scoreMode).setChildCollector(childCollector); } }