FileDocCategorySizeDatePackage
BooleanScorer2.javaAPI DocApache Lucene 1.913226Mon Feb 20 09:20:04 GMT 2006org.apache.lucene.search

BooleanScorer2

public class BooleanScorer2 extends Scorer
An alternative to BooleanScorer.
Uses ConjunctionScorer, DisjunctionScorer, ReqOptScorer and ReqExclScorer.
Implements skipTo(), and has no limitations on the numbers of added scorers.

Fields Summary
private ArrayList
requiredScorers
private ArrayList
optionalScorers
private ArrayList
prohibitedScorers
private final Coordinator
coordinator
private Scorer
countingSumScorer
The scorer to which all scoring will be delegated, except for computing and using the coordination factor.
private final int
minNrShouldMatch
The number of optionalScorers that need to match (if there are any)
private static Similarity
defaultSimilarity
Constructors Summary
public BooleanScorer2(Similarity similarity, int minNrShouldMatch)
Create a BooleanScorer2.

param
similarity The similarity to be used.
param
minNrShouldMatch The minimum number of optional added scorers that should match during the search. In case no required scorers are added, at least one of the optional scorers will have to match during the search.


                                                                                                                                                   
       
    super(similarity);
    if (minNrShouldMatch < 0) {
      throw new IllegalArgumentException("Minimum number of optional scorers should not be negative");
    }
    coordinator = new Coordinator();
    this.minNrShouldMatch = minNrShouldMatch;
  
public BooleanScorer2(Similarity similarity)
Create a BooleanScorer2. In no required scorers are added, at least one of the optional scorers will have to match during the search.

param
similarity The similarity to be used.

    this(similarity, 0);
  
Methods Summary
public voidadd(org.apache.lucene.search.Scorer scorer, boolean required, boolean prohibited)

    if (!prohibited) {
      coordinator.maxCoord++;
    }

    if (required) {
      if (prohibited) {
        throw new IllegalArgumentException("scorer cannot be required and prohibited");
      }
      requiredScorers.add(scorer);
    } else if (prohibited) {
      prohibitedScorers.add(scorer);
    } else {
      optionalScorers.add(scorer);
    }
  
private org.apache.lucene.search.ScoreraddProhibitedScorers(org.apache.lucene.search.Scorer requiredCountingSumScorer)
Returns the scorer to be used for match counting and score summing. Uses the given required scorer and the prohibitedScorers.

param
requiredCountingSumScorer A required scorer already built.

    return (prohibitedScorers.size() == 0)
          ? requiredCountingSumScorer // no prohibited
          : new ReqExclScorer(requiredCountingSumScorer,
                              ((prohibitedScorers.size() == 1)
                                ? (Scorer) prohibitedScorers.get(0)
                                : new DisjunctionSumScorer(prohibitedScorers)));
  
private org.apache.lucene.search.ScorercountingConjunctionSumScorer(java.util.List requiredScorers)


      
    // each scorer from the list counted as a single matcher
    final int requiredNrMatchers = requiredScorers.size();
    ConjunctionScorer cs = new ConjunctionScorer(defaultSimilarity) {
      private int lastScoredDoc = -1;

      public float score() throws IOException {
        if (doc() > lastScoredDoc) {
          lastScoredDoc = doc();
          coordinator.nrMatchers += requiredNrMatchers;
        }
        // All scorers match, so defaultSimilarity super.score() always has 1 as
        // the coordination factor.
        // Therefore the sum of the scores of the requiredScorers
        // is used as score.
        return super.score();
      }
    };
    Iterator rsi = requiredScorers.iterator();
    while (rsi.hasNext()) {
      cs.add((Scorer) rsi.next());
    }
    return cs;
  
private org.apache.lucene.search.ScorercountingDisjunctionSumScorer(java.util.List scorers, int minMrShouldMatch)

    return new DisjunctionSumScorer(scorers, minMrShouldMatch) {
      private int lastScoredDoc = -1;
      public float score() throws IOException {
        if (doc() > lastScoredDoc) {
          lastScoredDoc = doc();
          coordinator.nrMatchers += super.nrMatchers;
        }
        return super.score();
      }
    };
  
public intdoc()

 return countingSumScorer.doc(); 
private org.apache.lucene.search.ScorerdualConjunctionSumScorer(org.apache.lucene.search.Scorer req1, org.apache.lucene.search.Scorer req2)

 // non counting. 
    final int requiredNrMatchers = requiredScorers.size();
    ConjunctionScorer cs = new ConjunctionScorer(defaultSimilarity);
    // 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;
  
public org.apache.lucene.search.Explanationexplain(int doc)
Throws an UnsupportedOperationException. TODO: Implement an explanation of the coordination factor.

