@Override public Scorer filteredScorer(LeafReaderContext context, Weight weight, DocIdSet docIdSet) throws IOException { // CHANGE: If threshold is 0, always pass down the accept docs, don't pay the price of calling // nextDoc even... final Bits filterAcceptDocs = docIdSet.bits(); if (threshold == 0) { if (filterAcceptDocs != null) { return weight.scorer(context, filterAcceptDocs); } else { return FilteredQuery.LEAP_FROG_QUERY_FIRST_STRATEGY.filteredScorer( context, weight, docIdSet); } } // CHANGE: handle "default" value if (threshold == -1) { // default value, don't iterate on only apply filter after query if its not a "fast" // docIdSet // TODO: is there a way we could avoid creating an iterator here? if (filterAcceptDocs != null && DocIdSets.isBroken(docIdSet.iterator())) { return FilteredQuery.QUERY_FIRST_FILTER_STRATEGY.filteredScorer( context, weight, docIdSet); } } return super.filteredScorer(context, weight, docIdSet); }
@Override public DocIdSetIterator iterator() throws IOException { // we try and be smart here, if we can iterate through docsets quickly, prefer to iterate // over them as much as possible, before actually going to "bits" based ones to check List<DocIdSet> iterators = new ArrayList<DocIdSet>(sets.length); List<Bits> bits = new ArrayList<Bits>(sets.length); for (DocIdSet set : sets) { if (DocIdSets.isFastIterator(set)) { iterators.add(set); } else { Bits bit = set.bits(); if (bit != null) { bits.add(bit); } else { iterators.add(set); } } } if (bits.isEmpty()) { return new IteratorBasedIterator(iterators.toArray(new DocIdSet[iterators.size()])); } if (iterators.isEmpty()) { return new BitsDocIdSetIterator(new AndBits(bits.toArray(new Bits[bits.size()]))); } // combination of both..., first iterating over the "fast" ones, and then checking on the more // expensive ones return new BitsDocIdSetIterator.FilteredIterator( new IteratorBasedIterator(iterators.toArray(new DocIdSet[iterators.size()])), new AndBits(bits.toArray(new Bits[bits.size()]))); }