Index: src/java/org/apache/lucene/search/BooleanScorer2.java =================================================================== --- src/java/org/apache/lucene/search/BooleanScorer2.java (revision 465853) +++ src/java/org/apache/lucene/search/BooleanScorer2.java (working copy) @@ -115,7 +115,7 @@ * When "sum" is used in a name it means score value summing * over the matching scorers */ - private void initCountingSumScorer() { + private void initCountingSumScorer() throws IOException { coordinator.init(); countingSumScorer = makeCountingSumScorer(); } @@ -168,10 +168,10 @@ private static Similarity defaultSimilarity = new DefaultSimilarity(); - private Scorer countingConjunctionSumScorer(List requiredScorers) { + private Scorer countingConjunctionSumScorer(List requiredScorers) throws IOException { // each scorer from the list counted as a single matcher final int requiredNrMatchers = requiredScorers.size(); - ConjunctionScorer cs = new ConjunctionScorer(defaultSimilarity) { + return new ConjunctionScorer(defaultSimilarity, requiredScorers) { private int lastScoredDoc = -1; public float score() throws IOException { @@ -186,35 +186,26 @@ return super.score(); } }; - Iterator rsi = requiredScorers.iterator(); - while (rsi.hasNext()) { - cs.add((Scorer) rsi.next()); - } - return cs; } - private Scorer dualConjunctionSumScorer(Scorer req1, Scorer req2) { // non counting. - final int requiredNrMatchers = requiredScorers.size(); - ConjunctionScorer cs = new ConjunctionScorer(defaultSimilarity); + private Scorer dualConjunctionSumScorer(Scorer req1, Scorer req2) throws IOException { // non counting. + return new ConjunctionScorer(defaultSimilarity, new Scorer[]{req1, req2}); // All scorers match, so defaultSimilarity super.score() always has 1 as // the coordination factor. // Therefore the sum of the scores of two scorers // is used as score. - cs.add(req1); - cs.add(req2); - return cs; } /** Returns the scorer to be used for match counting and score summing. * Uses requiredScorers, optionalScorers and prohibitedScorers. */ - private Scorer makeCountingSumScorer() { // each scorer counted as a single matcher + private Scorer makeCountingSumScorer() throws IOException { // each scorer counted as a single matcher return (requiredScorers.size() == 0) ? makeCountingSumScorerNoReq() : makeCountingSumScorerSomeReq(); } - private Scorer makeCountingSumScorerNoReq() { // No required scorers + private Scorer makeCountingSumScorerNoReq() throws IOException { // No required scorers if (optionalScorers.size() == 0) { return new NonMatchingScorer(); // no clauses or only prohibited clauses } else { // No required scorers. At least one optional scorer. @@ -235,7 +226,7 @@ } } - private Scorer makeCountingSumScorerSomeReq() { // At least one required scorer. + private Scorer makeCountingSumScorerSomeReq() throws IOException { // At least one required scorer. if (optionalScorers.size() < minNrShouldMatch) { return new NonMatchingScorer(); // fewer optional clauses than minimum that should match } else if (optionalScorers.size() == minNrShouldMatch) { // all optional scorers also required. Index: src/java/org/apache/lucene/search/ConjunctionScorer.java =================================================================== --- src/java/org/apache/lucene/search/ConjunctionScorer.java (revision 465853) +++ src/java/org/apache/lucene/search/ConjunctionScorer.java (working copy) @@ -17,120 +17,88 @@ */ import java.io.IOException; -import java.util.Arrays; -import java.util.Comparator; +import java.util.Collection; /** Scorer for conjunctions, sets of queries, all of which are required. */ class ConjunctionScorer extends Scorer { - private Scorer[] scorers = new Scorer[2]; - private int length = 0; - private int first = 0; - private int last = -1; - private boolean firstTime = true; + private final Scorer[] scorers; + + // Current doc that each scorer is on. + // This is a workaround for the fact that doc() is not defined before + // next() or skipTo() is called. But sometimes we don't want to call + // skipTo if the scorer is already past the target. The other + // way around this would be to initialize all the scorers by calling + // next() on all of them in the constructor... then one could rely + // on scorer[i].doc() for the current position. + private final int[] docs; + + int maxDoc =-1; // maximum document seen so far private boolean more = true; - private float coord; + private final float coord; - public ConjunctionScorer(Similarity similarity) { - super(similarity); + public ConjunctionScorer(Similarity similarity, Collection scorers) throws IOException { + this(similarity, (Scorer[])scorers.toArray(new Scorer[scorers.size()])); } - final void add(Scorer scorer) { - if (length >= scorers.length) { - // grow the array - Scorer[] temps = new Scorer[scorers.length * 2]; - System.arraycopy(scorers, 0, temps, 0, length); - scorers = temps; + public ConjunctionScorer(Similarity similarity, Scorer[] scorers) throws IOException { + super(similarity); + this.scorers = scorers; + docs = new int[scorers.length]; + // Arrays.fill(docs,-1); + // calling next() for each scorer could be removed if skipTo() worked + // on all scorers w/o first calling next() + for (int i=0; i=scorers.length) return true; // all the scorers matched maxDoc + } else { + target = maxDoc; // adjust target to higher doc encountered + numMatches=1; // reset count to 1 (match current doc) + } + if (++pos==scorers.length) pos=0; } - - for (int i = 0, pos = first; i < length; i++) { - if (!more) break; - more = scorers[pos].skipTo(target); - pos = (pos == length-1) ? 0 : pos+1; - } - - if (more) - sortScorers(); // re-sort scorers - - return doNext(); } public float score() throws IOException { float sum = 0.0f; - for (int i = 0; i < length; i++) { + for (int i = 0; i < scorers.length; i++) { sum += scorers[i].score(); } return sum * coord; } - - private void init(boolean initScorers) throws IOException { - // compute coord factor - coord = getSimilarity().coord(length, length); - - more = length > 0; - if(initScorers){ - // move each scorer to its first entry - for (int i = 0, pos = first; i < length; i++) { - if (!more) break; - more = scorers[pos].next(); - pos = (pos == length-1) ? 0 : pos+1; - } - // initial sort of simulated list - if (more) - sortScorers(); - } - - firstTime = false; - } - - private void sortScorers() { - // squeeze the array down for the sort - if (length != scorers.length) { - Scorer[] temps = new Scorer[length]; - System.arraycopy(scorers, 0, temps, 0, length); - scorers = temps; - } - - // note that this comparator is not consistent with equals! - Arrays.sort(scorers, new Comparator() { // sort the array - public int compare(Object o1, Object o2) { - return ((Scorer)o1).doc() - ((Scorer)o2).doc(); - } - }); - - first = 0; - last = length - 1; - } - public Explanation explain(int doc) { throw new UnsupportedOperationException(); } Index: src/java/org/apache/lucene/search/BooleanQuery.java =================================================================== --- src/java/org/apache/lucene/search/BooleanQuery.java (revision 465853) +++ src/java/org/apache/lucene/search/BooleanQuery.java (working copy) @@ -236,16 +236,15 @@ } if (allRequired && noneBoolean) { // ConjunctionScorer is okay - ConjunctionScorer result = - new ConjunctionScorer(similarity); + Scorer[] scorers = new Scorer[weights.size()]; for (int i = 0 ; i < weights.size(); i++) { Weight w = (Weight)weights.elementAt(i); Scorer subScorer = w.scorer(reader); if (subScorer == null) return null; - result.add(subScorer); + scorers[i] = subScorer; } - return result; + return new ConjunctionScorer(similarity, scorers); } // Use good-old BooleanScorer instead.