Lucene的高亮顯示)

在Lucene的org.apache.lucene.search.highlight包中提供了關於高亮顯示檢索關鍵字的工具。我們在使用百度、Google搜索的時候,檢索結果顯示的時候,在摘要中實現與關鍵字相同的詞條進行高亮顯示,百度和Google指定紅色高亮顯示。

    有了Lucene提供的高亮顯示的工具,可以很方便地實現高亮顯示的功能。

    高亮顯示,就是根據用戶輸入的檢索關鍵字,檢索找到該關鍵字對應的檢索結果文件,提取對應於該文件的摘要文本,然後根據設置的高亮格式,將格式寫入到摘要文本中對應的與關鍵字相同或相似的詞條上,在網頁上顯示出來,該摘要中的與關鍵字有關的文本就會以高亮的格式顯示出來。

    高亮顯示模塊需要兩個獨立的輸入:完整的原始文本以用來提供操作數據,以及來源於該文本的一個TokenStream。爲了創建TokenStream,你必須對文本進行重新分析,此時需要使用與索引期間相同的分析器進行。
Highlighter依賴於詞彙單元流中每個詞彙單元的起始和結束位置偏移量來將原始輸入文本中的字符片段進行精確定位,來用於高亮顯示。

高亮處理的相關概念:


Fragmenter

   作用是將原始字符串拆分成獨立的片段。

  NullFragmenter 是該接口的一個具體實現類,它將整個字符串作爲單個片段返回,這適合於處理title域和前臺文本較短的域,而對於這些域來說,我們是希望在搜索結果中全部展示。

 SimpleFragmenter 是負責將文本拆分封固定字符長度的片段,但它並處理子邊界。你可以指定每個片段的字符長度(默認情況100)但這類片段有點過於簡單,在創建片段時,他並不限制查詢語句的位置,因此對於跨度的匹配操作會輕易被拆分到兩個片段中;

 SimpleSpanFragmenter 是嘗試將讓片段永遠包含跨度匹配的文檔。

如果不Highlighter實例中設置Fragmenter,那麼它會默認的SimpleFragmenter。

 

Scorer

  Fragmenter輸出的是文本片段序列,而Highlighter必須從中挑選出最適合的一個或多個片段呈現給客戶,爲了做到這點,Highlighter會要求Java接口Scorer來對每個片段進行評分。
   Highlighter提供了兩個Scorer具體實現類:QueryTermScorer和QueryScorer
QueryTermScorer 基於片段中對應Query的項數進行評分。
QueryScorer只對促成文檔匹配的實際項進行評分。
 

Encoder

   他的目的很簡單,將初始文本編碼成外部格式。該接口實現有兩個:
DefaultEncoder:默認情況下供Hightlighter使用,它並不對文本進行任何操作。
SimpleHTMLEncoder:負責將文本編碼成HTML,並忽略一些如< 、>以及其它非ASCII等特殊字符。一旦完成編碼,最後一步就是對片段進行格式化處理向用戶展現。
 

Formatter

   它負責將片段轉換成String形式,以及將被高亮顯示的項一起用於搜索結果展示以及高亮顯示。


Java代碼  收藏代碼
  1. public class Demo {  
  2.   
  3.     /** 
  4.      * 將即將檢索的資源寫入索引庫 
  5.      * @param writer 
  6.      * @throws Exception 
  7.      */  
  8.     public void buildDocs(IndexWriter writer)throws Exception {  
  9.         writer.deleteAll();//清空索引庫裏已存在的文檔(document)  
  10.         List<User> list = DataUtil.getUsers_more();//得到數據資源  
  11.         System.out.println("buildDocs()->總人數爲 :"+list.size());  
  12.         for(User user :list){  
  13.             Document doc = new Document();//創建索引庫的文檔  
  14.             doc.add(new Field("id",String.valueOf(user.getId()),Store.YES,Index.NO));  
  15.             doc.add(new Field("name",user.getName(),Store.YES,Index.ANALYZED));  
  16.             doc.add(new Field("age",String.valueOf(user.getAge()),Store.YES,Index.ANALYZED));  
  17.             doc.add(new Field("sex",user.getSex(),Store.YES,Index.ANALYZED));  
  18.             doc.add(new Field("birthday",String.valueOf(user.getBirthday()),Store.YES,Index.ANALYZED));  
  19.             writer.addDocument(doc);//將文檔寫入索引庫  
  20.         }  
  21.         int count =writer.numDocs();  
  22.         writer.forceMerge(100);//合併索引庫文件  
  23.         writer.close();  
  24.         System.out.println("buildDocs()->存入索引庫的數量:"+count);  
  25.     }  
  26.   
  27. }  
 
