Пример #1
0
 private BulkScorerAndDoc advance(int min) throws IOException {
   assert tail.size() == minShouldMatch - 1;
   final HeadPriorityQueue head = this.head;
   final TailPriorityQueue tail = this.tail;
   BulkScorerAndDoc headTop = head.top();
   BulkScorerAndDoc tailTop = tail.top();
   while (headTop.next < min) {
     if (tailTop == null || headTop.cost <= tailTop.cost) {
       headTop.advance(min);
       headTop = head.updateTop();
     } else {
       // swap the top of head and tail
       final BulkScorerAndDoc previousHeadTop = headTop;
       tailTop.advance(min);
       headTop = head.updateTop(tailTop);
       tailTop = tail.updateTop(previousHeadTop);
     }
   }
   return headTop;
 }
Пример #2
0
  private BulkScorerAndDoc scoreWindow(
      BulkScorerAndDoc top,
      LeafCollector collector,
      LeafCollector singleClauseCollector,
      Bits acceptDocs,
      int min,
      int max)
      throws IOException {
    final int windowBase = top.next & ~MASK; // find the window that the next match belongs to
    final int windowMin = Math.max(min, windowBase);
    final int windowMax = Math.min(max, windowBase + SIZE);

    // Fill 'leads' with all scorers from 'head' that are in the right window
    leads[0] = head.pop();
    int maxFreq = 1;
    while (head.size() > 0 && head.top().next < windowMax) {
      leads[maxFreq++] = head.pop();
    }

    if (minShouldMatch == 1 && maxFreq == 1) {
      // special case: only one scorer can match in the current window,
      // we can collect directly
      final BulkScorerAndDoc bulkScorer = leads[0];
      scoreWindowSingleScorer(
          bulkScorer, singleClauseCollector, acceptDocs, windowMin, windowMax, max);
      return head.add(bulkScorer);
    } else {
      // general case, collect through a bit set first and then replay
      scoreWindowMultipleScorers(collector, acceptDocs, windowBase, windowMin, windowMax, maxFreq);
      return head.top();
    }
  }
Пример #3
0
  private void scoreWindowMultipleScorers(
      LeafCollector collector,
      Bits acceptDocs,
      int windowBase,
      int windowMin,
      int windowMax,
      int maxFreq)
      throws IOException {
    while (maxFreq < minShouldMatch && maxFreq + tail.size() >= minShouldMatch) {
      // a match is still possible
      final BulkScorerAndDoc candidate = tail.pop();
      candidate.advance(windowMin);
      if (candidate.next < windowMax) {
        leads[maxFreq++] = candidate;
      } else {
        head.add(candidate);
      }
    }

    if (maxFreq >= minShouldMatch) {
      // There might be matches in other scorers from the tail too
      for (int i = 0; i < tail.size(); ++i) {
        leads[maxFreq++] = tail.get(i);
      }
      tail.clear();

      scoreWindowIntoBitSetAndReplay(
          collector, acceptDocs, windowBase, windowMin, windowMax, leads, maxFreq);
    }

    // Push back scorers into head and tail
    for (int i = 0; i < maxFreq; ++i) {
      final BulkScorerAndDoc evicted = head.insertWithOverflow(leads[i]);
      if (evicted != null) {
        tail.add(evicted);
      }
    }
  }
Пример #4
0
  private void scoreWindowSingleScorer(
      BulkScorerAndDoc bulkScorer,
      LeafCollector collector,
      Bits acceptDocs,
      int windowMin,
      int windowMax,
      int max)
      throws IOException {
    assert tail.size() == 0;
    final int nextWindowBase = head.top().next & ~MASK;
    final int end = Math.max(windowMax, Math.min(max, nextWindowBase));

    bulkScorer.score(collector, acceptDocs, windowMin, end);

    // reset the scorer that should be used for the general case
    collector.setScorer(fakeScorer);
  }
Пример #5
0
  BooleanScorer(
      BooleanWeight weight,
      boolean disableCoord,
      int maxCoord,
      Collection<BulkScorer> scorers,
      int minShouldMatch,
      boolean needsScores) {
    if (minShouldMatch < 1 || minShouldMatch > scorers.size()) {
      throw new IllegalArgumentException(
          "minShouldMatch should be within 1..num_scorers. Got " + minShouldMatch);
    }
    if (scorers.size() <= 1) {
      throw new IllegalArgumentException(
          "This scorer can only be used with two scorers or more, got " + scorers.size());
    }
    for (int i = 0; i < buckets.length; i++) {
      buckets[i] = new Bucket();
    }
    this.leads = new BulkScorerAndDoc[scorers.size()];
    this.head = new HeadPriorityQueue(scorers.size() - minShouldMatch + 1);
    this.tail = new TailPriorityQueue(minShouldMatch - 1);
    this.minShouldMatch = minShouldMatch;
    for (BulkScorer scorer : scorers) {
      if (needsScores == false) {
        // OrCollector calls score() all the time so we have to explicitly
        // disable scoring in order to avoid decoding useless norms
        scorer = BooleanWeight.disableScoring(scorer);
      }
      final BulkScorerAndDoc evicted = tail.insertWithOverflow(new BulkScorerAndDoc(scorer));
      if (evicted != null) {
        head.add(evicted);
      }
    }
    this.cost = cost(scorers, minShouldMatch);

    coordFactors = new float[scorers.size() + 1];
    for (int i = 0; i < coordFactors.length; i++) {
      coordFactors[i] = disableCoord ? 1.0f : weight.coord(i, maxCoord);
    }
  }