salyh
salyh

Reputation: 2135

Apply Lucene Query on Bits

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

Answers (1)

salyh
salyh

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

https://github.com/apache/lucene-solr/blob/master/lucene/misc/src/java/org/apache/lucene/index/PKIndexSplitter.java#L127-L170

Upvotes: 1

Related Questions