Java代碼  收藏代碼
  1. public class HighlighterDemo extends Demo {  
  2.   
  3.     /** 
  4.      * 從索引庫中搜索你要查詢的數據,並做最簡單的高亮處理 html的<B>標籤修飾 
  5.      * @param searcher 
  6.      * @throws IOException 
  7.      * @throws InvalidTokenOffsetsException  
  8.      * @throws ParseException  
  9.      */  
  10.     public void searToHighlighter(Analyzer analyzer,IndexSearcher searcher) throws IOException, InvalidTokenOffsetsException, ParseException{  
  11.         //Term term =new Term("sex", "男生");//查詢條件,意思是我要查找性別爲“男生”的人  
  12.         //PrefixQuery query =new PrefixQuery(term);  
  13.         QueryParser parser = new QueryParser(Version.LUCENE_36,"sex", analyzer);    
  14.         Query query = parser.parse("男生");  
  15.           
  16.           
  17.         TopDocs docs =searcher.search(query,null10);//查找  
  18.         System.out.println("searcherDoc()->男生人數:"+docs.totalHits);  
  19.           
  20.         QueryScorer scorer=new QueryScorer(query);  
  21.         Fragmenter fragmenter = new SimpleSpanFragmenter(scorer);  
  22.         Highlighter highlight=new Highlighter(scorer);  
  23.         highlight.setTextFragmenter(fragmenter);  
  24.           
  25.         int seq=0;  
  26.         for(ScoreDoc doc:docs.scoreDocs){//獲取查找的文檔的屬性數據  
  27.             seq++;  
  28.             int docID=doc.doc;  
  29.             Document document =searcher.doc(docID);  
  30.             String str="序號:"+seq+",ID:"+document.get("id")+",姓名:"+document.get("name")+",性別:" ;  
  31.             String value =document.get("sex");  
  32.             if (value != null) {    
  33.                 TokenStream tokenStream = analyzer.tokenStream("sex"new StringReader(value));    
  34.                 String str1 = highlight.getBestFragment(tokenStream, value);    
  35.                 str=str+str1;    
  36.             }     
  37.             System.out.println("查詢出人員:"+str);  
  38.         }  
  39.     }  
  40.       
  41.     /** 
  42.      * 從索引庫中搜索你要查詢的數據,使用CSS進行高亮顯示處理 
  43.      * @param analyzer 
  44.      * @param searcher 
  45.      * @throws IOException 
  46.      * @throws InvalidTokenOffsetsException 
  47.      */  
  48.     public void searToHighlighterCss(Analyzer analyzer,IndexSearcher searcher) throws IOException, InvalidTokenOffsetsException{  
  49.         Term term =new Term("sex""男生");//查詢條件,意思是我要查找性別爲“男生”的人  
  50.         TermQuery query =new TermQuery(term);  
  51.         TopDocs docs =searcher.search(query, 10);//查找  
  52.         System.out.println("searcherDoc()->男生人數:"+docs.totalHits);  
  53.           
  54.         /**自定義標註高亮文本標籤*/  
  55.         SimpleHTMLFormatter formatter = new SimpleHTMLFormatter("<span class=\"hightlighterCss\">","</span>");  
  56.         /**創建QueryScorer*/  
  57.         QueryScorer scorer=new QueryScorer(query);  
  58.         /**創建Fragmenter*/  
  59.         Fragmenter fragmenter = new SimpleSpanFragmenter(scorer);  
  60.         Highlighter highlight=new Highlighter(formatter,scorer);  
  61.         highlight.setTextFragmenter(fragmenter);  
  62.           
  63.         int seq=0;  
  64.         for(ScoreDoc doc:docs.scoreDocs){//獲取查找的文檔的屬性數據  
  65.             seq++;  
  66.             int docID=doc.doc;  
  67.             Document document =searcher.doc(docID);  
  68.             String str="序號:"+seq+",ID:"+document.get("id")+",姓名:"+document.get("name")+",性別:" ;  
  69.             String value =document.get("sex");  
  70.             if (value != null) {    
  71.                 TokenStream tokenStream = analyzer.tokenStream("sex"new StringReader(value));    
  72.                 String str1 = highlight.getBestFragment(tokenStream, value);    
  73.                 str=str+str1;    
  74.             }     
  75.             System.out.println("查詢出人員:"+str);  
  76.         }  
  77.     }  
  78. }  
 

