Solr高亮與Field權重

Solr高亮

原理 算法

作搜索時,高亮是很常見的需求,那麼Solr確定也爲高亮提供了支持。先解釋下Solr高亮的原理,在咱們設置了須要高亮顯示的Field以後,查詢獲得的返回結果會多出來下面的內容: 數據庫

複製代碼

周杰倫

複製代碼

 

其實就是多了highlighting的字段,並無改變原來返回的字段內容。 apache

Json串是使用 Unique Field :{高亮顯示的內容}的形式。 函數

SolrJ有三種高亮類型: url

若是要對某field作高亮顯示,必須對該field設置stored=true spa

Standard Highlighter,根據查詢的docIdSet,獲取Documents,並獲取當前document的須要高亮的field的value,根據query的term和該field的value作匹配算法
FastVector Highlighter,效率比普通的高亮顯示要高;須要定義termvector(佔用空間和IO),包括position和offset,根據query term的termvector到field value中作快速的定位標記,進而實現快速的高亮顯示
Postings Highlighter,因爲高亮顯示須要對field設置爲store=true,全部對於單節點數據量比較大而且該字段比較大的話,會消耗大量的IO操做,那麼能夠把該字段存儲在另外的地方,好比Hbase,在外部作高亮顯示的匹配。
code

其中推薦使用的是Standard Highlighter,下面也是針對Standard Highlighter,  xml

配置 排序

下面介紹兩種配置方式:ip

  1.SolrJ配置:

 

複製代碼

songQuery.setHighlight(); songQuery.set("hl.highlightMultiTerm","true");songQuery.setHighlightSimplePre("<font style=\"color:#A7D043;font-weight:bold;\">"); songQuery.setHighlightSimplePost("</font>");

複製代碼

 

  2.solrConfig.xml配置: 

複製代碼

  
    explicit
      10
      text
   true
   content
   50
   font color=red
   /font

複製代碼

 

詳細的RequestHandler配置請參看博客:五、SolrJ、Request Handler

其實這兩種配置並無本質上的區別。我我的習慣使用SolrJ配置。

 

解析

獲取highlighting是很是簡單的,一條語句搞定:

 

Map<String,Map<String,List<String>>> tempMap = response.getHighlighting();

 

相信你們也注意到了,雖然接受結果簡單,可是若是想遍歷就比較複雜了,由於接受到的結果是嵌套了不少層的類型Map<String,Map<String,List<String>>>

那麼我這邊把我解析的方法分享下:

 

複製代碼

Map<String,Map<String,List<String>>> tempMap =(Map.Entry<String, Map<String,List<String>>>(Integer.parseInt(entry.getKey()) ==(Map.Entry<String, List<String>>( != entryLayer2.getKey() && "Song_Name"( != entryLayer2.getKey() && "Song_SingerName"

複製代碼

 

這個方法比Iterator和foreach效率稍高。

我設置了兩個字段須要高亮,因此在循環中判斷了高亮是屬於哪一個字段,以後進行相應的操做。

由於我作的時候,一首歌可能有幾個Song_SingerName,在數據庫中用"/"分隔,因此這種狀況更加複雜,我首先是把後綴中的/換成了出現機率很小的@

songQuery.setHighlightSimplePost("<@font>");

而後再用split("@")分隔出不一樣的Song_SingerName,可是這樣就會有一個問題,就是我不知道高亮的歌手究竟是哪個歌手,因此這個時候,我還須要從分割後的String[]中提取全部的中文字符,比對後,存入另外一個變量,最後再用"/"替換掉"@"。

 

Solr權重

概念

Solr底層依然用的是Lucene的權重算法,也就是經過一個公式計算每一個Documents的得分,而後按得分高低排序,公式以下:

簡單解釋下這個公式中包含的一些因子:

Tf:Term frequency,就是條目出現的次數。

Idf: Inverse document frequency,就是用來描述在一個搜索關鍵字中,不一樣字詞的稀有程度。好比搜索The Cat in the Hat,那麼很明顯The和in遠沒有Cat和Hat重要。

Boosting:這個使咱們設置權重的重點,好比搜索歌手名,那麼在一個document中還有歌手的ID、歌曲的清晰度、歌曲上傳時間,而boosting是不一樣的Filed有不一樣權重,以後根據公式計算得分。因此能夠看到,咱們並不能直接影響solr搜索結果的排序,須要改變權重,進而改變不一樣Document的得分,從而影響排序

其中還有不少因子和公式的解釋,有興趣的同窗能夠參考Solr in action這本書,裏面有比較詳細的解釋。

由於咱們只需簡單的根據某一Filed的權重影響結果的排序,因此咱們須要改變Document的Boosting,那麼就須要用到Dismax,Dismax是一個查詢解析器(Query parser),查詢解析器的概念就是提供了一系列查詢的參數,一旦咱們在查詢url中設置了相應的參數,那麼查詢解析器將會解析查詢信息,從而獲得搜索結果,其實徹底也能夠把查詢解析器理解爲一個Api,就是提供了相應的方法,咱們設置,以後Solr根據咱們設置的參數進行查詢,只不過不一樣的Query Parser提供了不一樣的參數而已

一共提供了三種Query Parser

Standard:最經常使用的,而且是默認

Dismax:

Extended Dismax

功能從上至下是逐漸遞增的,在大部分狀況下,Standard已經能夠徹底知足需求,可是由於要使用權重排序,那麼須要用到Dismax,具體提供的參數請查看wiki:

https://cwiki.apache.org/confluence/display/solr/The+Standard+Query+Parser

 

那麼首先須要設置Query Parser爲Dismax:

 

songQuery.set("defType","dismax");

 

以後設置須要查詢的Field:

 

songQuery.set("qf","Song_Name^2 Song_SingerName^0.2");

 

好比我這裏就須要根據用戶輸入的關鍵字查詢歌手名和歌曲名,以後返回這兩個Field命中的結果、多個Query Filed中能夠設置不一樣的權重,好比Song_Name的權重就爲2,必須注意,在Solr權重的設置中,全部權重標準爲1,意思是當權重設置大於1時,表明這個字段的權重變大,若是權重設置小於1而且大於0的時候,表明這個字段權重變小

以後設置其它Field的權重:

 

songQuery.set("bf", "sum(div(Song_Quality,0.01),if(exists(Song_FileMV),20000,0),recip(ms(NOW,Song_CreateTimeForNew),1,10000,1))");

 

這裏面用到了不少Function Query,好比div,表明相除、exists表明若是Song_FileMV若是不爲空那麼設置它的權重爲20000,爲空則爲0。記住最後要sum起來,由於從上面的公式能夠看出來,boosting是一個變量,因此最好要有一個和值。相關的函數請參考wiki:

http://wiki.apache.org/solr/FunctionQuery

相關文章
相關標籤/搜索