Bobo源码笔记2(创建FacetValidator)

在browse()函数中有这样一段代码。这段代码做了两件事:一,根据每个facet的过滤条件创建filter;二,根据每个facet的分组计数规则创建FacetHitCollector

 for (String name : fields)//对应于每一个Facet
      {
        //得到该facet的筛选条件
        BrowseSelection sel = req.getSelection(name);
        //得到该facet分组计数规则
        FacetSpec ospec = req.getFacetSpec(name);

        FacetHandler<?> handler = getFacetHandler(name);
        
        if (handler == null){
        	logger.warn("facet handler: "+name+" is not defined, ignored.");
        	continue;
        }
        
        FacetHitCollector facetHitCollector = null;

        RandomAccessFilter filter = null;
        //如果该Facet下有selection,那么构建该facet的filter
        if (sel != null)
        {
          filter = handler.buildFilter(sel);
        }

        if (ospec == null)
        {//若ospec为空,那么不对该facet进行分组计数
          if (filter != null)
          {
            preFilterList.add(filter);
          }
        }
        else
        {

          FacetSpec fspec = ospec;
          //创建FacetHitCollector
          facetHitCollector = new FacetHitCollector();
          facetHitCollector.facetHandler = handler;
          
          if (isDefaultSearch)
          {//不做query,无过滤条件,相当于将索引中的各个facet的计数分组显示出来
        	facetHitCollector._collectAllSource=handler.getFacetCountCollectorSource(sel, fspec);
          }
          else
          {//得到分组计数产生器,并将它赋值给facetHitCollector
            facetHitCollector._facetCountCollectorSource = handler.getFacetCountCollectorSource(sel, fspec);            
            if (ospec.isExpandSelection())
            {
              if (isNoQueryNoFilter && sel!=null && selCount == 1)
              {
            	facetHitCollector._collectAllSource=handler.getFacetCountCollectorSource(sel, fspec);
                if (filter != null)
                {
                  preFilterList.add(filter);
                }
              }
              else
              {
                if (filter != null)
                {
                	facetHitCollector._filter = filter;
                }
              }
            }
            else
            {
              if (filter != null)
              {
                preFilterList.add(filter);
              }
            }
          }
        }
        if (facetHitCollector != null)
        {//对每一个设置了FacetSpec的facet,都有一个FacetHitCollector,将它们整理到一个list中
          facetHitCollectorList.add(facetHitCollector);
        }
      }

类FacetValidator是基类,_collectors是BoboSubBrowser维护的List<FacetHitCollector>列表赋值过来的,也就是上面代码

facetHitCollectorList.add(facetHitCollector);

中的facetHitCollectorList

下边看一下FacetValidator类用于针对于不同的IndexReader进行初始化的函数:

  abstract static class FacetValidator
{ 
 public void setNextReader(BoboIndexReader reader,int docBase) throws IOException{
      ArrayList<FacetCountCollector> collectorList = new ArrayList<FacetCountCollector>();
      sortPostCollectors(reader);
      for (int i=0;i<_collectors.length;++i){
        //对每个Facet对应的FacetHitCollector进行初始化工作,下面会提到
        _collectors[i].setNextReader(reader, docBase);
        FacetCountCollector collector = _collectors[i]._currentPointers.facetCountCollector;
        if(collector != null)
        {
          collectorList.add(collector);
        }
      }
      _countCollectors = collectorList.toArray(new FacetCountCollector[collectorList.size()]);
    }
}
 

接下来看一下FacetHitCollector这个类,其成员FacetCountCollectorSource用于创建 FacetCountCollector。那么FacetCountCollector是用来做什么的呢?它主要是用于统计在搜索结果以及过滤条件下,在 每个facet下每一个属性(对于设置了selection的facet,只有过滤条件对应的属性count才有值)所命中的文档的个数 ,其函数SetNextReader由FacetValidator的setNextReader函数调用:

public final class FacetHitCollector{
	
	public FacetCountCollectorSource _facetCountCollectorSource;//分组计数器的产生器	
	public FacetCountCollectorSource _collectAllSource = null;
	public FacetHandler<?> facetHandler;//该分组计数器对应的Facet
	public RandomAccessFilter _filter;
	public final CurrentPointers _currentPointers = new CurrentPointers();
	//
        public LinkedList<FacetCountCollector> _countCollectorList = new LinkedList<FacetCountCollector>();
	public LinkedList<FacetCountCollector> _collectAllCollectorList = new LinkedList<FacetCountCollector>();
	
	public void setNextReader(BoboIndexReader reader,int docBase) throws IOException{
		if (_collectAllSource!=null){
			FacetCountCollector collector = _collectAllSource.getFacetCountCollector(reader, docBase);
			_collectAllCollectorList.add(collector);
			collector.collectAll();
		}
		else{
		  if (_filter!=null){
			_currentPointers.docidSet = _filter.getRandomAccessDocIdSet(reader);
			_currentPointers.postDocIDSetIterator = _currentPointers.docidSet.iterator();
			_currentPointers.doc = _currentPointers.postDocIDSetIterator.nextDoc();
		  }
		  if (_facetCountCollectorSource!=null){
                    //根据产生器创建分组计数器FacetCountCollector,并把它赋给_currentPointers(当前Reader的配置)
                     _currentPointers.facetCountCollector = _facetCountCollectorSource.getFacetCountCollector(reader, docBase);
		   //同一个facet下,每一个IndexReader的facetCountCollector都被记录起来,放到一个list中,收集计数的时候用来做合并
                     _countCollectorList.add(_currentPointers.facetCountCollector);
		  }
		}
	}
	//当前的IndexReader下对应的一些配置,每个IndexReader下使用的分组计数器都是不同的
	public static class CurrentPointers{
		public RandomAccessDocIdSet docidSet=null;
		public DocIdSetIterator postDocIDSetIterator = null;
		public int doc;
		public FacetCountCollector facetCountCollector;
	}
}

FacetValidator的validate(docid)用于对facet进行分组计数:

   通常FacetSpec默认设置ExpandSelection为false ,那么CreateFacetValidator ()返回的是 new NoNeedFavalidator (FacetHitCollector[]),其validate()函数如下:

    @Override
    public final boolean validate(int docid) throws IOException {
      for (FacetCountCollector collector : _countCollectors){
        collector.collect(docid);
      }
      return true;
    }
 

分组计数器的基类是FacetCountCollector,只定义了几个接口,它的abstract子类:

public abstract class DefaultFacetCountCollector implements FacetCountCollector
{
   protected final FacetSpec _ospec;
  public int[] _count;//存放计数结果的int数组,长度对应于FacetDataCache中的freqs[],也就是属性的个数
  public int _countlength;//计数数组长度
  protected FacetDataCache _dataCache;//facet的缓存数据
  private final String _name;//facet的名称
  protected final BrowseSelection _sel;//过滤条件
  protected final BigSegmentedArray _array;//<docid , index> 的映射 
}

具体的FacetCountCollector实现类 ,有很多实现,这里只看一下常用的SimpleFacetCountCollector

public static final class SimpleFacetCountCollector extends DefaultFacetCountCollector
	{
		public SimpleFacetCountCollector(String name,FacetDataCache dataCache,int docBase,BrowseSelection sel,FacetSpec ospec)
		{
		    super(name,dataCache,docBase,sel,ospec);
		}
		//主要函数
		public final void collect(int docid) {
                    //根据docid,查到index,再将该属性的计数加一
                      _count[_array.get(docid)]++;
		}
		
		public final void collectAll() {
		  _count = _dataCache.freqs;
		}
	}
 

猜你喜欢

转载自eric-gcm.iteye.com/blog/1672171