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

DisjunctionSumScorer

public class DisjunctionSumScorer extends Scorer
A Scorer for OR like queries, counterpart of Lucene's ConjunctionScorer. This Scorer implements {@link Scorer#skipTo(int)} and uses skipTo() on the given Scorers.

Fields Summary
private final int
nrScorers
The number of subscorers.
protected final List
subScorers
The subscorers.
private final int
minimumNrMatchers
The minimum number of scorers that should match.
private ScorerQueue
scorerQueue
The scorerQueue contains all subscorers ordered by their current doc(), with the minimum at the top.
The scorerQueue is initialized the first time next() or skipTo() is called.
An exhausted scorer is immediately removed from the scorerQueue.
If less than the minimumNrMatchers scorers remain in the scorerQueue next() and skipTo() return false.

After each to call to next() or skipTo() currentSumScore is the total score of the current matching doc, nrMatchers is the number of matching scorers, and all scorers are after the matching doc, or are exhausted.

private int
currentDoc
The document number of the current match.
protected int
nrMatchers
The number of subscorers that provide the current match.
private float
currentScore
Constructors Summary
public DisjunctionSumScorer(List subScorers, int minimumNrMatchers)
Construct a DisjunctionScorer.

param
subScorers A collection of at least two subscorers.
param
minimumNrMatchers The positive minimum number of subscorers that should match to match this query.
When minimumNrMatchers is bigger than the number of subScorers, no matches will be produced.
When minimumNrMatchers equals the number of subScorers, it more efficient to use ConjunctionScorer.

  
                                                           
        
    super(null);
    
    nrScorers = subScorers.size();

    if (minimumNrMatchers <= 0) {
      throw new IllegalArgumentException("Minimum nr of matchers must be positive");
    }
    if (nrScorers <= 1) {
      throw new IllegalArgumentException("There must be at least 2 subScorers");
    }

    this.minimumNrMatchers = minimumNrMatchers;
    this.subScorers = subScorers;
  
public DisjunctionSumScorer(List subScorers)
Construct a DisjunctionScorer, using one as the minimum number of matching subscorers.

    this(subScorers, 1);
  
Methods Summary
protected booleanadvanceAfterCurrent()
Advance all subscorers after the current document determined by the top of the scorerQueue. Repeat until at least the minimum number of subscorers match on the same document and all subscorers are after that document or are exhausted.
On entry the scorerQueue has at least minimumNrMatchers available. At least the scorer with the minimum document number will be advanced.

return
true iff there is a match.
In case there is a match, currentDoc, currentSumScore, and nrMatchers describe the match.
todo
Investigate whether it is possible to use skipTo() when the minimum number of matchers is bigger than one, ie. try and use the character of ConjunctionScorer for the minimum number of matchers.

    do { // repeat until minimum nr of matchers
      Scorer top = (Scorer) scorerQueue.top();
      currentDoc = top.doc();
      currentScore = top.score();
      nrMatchers = 1;
      do { // Until all subscorers are after currentDoc
        if (top.next()) {
          scorerQueue.adjustTop();
        } else {
          scorerQueue.pop();
          if (scorerQueue.size() < (minimumNrMatchers - nrMatchers)) {
            // Not enough subscorers left for a match on this document,
            // and also no more chance of any further match.
            return false;
          }
          if (scorerQueue.size() == 0) {
            break; // nothing more to advance, check for last match.
          }
        }
        top = (Scorer) scorerQueue.top();
        if (top.doc() != currentDoc) {
          break; // All remaining subscorers are after currentDoc.
        } else {
          currentScore += top.score();
          nrMatchers++;
        }
      } while (true);
      
      if (nrMatchers >= minimumNrMatchers) {
        return true;
      } else if (scorerQueue.size() < minimumNrMatchers) {
        return false;
      }
    } while (true);
  
public intdoc()

 return currentDoc; 
public org.apache.lucene.search.Explanationexplain(int doc)
Gives and explanation for the score of a given document.

todo
Show the resulting score. See BooleanScorer.explain() on how to do this.

    Explanation res = new Explanation();
    res.setDescription("At least " + minimumNrMatchers + " of");
    Iterator ssi = subScorers.iterator();
    while (ssi.hasNext()) {
      res.addDetail( ((Scorer) ssi.next()).explain(doc));
    }
    return res;
  
private voidinitScorerQueue()
Called the first time next() or skipTo() is called to initialize scorerQueue.

    Iterator si = subScorers.iterator();
    scorerQueue = new ScorerQueue(nrScorers);
    while (si.hasNext()) {
      Scorer se = (Scorer) si.next();
      if (se.next()) { // doc() method will be used in scorerQueue.
        scorerQueue.insert(se);
      }
    }
  
public booleannext()

    if (scorerQueue == null) {
      initScorerQueue();
    }
    if (scorerQueue.size() < minimumNrMatchers) {
      return false;
    } else {
      return advanceAfterCurrent();
    }
  
public intnrMatchers()
Returns the number of subscorers matching the current document. Initially invalid, until {@link #next()} is called the first time.

    return nrMatchers;
  
public floatscore()
Returns the score of the current document matching the query. Initially invalid, until {@link #next()} is called the first time.

 return currentScore; 
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.
The implementation uses the skipTo() method on the subscorers.

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

    if (scorerQueue == null) {
      initScorerQueue();
    }
    if (scorerQueue.size() < minimumNrMatchers) {
      return false;
    }
    if (target <= currentDoc) {
      target = currentDoc + 1;
    }
    do {
      Scorer top = (Scorer) scorerQueue.top();
      if (top.doc() >= target) {
        return advanceAfterCurrent();
      } else if (top.skipTo(target)) {
        scorerQueue.adjustTop();
      } else {
        scorerQueue.pop();
        if (scorerQueue.size() < minimumNrMatchers) {
          return false;
        }
      }
    } while (true);