@Override public FacetCountCollectorSource getFacetCountCollectorSource(final BrowseSelection sel,final FacetSpec ospec) { return new FacetCountCollectorSource() { @Override public FacetCountCollector getFacetCountCollector(BoboIndexReader reader, int docBase) { FacetDataCache dataCache = getFacetData(reader); return new RangeFacetCountCollector(_name,dataCache,docBase,ospec,_predefinedRanges); } }; }
private final static class NoNeedFacetValidator extends FacetValidator{ NoNeedFacetValidator(FacetHitCollector[] collectors) throws IOException{ super(collectors,0); } @Override public final boolean validate(int docid) throws IOException { for (FacetCountCollector collector : _countCollectors){ collector.collect(docid); } return true; } }
其中的FacetCountCollector是RangeFacetCountClollector,其收集函数也是很简单的计数:
public final void collect(int docid) { _count[_array.get(docid)]++; }
这样呢,对每个搜索结果和过滤结果都符合的doc,对应的_count[]都进行加一计算。
public List<BrowseFacet> getFacets() { if (_ospec!=null){ if (_predefinedRangeIndexes!=null) { int minCount=_ospec.getMinHitCount(); //int maxNumOfFacets = _ospec.getMaxCount(); //if (maxNumOfFacets <= 0 || maxNumOfFacets > _predefinedRangeIndexes.length) maxNumOfFacets = _predefinedRangeIndexes.length; int[] rangeCount = new int[_predefinedRangeIndexes.length]; //对每一个Range做计数统计 for (int k=0;k<_predefinedRangeIndexes.length;++k) { int count = 0; //范围Range的起始值 int idx = _predefinedRangeIndexes[k][0]; //Range的终止值 int end = _predefinedRangeIndexes[k][1]; while(idx <= end) { count += _count[idx++]; } rangeCount[k] = count; } List<BrowseFacet> facetColl = new ArrayList<BrowseFacet>(_predefinedRanges.size()); for (int k=0;k<_predefinedRangeIndexes.length;++k) { if(rangeCount[k] >= minCount) { BrowseFacet choice=new BrowseFacet(_predefinedRanges.get(k), rangeCount[k]); facetColl.add(choice); } //if(facetColl.size() >= maxNumOfFacets) break; } return facetColl; } else { return FacetCountCollector.EMPTY_FACET_LIST; } } else { return FacetCountCollector.EMPTY_FACET_LIST; } }
@Override final public int nextDoc() throws IOException { return (_doc = (_doc < _maxID ? _orderArray.findValueRange(_start, _end, (_doc + 1), _maxID) : NO_MORE_DOCS)); } @Override final public int advance(int id) throws IOException { if (_doc < id) { return (_doc = (id <= _maxID ? _orderArray.findValueRange(_start, _end, id, _maxID) : NO_MORE_DOCS)); } return nextDoc(); }
其实也跟SimpleFacet差不多,就是多了个_start和_end,nextDoc()的时候不是判断是否和过滤值相等,而是判断是否在[_start, _end] 范围内