Bobo源码笔记4(collector的创建)

Bobo的收集器基类是SortCollector继承于lucene的Collector类,其中函数是获取收集器的外部接口:

 

public static SortCollector buildSortCollector(Browsable browser,Query q,SortField[] sort,int offset,int count,boolean forceScoring,boolean fetchStoredFields){
		boolean doScoring=forceScoring;
		if (sort == null || sort.length==0){	
			if (q!=null && !(q instanceof MatchAllDocsQuery)){
			  sort = new SortField[]{SortField.FIELD_SCORE};
			}
		}

		if (sort==null || sort.length==0){
			sort = new SortField[]{SortField.FIELD_DOC};
		}
		
		Set<String> facetNames = browser.getFacetNames();
		for (SortField sf : sort){
			if (sf.getType() == SortField.SCORE) {
				doScoring= true;
				break;
			}	
		}

		DocComparatorSource compSource;
		if (sort.length==1){
                        //对sort[]记性转换
                        SortField sf = convert(browser,sort[0]);
			compSource = getComparatorSource(browser,sf);
		}
		else{
			DocComparatorSource[] compSources = new DocComparatorSource[sort.length];
			for (int i = 0; i<sort.length;++i){
				compSources[i]=getComparatorSource(browser,convert(browser,sort[i]));
			}
                        //可以对结果以多个field进行排序,排序的优先级由sort[]中的位置确定,例:sort[0]优先于sort[1]
                        compSource = new MultiDocIdComparatorSource(compSources);
		}
		return new SortCollectorImpl(compSource, sort, browser, offset, count, doScoring, fetchStoredFields);
	}

 

其中convert(browsable , sortField[])函数是对sortField进行转换,如果有该field的facetHandler,那么就必须使用该facetHandler自定义的Comparator(比较器)进行收集(collect):

 

private static SortField convert(Browsable browser,SortField sort){
		String field =sort.getField();
		FacetHandler<?> facetHandler = browser.getFacetHandler(field);
		if (facetHandler!=null){
                        //有该sortField所在域的FacetHandler的时候使用facet自己的Comparator
			BoboCustomSortField sortField = new BoboCustomSortField(field, sort.getReverse(), facetHandler.getDocComparatorSource());
			return sortField;
		}
		else{
			return sort;
		}
	}
 

上面的转换的影响从下边函数里可以体现出来,上面有facet的SortField被转换成BoboCustomSortField,在下面函数中

 if (sf instanceof BoboCustomSortField){
			BoboCustomSortField custField = (BoboCustomSortField)sf;
			DocComparatorSource src = custField.getCustomComparatorSource();
			assert src!=null;
			compSource = src;
		}

使用了facetHandler的比较器的产生器来生产Comparator

 

 

	private static DocComparatorSource getComparatorSource(Browsable browser,SortField sf){
		DocComparatorSource compSource = null;
		//按照文档的id进行排序收集
                if (SortField.FIELD_DOC.equals(sf)){
			compSource = new DocIdDocComparatorSource();
		}//按照文档的得分进行收集
                else if (SortField.FIELD_SCORE.equals(sf) || sf.getType() == SortField.SCORE){
			// we want to do reverse sorting regardless for relevance
			compSource = new ReverseDocComparatorSource(new RelevanceDocComparatorSource());
		}
		else if (sf instanceof BoboCustomSortField){
			BoboCustomSortField custField = (BoboCustomSortField)sf;
			DocComparatorSource src = custField.getCustomComparatorSource();
			assert src!=null;
			compSource = src;
		}
		else{
			Set<String> facetNames = browser.getFacetNames();
			String sortName = sf.getField();
			if (facetNames.contains(sortName)){
				FacetHandler<?> handler = browser.getFacetHandler(sortName);
				assert handler!=null;
				compSource = handler.getDocComparatorSource();
			}
			else{		// default lucene field
				compSource = getNonFacetComparatorSource(sf);
			}
		}
		boolean reverse = sf.getReverse();
		if (reverse){
			compSource = new ReverseDocComparatorSource(compSource);
		}
		compSource.setReverse(reverse);
		return compSource;
	}

 