param
doc The document number for the explanation.
throws
UnsupportedOperationException

    throw new UnsupportedOperationException();
 /* How to explain the coordination factor?
    initCountingSumScorer();
    return countingSumScorer.explain(doc); // misses coord factor. 
  */
  
private voidinitCountingSumScorer()
Initialize the match counting scorer that sums all the scores.

When "counting" is used in a name it means counting the number of matching scorers.
When "sum" is used in a name it means score value summing over the matching scorers

    coordinator.init();
    countingSumScorer = makeCountingSumScorer();
  
private org.apache.lucene.search.ScorermakeCountingSumScorer()
Returns the scorer to be used for match counting and score summing. Uses requiredScorers, optionalScorers and prohibitedScorers.

 // each scorer counted as a single matcher
    return (requiredScorers.size() == 0)
          ? makeCountingSumScorerNoReq()
          : makeCountingSumScorerSomeReq();
  
private org.apache.lucene.search.ScorermakeCountingSumScorerNoReq()

 // 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.
      // minNrShouldMatch optional scorers are required, but at least 1
      int nrOptRequired = (minNrShouldMatch < 1) ? 1 : minNrShouldMatch;
      if (optionalScorers.size() < nrOptRequired) { 
        return new NonMatchingScorer(); // fewer optional clauses than minimum (at least 1) that should match
      } else { // optionalScorers.size() >= nrOptRequired, no required scorers
        Scorer requiredCountingSumScorer =
              (optionalScorers.size() > nrOptRequired)
              ? countingDisjunctionSumScorer(optionalScorers, nrOptRequired)
              : // optionalScorers.size() == nrOptRequired (all optional scorers are required), no required scorers
              (optionalScorers.size() == 1)
              ? new SingleMatchScorer((Scorer) optionalScorers.get(0))
              : countingConjunctionSumScorer(optionalScorers);
        return addProhibitedScorers( requiredCountingSumScorer);
      }
    }
  
private org.apache.lucene.search.ScorermakeCountingSumScorerSomeReq()

 // 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.
      ArrayList allReq = new ArrayList(requiredScorers);
      allReq.addAll(optionalScorers);
      return addProhibitedScorers( countingConjunctionSumScorer(allReq));
    } else { // optionalScorers.size() > minNrShouldMatch, and at least one required scorer
      Scorer requiredCountingSumScorer =
            (requiredScorers.size() == 1)
            ? new SingleMatchScorer((Scorer) requiredScorers.get(0))
            : countingConjunctionSumScorer(requiredScorers);
      if (minNrShouldMatch > 0) { // use a required disjunction scorer over the optional scorers
        return addProhibitedScorers( 
                      dualConjunctionSumScorer( // non counting
                              requiredCountingSumScorer,
                              countingDisjunctionSumScorer(
                                      optionalScorers,
                                      minNrShouldMatch)));
      } else { // minNrShouldMatch == 0
        return new ReqOptSumScorer(
                      addProhibitedScorers(requiredCountingSumScorer),
                      ((optionalScorers.size() == 1)
                        ? new SingleMatchScorer((Scorer) optionalScorers.get(0))
                        : countingDisjunctionSumScorer(optionalScorers, 1))); // require 1 in combined, optional scorer.
      }
    }
  
public booleannext()

    if (countingSumScorer == null) {
      initCountingSumScorer();
    }
    return countingSumScorer.next();
  
public voidscore(org.apache.lucene.search.HitCollector hc)
Scores and collects all matching documents.

param
hc The collector to which all matching documents are passed through {@link HitCollector#collect(int, float)}.
When this method is used the {@link #explain(int)} method should not be used.

    if (countingSumScorer == null) {
      initCountingSumScorer();
    }
    while (countingSumScorer.next()) {
      hc.collect(countingSumScorer.doc(), score());
    }
  
protected booleanscore(org.apache.lucene.search.HitCollector hc, int max)
Expert: Collects matching documents in a range.
Note that {@link #next()} must be called once before this method is called for the first time.

param
hc The collector to which all matching documents are passed through {@link HitCollector#collect(int, float)}.
param
max Do not score documents past this.
return
true if more matching documents may remain.

    // null pointer exception when next() was not called before:
    int docNr = countingSumScorer.doc();
    while (docNr < max) {
      hc.collect(docNr, score());
      if (! countingSumScorer.next()) {
        return false;
      }
      docNr = countingSumScorer.doc();
    }
    return true;
  
public floatscore()

    coordinator.initDoc();
    float sum = countingSumScorer.score();
    return sum * coordinator.coordFactor();
  
public booleanskipTo(int target)
Skips to the first match beyond the current whose document number is greater than or equal to a given target.

When this method is used the {@link #explain(int)} method should not be used.

param
target The target document number.
return
true iff there is such a match.

    if (countingSumScorer == null) {
      initCountingSumScorer();
    }
    return countingSumScorer.skipTo(target);