package com.browseengine.bobo.facets.filter; import java.io.IOException; import org.apache.lucene.search.DocIdSet; import org.apache.lucene.search.DocIdSetIterator; import org.apache.lucene.util.OpenBitSet; import com.browseengine.bobo.api.BoboSegmentReader; import com.browseengine.bobo.docidset.EmptyDocIdSet; import com.browseengine.bobo.docidset.RandomAccessDocIdSet; import com.browseengine.bobo.facets.FacetHandler; import com.browseengine.bobo.facets.data.MultiValueFacetDataCache; import com.browseengine.bobo.facets.filter.FacetOrFilter.FacetOrDocIdSetIterator; import com.browseengine.bobo.util.BigNestedIntArray; public class MultiValueORFacetFilter extends RandomAccessFilter { private final FacetHandler<?> _facetHandler; private final String[] _vals; private final boolean _takeCompliment; private final FacetValueConverter _valueConverter; public MultiValueORFacetFilter(FacetHandler<?> facetHandler, String[] vals, boolean takeCompliment) { this(facetHandler, vals, FacetValueConverter.DEFAULT, takeCompliment); } public MultiValueORFacetFilter(FacetHandler<?> facetHandler, String[] vals, FacetValueConverter valueConverter, boolean takeCompliment) { _facetHandler = facetHandler; _vals = vals; _valueConverter = valueConverter; _takeCompliment = takeCompliment; } @Override public double getFacetSelectivity(BoboSegmentReader reader) { double selectivity = 0; @SuppressWarnings("unchecked") MultiValueFacetDataCache<String> dataCache = (MultiValueFacetDataCache<String>) _facetHandler .getFacetData(reader); int[] idxes = _valueConverter.convert(dataCache, _vals); if (idxes == null) { return 0.0; } int accumFreq = 0; for (int idx : idxes) { accumFreq += dataCache.freqs[idx]; } int total = reader.maxDoc(); selectivity = (double) accumFreq / (double) total; if (selectivity > 0.999) { selectivity = 1.0; } return selectivity; } public final static class MultiValueOrFacetDocIdSetIterator extends FacetOrDocIdSetIterator { private final BigNestedIntArray _nestedArray; public MultiValueOrFacetDocIdSetIterator(MultiValueFacetDataCache<?> dataCache, OpenBitSet bs) { super(dataCache, bs); _nestedArray = dataCache._nestedArray; } @Override final public int nextDoc() throws IOException { return (_doc = (_doc < _maxID ? _nestedArray.findValues(_bitset, (_doc + 1), _maxID) : NO_MORE_DOCS)); } @Override final public int advance(int id) throws IOException { if (_doc < id) { return (_doc = (id <= _maxID ? _nestedArray.findValues(_bitset, id, _maxID) : NO_MORE_DOCS)); } return nextDoc(); } } @Override public RandomAccessDocIdSet getRandomAccessDocIdSet(BoboSegmentReader reader) throws IOException { @SuppressWarnings("unchecked") final MultiValueFacetDataCache<String> dataCache = (MultiValueFacetDataCache<String>) _facetHandler .getFacetData(reader); final int[] index = _valueConverter.convert(dataCache, _vals); final BigNestedIntArray nestedArray = dataCache._nestedArray; final OpenBitSet bitset = new OpenBitSet(dataCache.valArray.size()); for (int i : index) { bitset.fastSet(i); } if (_takeCompliment) { // flip the bits int size = dataCache.valArray.size(); for (int i = 0; i < size; ++i) { bitset.fastFlip(i); } } long count = bitset.cardinality(); if (count == 0) { final DocIdSet empty = EmptyDocIdSet.getInstance(); return new RandomAccessDocIdSet() { @Override public boolean get(int docId) { return false; } @Override public DocIdSetIterator iterator() throws IOException { return empty.iterator(); } }; } else { return new RandomAccessDocIdSet() { @Override public DocIdSetIterator iterator() { return new MultiValueOrFacetDocIdSetIterator(dataCache, bitset); } @Override final public boolean get(int docId) { return nestedArray.contains(docId, bitset); } }; } } }