SortCollectorImpl是sortCollector类的一个实现类,实现Collector类的接口SetNextReader()函数:

 

 @Override
  public void setNextReader(IndexReader reader, int docBase) throws IOException {
    assert reader instanceof BoboIndexReader;
    _currentReader = (BoboIndexReader)reader;
   //得到当前Reader下的比较器
    _currentComparator = _compSource.getComparator(reader,docBase);
    //用于收集当前Reader搜索结果的最小堆,用上面的比较器
    _currentQueue = new DocIDPriorityQueue(_currentComparator, _numHits, docBase);
    MyScoreDoc myScoreDoc = (MyScoreDoc)_tmpScoreDoc;
    myScoreDoc.queue = _currentQueue;
    myScoreDoc.reader = _currentReader;
    myScoreDoc.sortValue = null;
    _pqList.add(_currentQueue);
    _queueFull = false;
  }
 

 最后对多个IndexReader的结果进行merge(合并)

 

 @Override
  public BrowseHit[] topDocs() throws IOException{
    ArrayList<Iterator<MyScoreDoc>> iterList = new ArrayList<Iterator<MyScoreDoc>>(_pqList.size());
    for (DocIDPriorityQueue pq : _pqList){
      int count = pq.size();
      MyScoreDoc[] resList = new MyScoreDoc[count];
      for (int i = count - 1; i >= 0; i--) { 
        resList[i] = (MyScoreDoc)pq.pop();
      }
       //将每个IndexReader的结果从最小堆转移到List中,将每个List的iterator添加到一个List<iterator>中去
       iterList.add(Arrays.asList(resList).iterator());
    }
   //对多个IndexReader的搜索结果队列进行多路归并
    ArrayList<MyScoreDoc> resList = ListMerger.mergeLists(_offset, _count, iterList, MERGE_COMPATATOR);
    Map<String,FacetHandler<?>> facetHandlerMap = _boboBrowser.getFacetHandlerMap();
    return buildHits(resList.toArray(new MyScoreDoc[resList.size()]), _sortFields, facetHandlerMap, _fetchStoredFields);
  }

  //将搜索结果转换成BrowseHit
  protected static BrowseHit[] buildHits(MyScoreDoc[] scoreDocs,SortField[] sortFields,Map<String,FacetHandler<?>> facetHandlerMap,boolean fetchStoredFields)
  throws IOException
  {
    BrowseHit[] hits = new BrowseHit[scoreDocs.length];
    Collection<FacetHandler<?>> facetHandlers= facetHandlerMap.values();
    for (int i =scoreDocs.length-1; i >=0 ; i--)
    {
      MyScoreDoc fdoc = scoreDocs[i];
      BoboIndexReader reader = fdoc.reader;
      BrowseHit hit=new BrowseHit();
      if (fetchStoredFields){

        hit.setStoredFields(reader.document(fdoc.doc));
      }
      Map<String,String[]> map = new HashMap<String,String[]>();
      Map<String,Object[]> rawMap = new HashMap<String,Object[]>();
      for (FacetHandler<?> facetHandler : facetHandlers)
      {
          map.put(facetHandler.getName(),facetHandler.getFieldValues(reader,fdoc.doc));
          rawMap.put(facetHandler.getName(),facetHandler.getRawFieldValues(reader,fdoc.doc));
      }
      hit.setFieldValues(map);
      hit.setRawFieldValues(rawMap);
      hit.setDocid(fdoc.doc+fdoc.queue.base);
      hit.setScore(fdoc.score);
      hit.setComparable(fdoc.getValue());
      hits[i] = hit;
    }
    return hits;
  }
 

 

 

 

 

你可能感兴趣的:(Collector)