Reputation: 2135
How to apply a org.apache.lucene.search.Query
on a given org.apache.lucene.util.Bits
object?
Background: I have a subclass of org.apache.lucene.index.FilterLeafReader
where i want to filter the livedocs by applying a query on the "Bits".
According to javadoc i need also to override numDocs()
if i override getLiveDocs()
. So the question extends also to how to filter the number of documents based on a query (within a FilterLeafReader
)
Upvotes: 2
Views: 364
Reputation: 2135
I ended up with this solution (after asking the question on the lucene mailinglist):
final IndexSearcher searcher = new IndexSearcher(reader);
searcher.setQueryCache(null);
final boolean needsScores = false; // scores are not needed, only matching docs
final Weight preserveWeight = searcher.createNormalizedWeight(preserveFilter, needsScores);
final int maxDoc = in.maxDoc();
final FixedBitSet bits = new FixedBitSet(maxDoc);
// ignore livedocs here, as we filter them later:
final Scorer preverveScorer = preserveWeight.scorer(context);
if (preverveScorer != null) {
bits.or(preverveScorer.iterator());
}
if (negateFilter) {
bits.flip(0, maxDoc);
}
if (in.hasDeletions()) {
final Bits oldLiveDocs = in.getLiveDocs();
assert oldLiveDocs != null;
final DocIdSetIterator it = new BitSetIterator(bits, 0L); // the cost is not useful here
for (int i = it.nextDoc(); i != DocIdSetIterator.NO_MORE_DOCS; i = it.nextDoc()) {
if (!oldLiveDocs.get(i)) {
// we can safely modify the current bit, as the iterator already stepped over it:
bits.clear(i);
}
}
}
this.liveDocs = bits;
this.numDocs = bits.cardinality();
Upvotes: 1