Lucene sort 排序

排序是對於全文檢索來言是一個必不可少的功能,在實際運用中,排序功能能在某些時候給我們帶來很大的方便,比如在淘寶,京東等一些電商網站我們可能通過排序來快速找到價格最便宜的商品,或者通過排序來找到評論數最高或賣的最好的商品,再比如在Iteye裏的博客欄裏,每天都會以降序的方式,來顯示出最新發出的幾篇博客,有了排序,我們就能在某些時候很方便快速的得到某些有效信息,所以說排序功能,無處不在 ^_^。 




那麼,本篇散仙就來看下我們在Lucene中怎麼使用其豐富的排序功能。 


在這之前,我們先來熟悉下lucene中排序的基本知識,在默認情況下,Lucene使用的是以關聯性降序的方式爲默認的排序方式,這樣可以使得我們搜索的結果通常是最優的,因爲它會儘可能的使得首先出現的幾個結果是與我們搜索的內容最相關,而不需要我們翻頁尋找我們最想要的內容,這一點是與數據庫相比,是全文檢索一個很大的優點。當然,在實際開發中我們也需要根據業務的實際情況來給我們的客戶提供多種不同的排序方式。我們先來看下在Lucene中比較特殊的兩種基本的排序方式 




Sort裏的屬性 SortField裏的屬性 含義
Sort.INDEXORDER SortField.FIELD_DOC 按照索引的順序進行排序
Sort.RELEVANCE SortField.FIELD_SCORE 按照關聯性評分進行排序




我們再來看幾個檢索時需要用的方法 
Java代碼  收藏代碼
 =========SortField類============  
//field是排序字段type是排序類型  
public SortField(String field, Type type);  
//field是排序字段type是排序類型reverse是指定升序還是降序  
//reverse 爲true是降序  false爲升序  
  public SortField(String field, Type type, boolean reverse)  
  
  =========Sort類============  
  public Sort();//Sort對象構造方法默認是按文檔評分排序  
  public Sort(SortField field);//排序的一個SortField  
  public Sort(SortField... fields)//排序的多個SortField可以傳入一個數組  
   
  =========IndexSearche類r========  
//query是查詢的Query對象 filter是過濾  n返回的數量  sort是排序  
search(Query query, Filter filter, int n, Sort sort)   
//doDocScores 爲true情況下每個命中的結果下都會被評分  
//doMaxScore  爲true情況下對最大分值的搜索結果進行評分  
search(Query query, Filter filter, int n, Sort sort, boolean doDocScores, boolean doMaxScore)   
   


1,在還沒有進行一點排序前我們先來看下索引裏的內容,核心代碼如下: 
Java代碼  收藏代碼
TopDocs topDocs=searcher.search(new MatchAllDocsQuery(),10000);       




2,使用默認的關聯性評分後,核心代碼和運行效果圖如下: 
Java代碼  收藏代碼
Sort sort=new Sort();//默認使用關聯性評分  
    TopDocs topDocs=searcher.search(new MatchAllDocsQuery(),10000,sort);  








關於上圖中亂碼字符原因是因爲默認排序情況下lucene是不會對搜索結果進行評分操作的,因爲評分操作會降低性能,所以關於score的那一列返回的是NAN的字符串,出於格式的需要,散仙在用DecimalFormat類給其評分結果保留2位小數時,因爲是一個特殊字符,所以就出現了上圖情況。 


3,按照日期降序排序,,核心代碼和運行效果圖如下: 
Java代碼  收藏代碼
Sort sort=new Sort(new SortField("date", Type.INT,true));//true爲降序排列  
         TopDocs topDocs=searcher.search(new MatchAllDocsQuery(),10000,sort);  






3,按照價格升序排序,,核心代碼和運行效果圖如下: 
Java代碼  收藏代碼
Sort sort=new Sort(new SortField("price", Type.DOUBLE,false));//false爲降序排列  
         TopDocs topDocs=searcher.search(new MatchAllDocsQuery(),10000,sort);  






4,多字段排序,按照日期降序的情況下,因爲id爲7和8的日期相同,所以我們就新增一個排序字段按ename升序排列,,核心代碼和運行效果圖如下: 
Java代碼  收藏代碼
// Sort sort=new Sort(new SortField("date", Type.INT, true),new SortField("ename", Type.STRING, false));  
        //這兩段代碼效果一樣  
        Sort sort=new Sort(new SortField[]{new SortField("date", Type.INT, true),new SortField("ename", Type.STRING, false)});  
         TopDocs topDocs=searcher.search(new MatchAllDocsQuery(),10000,sort);  






5,帶評分的排序,注意後面兩個布爾類型的變量可以控制是否評分,特別是在沒有要求需要打分時,建議別開啓,大數量時對性能影響較大,檢索“編程”得到的結果,默認按評分降序排序,核心代碼和運行效果圖如下: 
Java代碼  收藏代碼
Sort sort=Sort.RELEVANCE;  
  TopDocs topDocs=searcher.search(new TermQuery(new Term("bookname", "編程")),null,100,sort,true,true);  






上面的編程,編程因爲在切分時編程的tf出現了2次,所以在查詢時有較高的得分,所以排在首位。 


6,注意幾點 
(1)排序對一個文檔裏什麼域都沒存儲,使用字符串排序會排在首位 
(2)排序對一個文檔裏什麼域都沒存儲,使用數字類型排序會默認給其賦值爲0進行排序 
(3)我們可以對數字類型的null值的文檔進行代碼控制,可以將其設置爲最大,所以將會排在最後面,代碼如下 


Java代碼  收藏代碼
SortField sortField = new SortField("value", SortField.Type.INT);  
   sortField.setMissingValue(Integer.MAX_VALUE);  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章