咱們先來回顧下,一個基本的搜索流程是怎麼完成的
1,獲得一個索引目錄Directory(可能基於內存的或者磁盤的)。
2,獲得一個DirectoryReader。
3,實例化查詢組件IndexSearcher。
4,檢索獲得TopDoc查詢結果集
5,遍歷ScoresDocs處理結果
咱們看下這個檢索的流程,大概能夠分這5步,前1,2,3算是準備工做,後面的2步是咱們常常須要進行數據處理的地方,那麼咱們Collector到底工做在哪一步呢?,其實Collector真正的起做用是在3-4步之間的。
那麼Collector的做用是幹什麼的?爲何須要使用Collector?
在這以前先分析下TopDocs這個類,這個類的工做原理,其實在後臺使用的也是一個收集器,收收集咱們檢索的結果,經過TopDocsCollector這個基類下面的2個子類收集器,來收集一次咱們檢索的命中數據。
因此collector的做用就是收集某些咱們須要定製化的結果集,某些狀況下使用collector能夠能夠極大的提高咱們程序的性能,經過collector可讓咱們對每個匹配上的文檔作一些特有的定製化操做,固然前提是在咱們須要使用的狀況下。
下面咱們來看下collector基類的幾個方法
java
方法 | 說明 |
collect() | 檢索時,每匹配上一個文檔,都會調用此方法 |
acceptsDocsOutOfOrder() | 測試本collector是否能處理無序到達的docid |
setScorer(Scorer scorer) | 處理檢索結果的評分 |
setNextReader(AtomicReaderContext context) | 檢索時,在多個索引段結構之間切換的方法 |
下面咱們來看下自定義的一個collector來實現ScoreDoc類的功能,代碼以下.
apache
package com.piaoxuexianjing; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.apache.lucene.index.AtomicReaderContext; import org.apache.lucene.search.Collector; import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.Scorer; /** * @author * @version 1.0 * * 自定義收集器 * 實現評分收集 * **/ public class MyScoreCollector extends Collector { //private HashMap<String, String> documents=new HashMap<String, String>(); List<ScoreDoc> docs=new ArrayList<ScoreDoc>(); private Scorer scorer;//scorer類 private int docBase;//全局相對段基數 @Override public boolean acceptsDocsOutOfOrder() { // TODO Auto-generated method stub //返回true是容許無次序的ID //返回false必須是有次序的 return true; } @Override public void collect(int arg0) throws IOException { /** * 匹配上一個文檔 * 就記錄其docid與打分狀況 * * */ docs.add(new ScoreDoc(arg0+docBase,scorer.score()));// } // BinaryDocValues names;//字符類型的內置存儲 // BinaryDocValues bookNames;//字符類型的內置存儲 // BinaryDocValues ids;//字符類型的內置存儲 // BinaryDocValues prices;//字符類型的內置存儲 // FieldCache.Doubles d ; //數值類型的內置存儲 // FieldCache.Ints ints;//數值類型的內置存儲 @Override public void setNextReader(AtomicReaderContext arg0) throws IOException { this.docBase=arg0.docBase;//記錄每一個索引段結構的相對位置 } @Override public void setScorer(Scorer arg0) throws IOException { // TODO Auto-generated method stub this.scorer=arg0;//記錄改匹配的打分狀況 } }
測試類的核心代碼
ide
//自定義收集器 MyScoreCollector scoreCollector=new MyScoreCollector(); searcher.search(new MatchAllDocsQuery(), scoreCollector); /** * 自定義的收集類,實現效果===>ScoreDocs類 * **/ List<ScoreDoc> s=scoreCollector.docs; for(ScoreDoc sc:s){ System.out.println(sc.doc+"===="+sc.score); }
輸出結果以下性能
0====1.0 1====1.0 2====1.0 3====1.0 4====1.0 5====1.0 6====1.0 7====1.0
至此,咱們就利用自定義的collector完成了一個簡單的收集評分功能,固然咱們能夠根據本身的業務,來實現各類各樣的collector,靈活運用!
測試