Java代碼  收藏代碼
  1. public class TestHighlighter {  
  2.     private IndexWriter writer=null;  
  3.     private Directory directory=null;  
  4.     private IndexReader reader = null;  
  5.     private IndexSearcher searcher=null;  
  6.     private HighlighterDemo demo =new HighlighterDemo();  
  7.     private Analyzer analyzer =null;  
  8.       
  9.     @Before  
  10.     public void setUp() throws Exception {  
  11.         directory = new SimpleFSDirectory(new File("F:/luc_dir"));  
  12.         analyzer =new IKAnalyzer(); //new StandardAnalyzer(Version.LUCENE_36);  
  13.         IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_36,analyzer);  
  14.         writer = new IndexWriter(directory,config);  
  15.     }  
  16.   
  17.     @Test  
  18.     public void testSearToHighlighter()throws Exception {  
  19.         /**生成索引庫*/  
  20.         demo.buildDocs(writer);  
  21.           
  22.         /**查詢數據*/  
  23.         reader = IndexReader.open(directory);  
  24.         searcher =new IndexSearcher(reader);  
  25.         demo.searToHighlighter(analyzer,searcher);  
  26.     }  
  27.       
  28.     @Test  
  29.     public void testSearToHighlighterCss()throws Exception {  
  30.         /**生成索引庫*/  
  31.         demo.buildDocs(writer);  
  32.           
  33.         /**查詢數據*/  
  34.         reader = IndexReader.open(directory);  
  35.         searcher =new IndexSearcher(reader);  
  36.         demo.searToHighlighterCss(new IKAnalyzer(),searcher);  
  37.     }  
  38. }  
 
testSearToHighlighter測試結果:
Java代碼  收藏代碼
  1. buildDocs()->總人數爲 :100  
  2. buildDocs()->存入索引庫的數量:100  
  3. searcherDoc()->男生人數:66  
  4. 查詢出人員:序號:1,ID:1,姓名:張三1,性別:我是<B>男生</B>  
  5. 查詢出人員:序號:2,ID:2,姓名:張三2,性別:我是<B>男生</B>  
  6. 查詢出人員:序號:3,ID:4,姓名:張三4,性別:我是<B>男生</B>  
  7. 查詢出人員:序號:4,ID:5,姓名:張三5,性別:我是<B>男生</B>  
  8. 查詢出人員:序號:5,ID:7,姓名:張三7,性別:我是<B>男生</B>  
  9. 查詢出人員:序號:6,ID:8,姓名:張三8,性別:我是<B>男生</B>  
  10. 查詢出人員:序號:7,ID:10,姓名:張三10,性別:我是<B>男生</B>  
  11. 查詢出人員:序號:8,ID:11,姓名:張三11,性別:我是<B>男生</B>  
  12. 查詢出人員:序號:9,ID:13,姓名:張三13,性別:我是<B>男生</B>  
  13. 查詢出人員:序號:10,ID:14,姓名:張三14,性別:我是<B>男生</B>  
 testSearToHighlighterCss 測試結果

Java代碼  收藏代碼
  1. buildDocs()->總人數爲 :100  
  2. buildDocs()->存入索引庫的數量:100  
  3. searcherDoc()->男生人數:66  
  4. 查詢出人員:序號:1,ID:1,姓名:張三1,性別:我是<span class="hightlighterCss">男生</span>  
  5. 查詢出人員:序號:2,ID:2,姓名:張三2,性別:我是<span class="hightlighterCss">男生</span>  
  6. 查詢出人員:序號:3,ID:4,姓名:張三4,性別:我是<span class="hightlighterCss">男生</span>  
  7. 查詢出人員:序號:4,ID:5,姓名:張三5,性別:我是<span class="hightlighterCss">男生</span>  
  8. 查詢出人員:序號:5,ID:7,姓名:張三7,性別:我是<span class="hightlighterCss">男生</span>  
  9. 查詢出人員:序號:6,ID:8,姓名:張三8,性別:我是<span class="hightlighterCss">男生</span>  
  10. 查詢出人員:序號:7,ID:10,姓名:張三10,性別:我是<span class="hightlighterCss">男生</span>  
  11. 查詢出人員:序號:8,ID:11,姓名:張三11,性別:我是<span class="hightlighterCss">男生</span>  
  12. 查詢出人員:序號:9,ID:13,姓名:張三13,性別:我是<span class="hightlighterCss">男生</span>  
  13. 查詢出人員:序號:10,ID:14,姓名:張三14,性別:我是<span class="hightlighterCss">男生</span>  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章