package com.senseidb.search.query.filters; import com.browseengine.bobo.api.BoboIndexReader; import com.browseengine.bobo.facets.filter.RandomAccessFilter; import org.apache.lucene.index.IndexReader; import org.apache.lucene.search.DocIdSet; import org.apache.lucene.search.Filter; import java.io.IOException; /** * A filter implementation that provides an expected cardinality of the associated filter. * The cardinality is intended to be used to optimize filter execution order at runtime. * For instance, an AND filter should always begin the AND using a filter of the LOWEST cardinality to * reduce the number of documents considered in the result set */ public abstract class SenseiFilter extends Filter { protected static final String EMPTY_STRING = FilterConstructor.EMPTY_STRING; @Override public DocIdSet getDocIdSet(IndexReader reader) throws IOException { SenseiDocIdSet docIdSet = getSenseiDocIdSet(reader); return docIdSet.getDocIdSet(); } public abstract SenseiDocIdSet getSenseiDocIdSet(IndexReader reader) throws IOException; public static SenseiFilter buildDefault(final Filter filter) { return buildDefault(filter, null, "UNKNOWN LUCENE FILTER"); } public static SenseiFilter build(final RandomAccessFilter randomAccessFilter, final String queryPlan) throws IOException { return new SenseiFilter() { @Override public SenseiDocIdSet getSenseiDocIdSet(IndexReader reader) throws IOException { double facetSelectivity = randomAccessFilter.getFacetSelectivity((BoboIndexReader) reader); return new SenseiDocIdSet(randomAccessFilter.getDocIdSet(reader), DocIdSetCardinality.exact(facetSelectivity), queryPlan); } }; } public static SenseiFilter buildDefault(final Filter filter, final DocIdSetCardinality suppliedDocIdSetCardinality, final String queryPlan) { return new SenseiFilter() { @Override public SenseiDocIdSet getSenseiDocIdSet(IndexReader reader) throws IOException { // TODO: There needs to be a way to estimate docIdSetCardinality of a column in general. // Either we can maintain a running estimate of the hit rate of a column // or allow a client to preload an expected estimate DocIdSetCardinality docIdSetCardinality = suppliedDocIdSetCardinality == null ? DocIdSetCardinality.random() : suppliedDocIdSetCardinality; return new SenseiDocIdSet(filter.getDocIdSet(reader), docIdSetCardinality, queryPlan); } }; } }