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; }
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); }
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); } }
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); } } }