1. 程式人生 > >solr教程,值得剛接觸搜尋開發人員一看

solr教程,值得剛接觸搜尋開發人員一看

Solr調研總結

開發型別

全文檢索相關開發

Solr版本

4.2

檔案內容

本文介紹solr的功能使用及相關注意事項;主要包括以下內容:環境搭建及除錯;兩個核心配置檔案介紹;維護索引;查詢索引,和在查詢中可以應用的高亮顯示、拼寫檢查、搜尋建議、分組統計、拼音檢索等功能的使用方法。

版本

作者/修改人

日期

V1.0

gzk

2013-06-04

1. Solr 是什麼?

Solr它是一種開放原始碼的、基於 Lucene Java 的搜尋伺服器,易於加入到 Web 應用程式中。Solr 提供了層面搜尋(就是統計)、命中醒目顯示並且支援多種輸出格式(包括XML/XSLT 和JSON等格式)。它易於安裝和配置,而且附帶了一個基於HTTP 的管理介面。可以使用 Solr 的表現優異的基本搜尋功能,也可以對它進行擴充套件從而滿足企業的需要。Solr的特性包括:

  • 高階的全文搜尋功能
  • 專為高通量的網路流量進行的優化
  • 基於開放介面(XML和HTTP)的標準
  • 綜合的HTML管理介面
  • 可伸縮性-能夠有效地複製到另外一個Solr搜尋伺服器
  • 使用XML配置達到靈活性和適配性
  • 可擴充套件的外掛體系

2. Lucene 是什麼?

Lucene是一個基於Java的全文資訊檢索工具包,它不是一個完整的搜尋應用程式,而是為你的應用程式提供索引和搜尋功能。Lucene 目前是 Apache Jakarta(雅加達) 家族中的一個開源專案。也是目前最為流行的基於Java開源全文檢索工具包。目前已經有很多應用程式的搜尋功能是基於 Lucene ,比如Eclipse 幫助系統的搜尋功能。Lucene能夠為文字型別的資料建立索引,所以你只要把你要索引的資料格式轉化的文字格式,Lucene 就能對你的文件進行索引和搜尋。

3. Solr vs Lucene

Solr與Lucene 並不是競爭對立關係,恰恰相反Solr 依存於Lucene,因為Solr底層的核心技術是使用Lucene 來實現的,Solr和Lucene的本質區別有以下三點:搜尋伺服器,企業級和管理。Lucene本質上是搜尋庫,不是獨立的應用程式,而Solr是。Lucene專注於搜尋底層的建設,而Solr專注於企業應用。Lucene不負責支撐搜尋服務所必須的管理,而Solr負責。所以說,一句話概括 Solr: Solr是Lucene面向企業搜尋應用的擴充套件。

Solr與Lucene架構圖:

Solr使用Lucene並且擴充套件了它!

  • 一個真正的擁有動態欄位(Dynamic Field)和唯一鍵(Unique Key)的資料模式(Data Schema)
  • 對Lucene查詢語言的強大擴充套件!
  • 支援對結果進行動態的分組和過濾
  • 高階的,可配置的文字分析
  • 高度可配置和可擴充套件的快取機制
  • 效能優化
  • 支援通過XML進行外部配置
  • 擁有一個管理介面
  • 可監控的日誌
  • 支援高速增量式更新(Fast incremental Updates)和快照發布(Snapshot Distribution)

4.搭建並除錯Solr

4.1 安裝虛擬機器

Solr 必須執行在Java1.6 或更高版本的Java 虛擬機器中,執行標準Solr 服務只需要安裝JRE 即可,但如果需要擴充套件功能或編譯原始碼則需要下載JDK 來完成。可以通過下面的地址下載所需JDK 或JRE :

安裝 步驟請參考相應的幫助文件。

4.2下載Solr

本文針對Solr4.2版本進行調研的,下文介紹內容均針對Solr4.2版本,如與Solr 最新版本有出入請以官方網站內容為準。Solr官方網站下載地址:http://lucene.apache.org/solr/

4.3下載並設定Apache Ant

Solr是使用Ant進行管理的原始碼, Ant是一種基於Java的build工具。理論上來說,它有些類似於Maven 或者是 C中的make。下載後解壓出來後,進行環境變數設定。

ANT_HOME:E:\Work\apache-ant\1.9.1 (這裡為你自己解壓縮的目錄) PATH:%ANT_HOME%\bin (這個設定是為了方便在dos環境下操作)

檢視是否安裝成功,在命令列視窗中輸入命令ant,若出現結果:



說明ant安裝成功!因為ant預設執行build.xml檔案,這個檔案需要我們建立。現在就可以進行build Solr原始碼了。在命令列視窗中進入到你的Solr原始碼目錄,輸入ant會出現當前build.xml使用提示資訊。

其它的先不用管它,我們只要針對我們使用的IDE進行build就行了,如果使用eclipse就在命令列輸入:ant eclipse.如果使用IntelliJ IDEA 就在命令列輸入:ant idea。這樣就能進行build了。

黑窗口裡提示這個。。。

失敗。。。為什麼呢,最後我發現是因為下載的ant中少了一個jar就是這apache-ivy(下載地址:http://ant.apache.org/ivy/)這東東名子真怪 ivy是ant管理jar依賴關係的。當第一次bulid時ivy會自動把build中的缺少的依賴進行下載。網速慢的第一次build要好久的。。。

下載一個jar就行把jar放到ant的lib下(E:\Work\apache-ant\1.9.1\lib)這樣再次執行ant 就會成功了。到現在才可以進行Solr的程式碼除錯。

4.4配置並執行Solr程式碼

不管用什麼IDE首選都要設定Solr Home在IDE的JVM引數設定VM arguments寫入 -Dsolr.solr.home=solr/example/solr一般就行了.不行也可以使用絕對路徑.

solr使用StartSolrJetty檔案作為入口檔案進行除錯程式碼,在這裡可以設定伺服器使用的埠和solr的webapps目錄.一般都不用設定,預設的就可以進行除錯.Solr Home也能可在程式碼中設定一樣好用.  System.setProperty("solr.solr.home", "E:\\Work\\solr-4.2.0-src-idea\\solr\\example\\solr");

目前是使用自帶的一個example作為solr配置的根目錄,如果你有其他的solr配置目錄,設定之即可。點選run即可,debug也是一樣可以用了。沒有別的問題就應該能運行了.注意servlet 容器使用的埠,如查提示:

FAILED [email protected]:8983: java.net.BindException: Address already in use: JVM_Bind 就說明當前端口占用中.改一下就可以了.如果沒有報錯啟動成功後就可以在瀏覽器中輸入地址: http://localhost:8983/solr/ 就可以看到如下介面

到這裡Solr就成功配置並運行了.要是想跟程式碼除錯在啟動時在這個方法裡點斷點就可以Initializer的initialize()方法如果想從瀏覽器中找斷點除錯就要到SolrDispatchFilter的doFilter方法中點斷點了.

注:IE9在相容模式下有bug,必須設定為非相容模式。

5.Solr基礎

因為 Solr 包裝並擴充套件了Lucene,所以它們使用很多相同的術語。更重要的是,Solr 建立的索引與 Lucene 搜尋引擎庫完全相容。通過對 Solr 進行適當的配置,某些情況下可能需要進行編碼,Solr 可以閱讀和使用構建到其他 Lucene 應用程式中的索引。在 Solr 和 Lucene 中,使用一個或多個 Document 來構建索引。Document 包括一個或多個 Field。Field 包括名稱、內容以及告訴 Solr 如何處理內容的元資料。

例如,Field 可以包含字串、數字、布林值或者日期,也可以包含你想新增的任何型別,只需用在solr的配置檔案中進行相應的配置即可。Field 可以使用大量的選項來描述,這些選項告訴 Solr 在索引和搜尋期間如何處理內容。

現在,檢視一下表 1 中列出的重要屬性的子集:

屬性名稱

描述

Indexed

Indexed Field 可以進行搜尋和排序。你還可以在 indexed Field 上執行 Solr 分析過程,此過程可修改內容以改進或更改結果。

Stored

stored Field 內容儲存在索引中。這對於檢索和醒目顯示內容很有用,但對於實際搜尋則不是必需的。例如,很多應用程式儲存指向內容位置的指標而不是儲存實際的檔案內容。

5.1模式配置Schema.xml

schema.xml這個配置檔案可以在你下載solr包的安裝解壓目錄的\solr\example\solr\collection1\conf中找到,它就是solr模式關聯的檔案。開啟這個配置檔案,你會發現有詳細的註釋。模式組織主要分為三個重要配置

5.1.1. types 部分

是一些常見的可重用定義,定義了 Solr(和 Lucene)如何處理 Field。也就是新增到索引中的xml檔案屬性中的型別,如int、text、date等.

<fieldType name="string" class="solr.StrField" sortMissingLast="true"/>

<fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/>

<fieldType name="int" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0"/>

<fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">

<analyzer type="index">

  <tokenizer class="solr.StandardTokenizerFactory"/>

  <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />

  <filter class="solr.LowerCaseFilterFactory"/>

</analyzer>

<analyzer type="query">

  <tokenizer class="solr.StandardTokenizerFactory"/>

  <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />

  <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>

  <filter class="solr.LowerCaseFilterFactory"/>

</analyzer>

</fieldType>

引數說明:

屬性

描述

name

標識而已

class

和其他屬性決定了這個fieldType的實際行為。

sortMissingLast

設定成true沒有該field的資料排在有該field的資料之後,而不管請求時的排序規則, 預設是設定成false。

sortMissingFirst

跟上面倒過來唄。 預設是設定成false

analyzer

欄位型別指定的分詞器

type

當前分詞用用於的操作.index代表生成索引時使用的分詞器query程式碼在查詢時使用的分詞器

tokenizer

分詞器類

filter

分詞後應用的過濾器  過濾器呼叫順序和配置相同.

5.1.2. fileds

是你新增到索引檔案中出現的屬性名稱,而宣告型別就需要用到上面的types

<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false"/>

<field name="path" type="text_smartcn" indexed="false" stored="true" multiValued="false" termVector="true" />

<field name="content" type="text_smartcn" indexed="false" stored="true" multiValued="false" termVector="true"/>

<field name ="text" type ="text_ik" indexed ="true" stored ="false" multiValued ="true"/>

<field name ="pinyin" type ="text_pinyin" indexed ="true" stored ="false" multiValued ="false"/>

<field name="_version_" type="long" indexed="true" stored="true"/>

<dynamicField name="*_i" type="int" indexed="true" stored="true"/>

<dynamicField name="*_l" type="long" indexed="true" stored="true"/>

<dynamicField name="*_s" type="string" indexed="true" stored="true" />

  • field: 固定的欄位設定
  • dynamicField: 動態的欄位設定,用於後期自定義欄位,*號萬用字元.例如: test_i就是int型別的動態欄位.

還有一個特殊的欄位copyField,一般用於檢索時用的欄位這樣就只對這一個欄位進行索引分詞就行了copyField的dest欄位如果有多個source一定要設定multiValued=true,否則會報錯的

<copyField source="content" dest="pinyin"/>

<copyField source="content" dest="text"/>

<copyField source="pinyin" dest="text"/>

欄位屬性說明:

屬性

描述

name

欄位型別名

class

java類名

indexed

預設true。 說明這個資料應被搜尋和排序,如果資料沒有indexed,則stored應是true。

stored

預設true。說明這個欄位被包含在搜尋結果中是合適的。如果資料沒有stored,則indexed應是true。

omitNorms

欄位的長度不影響得分和在索引時不做boost時,設定它為true。

一般文字欄位不設定為true。

termVectors

如果欄位被用來做more like this 和highlight的特性時應設定為true。

compressed

欄位是壓縮的。這可能導致索引和搜尋變慢,但會減少儲存空間,只有StrField和TextField是可以壓縮,這通常適合欄位的長度超過200個字元。

multiValued

欄位多於一個值的時候,可設定為true。

positionIncrementGap

和multiValued一起使用,設定多個值之間的虛擬空白的數量

注意:_version_ 是一個特殊欄位,不能刪除,是記錄當前索引版本號的.

5.1.3. 其他配置

uniqueKey: 唯一鍵,這裡配置的是上面出現的fileds,一般是id、url等不重複的。在更新、刪除的時候可以用到。

defaultSearchField:預設搜尋屬性,如q=solr就是預設的搜尋那個欄位

solrQueryParser:查詢轉換模式,是並且還是或者(AND/OR必須大寫)

5.2. solr配置solrconfig.xml

       solrconfig.xml這個配置檔案可以在你下載solr包的安裝解壓目錄的E:\Work\solr-4.2.0-src-idea\solr\example\solr\collection1\conf中找到,這個配置檔案內容有點多,主要內容有:使用的lib配置,包含依賴的jar和Solr的一些外掛;元件資訊配置;索引配置和查詢配置,下面詳細說一下索引配置和查詢配置.

5.2.1索引indexConfig

       Solr 效能因素,來了解與各種更改相關的效能權衡。 表 1 概括了可控制 Solr 索引處理的各種因素:

屬性

描述

useCompoundFile

通過將很多 Lucene 內部檔案整合到一個檔案來減少使用中的檔案的數量。這可有助於減少 Solr 使用的檔案控制代碼數目,代價是降低了效能。除非是應用程式用完了檔案控制代碼,否則 false 的預設值應該就已經足夠。

ramBufferSizeMB

在新增或刪除文件時,為了減少頻繁的更些索引,Solr會選快取在記憶體中,當記憶體中的檔案大於設定的值,才會更新到索引庫。較大的值可使索引時間變快但會犧牲較多的記憶體。如兩個值同時設定,滿足一個就會進行重新整理索引.

maxBufferedDocs

mergeFactor

決定低水平的 Lucene 段被合併的頻率。較小的值(最小為 2)使用的記憶體較少但導致的索引時間也更慢。較大的值可使索引時間變快但會犧牲較多的記憶體。

maxIndexingThreads

indexWriter生成索引時使用的最大執行緒數

unlockOnStartup

unlockOnStartup 告知 Solr 忽略在多執行緒環境中用來保護索引的鎖定機制。在某些情況下,索引可能會由於不正確的關機或其他錯誤而一直處於鎖定,這就妨礙了新增和更新。將其設定為 true 可以禁用啟動鎖定,進而允許進行新增和更新。

lockType

single: 在只讀索引或是沒有其它程序修改索引時使用.

native: 使用作業系統本地檔案鎖,不能使用多個Solr在同一個JVM中共享一個索引.

simple :使用一個文字檔案鎖定索引.

5.2.2 查詢配置query

屬性

描述

maxBooleanClauses

最大的BooleanQuery數量. 當值超出時,丟擲 TooManyClausesException.注意這個是全域性的,如果是多個SolrCore都會使用一個值,每個Core裡設定不一樣的化,會使用最後一個的.

filterCache

filterCache儲存了無序的lucene document id集合,1.儲存了filter queries(“fq”引數)得到的document id集合結果。2還可用於facet查詢3. 3)如果配置了useFilterForSortedQuery,那麼如果查詢有filter,則使用filterCache。

queryResultCache

快取搜尋結果,一個文件ID列表

documentCache

快取Lucene的Document物件,不會自熱

fieldValueCache

欄位快取使用文件ID進行快速訪問。預設情況下建立fieldValueCache即使這裡沒有配置。

enableLazyFieldLoading

若應用程式預期只會檢索 Document 上少數幾個 Field,那麼可以將屬性設定為 true。延遲載入的一個常見場景大都發生在應用程式返回和顯示一系列搜尋結果的時候,使用者常常會單擊其中的一個來檢視儲存在此索引中的原始文件。初始的顯示常常只需要顯示很短的一段資訊。若考慮到檢索大型 Document 的代價,除非必需,否則就應該避免載入整個文件。

queryResultWindowSize

一次查詢中儲存最多的doc的id數目.

queryResultMaxDocsCached

查詢結果doc的最大快取數量, 例如要求每頁顯示10條,這裡設定是20條,也就是說快取裡總會給你多出10條的資料.讓你點示下一頁時很快拿到資料.

listener

選項定義 newSearcher 和 firstSearcher 事件,您可以使用這些事件來指定例項化新搜尋程式或第一個搜尋程式時應該執行哪些查詢。如果應用程式期望請求某些特定的查詢,那麼在建立新搜尋程式或第一個搜尋程式時就應該反註釋這些部分並執行適當的查詢。

useColdSearcher

是否使用冷搜尋,為false時使用自熱後的searcher

maxWarmingSearchers

最大自熱searcher數量

5.3Solr加入中文分詞器

     中文分詞在solr裡面是沒有預設開啟的,需要我們自己配置一箇中文分詞器。目前可用的分詞器有smartcn,IK,Jeasy,庖丁。其實主要是兩種,一種是基於中科院ICTCLAS的隱式馬爾科夫HMM演算法的中文分詞器,如smartcn,ictclas4j,優點是分詞準確度高,缺點是不能使用使用者自定義詞庫;另一種是基於最大匹配的分詞器,如IK ,Jeasy,庖丁,優點是可以自定義詞庫,增加新詞,缺點是分出來的垃圾詞較多。各有優缺點看應用場合自己衡量選擇吧。

       下面給出兩種分詞器的安裝方法,任選其一即可,推薦第一種,因為smartcn就在solr發行包的contrib/analysis-extras/lucene-libs/下,就是lucene-analyzers-smartcn-4.2.0.jar,首選在solrconfig.xml中加一句引用analysis-extras的配置,這樣我們自己加入的分詞器才會引到的solr中.

<lib dir="../../../contrib/analysis-extras/lib" regex=".*\.jar" />

5.3.1. smartcn 分詞器的安裝

    首選將發行包的contrib/analysis-extras/lucene-libs/ lucene-analyzers-smartcn-4.2.0.jar複製到\solr\contrib\analysis-extras\lib下,在solr本地應用資料夾下,開啟/solr/conf/scheme.xml,編輯text欄位型別如下,新增以下程式碼到scheme.xml中的相應位置,就是找到fieldType定義的那一段,在下面多新增這一段就好啦

<fieldType name="text_smartcn" class="solr.TextField" positionIncrementGap="0">

      <analyzer type="index">

        <tokenizer class="org.apache.lucene.analysis.cn.smart.SmartChineseSentenceTokenizerFactory"/>

        <filter class="org.apache.lucene.analysis.cn.smart.SmartChineseWordTokenFilterFactory"/>

      </analyzer>

      <analyzer type="query">

         <tokenizer class="org.apache.lucene.analysis.cn.smart.SmartChineseSentenceTokenizerFactory"/>

        <filter class="org.apache.lucene.analysis.cn.smart.SmartChineseWordTokenFilterFactory"/>

      </analyzer>

</fieldType>

       如果需要檢索某個欄位,還需要在scheme.xml下面的field中,新增指定的欄位,用text_ smartcn作為type的名字,來完成中文分詞。如 text要實現中文檢索的話,就要做如下的配置:

<field name ="text" type ="text_smartcn" indexed ="true" stored ="false" multiValued ="true"/>

5.3.2. IK 分詞器的安裝

下載後解壓出來檔案中的三個複製到\solr\contrib\analysis-extras\lib目錄中.

IKAnalyzer2012FF_u1.jar       分詞器jar包

IKAnalyzer.cfg.xml                 分詞器配置檔案

Stopword.dic                           分詞器停詞字典,可自定義新增內容

複製後就可以像smartcn一樣的進行配置scheme.xml了.

<fieldType name="text_ik" class="solr.TextField">

         <analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>

</fieldType>

<field name ="text" type ="text_ik" indexed ="true" stored ="false" multiValued ="true"/>

       現在來驗證下是否新增成功,首先使用StartSolrJetty來啟動solr服務,啟動過程中如果配置出錯,一般有兩個原因:一是配置的分詞器jar找不到,也就是你沒有複製jar包到\solr\contrib\analysis-extras\lib目前下;二是分詞器版本不對導致的分詞器介面API不一樣出的錯,要是這個錯的話就在檢查分詞器的相關文件,看一下支援的版本是否一樣.

       如果在啟動過程中沒有報錯的話說明配置成功了.我們可以進入到http://localhost:8983/solr地址進行測試一下剛加入的中文分詞器.在首頁的Core Selector中選擇你配置的Croe後點擊下面的Analysis,在Analyse Fieldname / FieldType裡選擇你剛才設定的欄位名稱或是分詞器型別,在Field Value(index)中輸入:中國人,點選右面的分詞就行了.

6.Solr功能應用

       我這裡主要使用SolrJ進行介紹一下Solr的一些基本應用,使用SolrJ加上EmbeddedSolrServer(嵌入式伺服器),方便進行程式碼跟蹤除錯.在功能上和其它伺服器都是一樣的,它們都是繼承的SolrServer來提供服務API的. EmbeddedSolrServer優點是不用起http協議,直接載入SolrCore進行操作,效能上應該是最快的,方便用於把Solr單結點服務嵌入到專案中使用.下面開始介紹Solr的功能的應用.EmbeddedSolrServer初始化:

System.setProperty("solr.solr.home", "E:\\Work\\solr-4.2.0-src\\solr\\example\\solr");

CoreContainer.Initializer initializer = new CoreContainer.Initializer();

CoreContainer  coreContainer = initializer.initialize();

SolrServer  server = new EmbeddedSolrServer(coreContainer, "");

6.1維護索引

       在一般系統中維護的都是增刪改,在Solr中的維護功能是增刪和優化功能,在Solr中的修改操作就是先刪掉再新增.在做索引維護之前,首先要做的是配置schema.xml主要是按上面章節中的說明設定好欄位資訊(名稱,型別,索引,儲存,分詞等資訊),大概就像在資料庫中新建一個表一樣.設定好schema.xml就可以進行索引相關操作了.

6.1.1增加索引

       在增加索引之前先可構建好SolrInputDocument物件.主要操作就是給文件新增欄位和值.程式碼如下:

SolrInputDocument doc = new SolrInputDocument();

doc.setField("id", "ABC");

doc.setField("content", "中華人民共和國");

構建好文件後新增的上面初始化好的server裡就行了.

server.add(doc);

server.commit();//這句一般不用加因為我們可以通過在配置檔案中的

                             //autoCommit來提高效能

       Solr在add文件時.如果文件不存在就直接新增,如果文件存在就刪除後新增,這也就是修改功能了.判斷文件是否存在的依據是定義好的uniqueKey欄位.

6.1.2刪除索引

       刪除索引可以通過兩種方式操作,一種是通過文件ID進行刪除,別一種是通過查詢到的結果進行刪除.

通過ID刪除方式程式碼:

server.deleteById(id);

//或是使用批量刪除

server.deleteById(ids);

通過查詢刪除方式程式碼:

server.deleteByQuery("*.*");//這樣就刪除了所有文件索引

//”*.*”就查詢所有內容的,介紹查詢時會詳細說明.

6.1.2優化索引

       優化Lucene 的索引檔案以改進搜尋效能。索引完成後執行一下優化通常比較好。如果更新比較頻繁,則應該在使用率較低的時候安排優化。一個索引無需優化也可以正常地執行。優化是一個耗時較多的過程。

  server.optimize();//不要頻繁的呼叫..儘量在無人使用時呼叫.

6.2查詢索引

       Solr在不修改任務配置的情況下就可以使用查詢功能,在web專案中應用可以直接URL進行訪問Solr伺服器例如 :

       上面的意思就是查詢名為collection1的SolrCore的所有內容用xml格式返回並且有縮排。

返回結果如下:

<?xml version="1.0" encoding="UTF-8"?>

<response>

<lst name="responseHeader">

  <int name="status">0</int>

  <int name="QTime">0</int>

  <lst name="params">

    <str name="indent">true</str>

    <str name="q">*:*</str>

    <str name="wt">xml</str>

  </lst>

</lst>

<result name="response" numFound="17971" start="0">

  <doc>

    <str name="path">E:\Reduced\軍事\1539.txt</str>

    <str name="category_s">2</str>

    <int name="browseCount_i">-1423701734</int>

    <long name="modified_l">1162438568000</long>

    <long name="releasedate_l">1162438568000</long>

    <str name="content"> [俄羅斯lenta網站2006年2月9日報道]俄空軍副總司令比熱耶夫中將稱,2006年春天獨聯體國家防空系統打擊範圍向西推進150千米,偵察範圍向西推進400千米。  2006年3月白俄羅斯4個S-300PS防空導彈營擔負戰鬥任務,使獨聯體防空系統作戰範圍得以向西推進。比熱耶夫中將還宣佈,近期烏茲別克可能加入獨聯體防空系統。  獨聯體國家防空系統建於9年前,共有9個國家參加該組織。目前只有亞美尼亞、白俄羅斯、哈薩克、吉爾吉斯、俄羅斯和塔吉克支援該體系。  烏克蘭、烏茲別克與俄羅斯在雙邊基礎上合作,喬治亞和土庫曼最近7年不參加獨聯體國家對空防禦。</str>

    <str name="id">E3798D82-EAB6-2BEA-D7E2-79FBD102E845</str>

    <long name="_version_">1436361868021071872</long></doc>

  …

</result>

</response>

上面所看到的就是用xml格式返回的查詢結果,其中的doc就是一個文件,在doc裡面的那個就是我們開始在schema.xml中定義的欄位.

如果使用SolrJ進行呼叫的話程式碼如下:

SolrQuery query = new SolrQuery();

query.set("q","*.*");

QueryResponse rsp =server.query(query)

SolrDocumentList list = rsp.getResults();

返回結果在SolrDocumentList中在這個物件中遍歷取出值來:

for (int i = 0; i < list.size(); i++) {

   SolrDocument sd = list.get(i);

   String id = (String) sd.getFieldValue("id");

   System.out.println(id);

}

6.2.1查詢引數

名稱

描述

q

查詢字串,必須的。

fq

filter query。使用Filter Query可以充分利用Filter Query Cache,提高檢索效能。作用:在q查詢符合結果中同時是fq查詢符合的,例如:q=mm&fq=date_time:[20081001 TO 20091031],找關鍵字mm,並且date_time是20081001到20091031之間的。

fl

field list。指定返回結果欄位。以空格“ ”或逗號“,”分隔。

start

用於分頁定義結果起始記錄數,預設為0。

rows

用於分頁定義結果每頁返回記錄數,預設為10。

sort

排序,格式:sort=<field name>+<desc|asc>[,<field name>+<desc|asc>]… 。示例:(inStock desc, price asc)表示先 “inStock” 降序, 再 “price” 升序,預設是相關性降序。

df

預設的查詢欄位,一般預設指定。

q.op

覆蓋schema.xml的defaultOperator(有空格時用"AND"還是用"OR"操作邏輯),一般預設指定。必須大寫

wt

writer type。指定查詢輸出結構格式,預設為“xml”。在solrconfig.xml中定義了查詢輸出格式:xml、json、python、ruby、php、phps、custom。

qt

query type,指定查詢使用的Query Handler,預設為“standard”。

explainOther

設定當debugQuery=true時,顯示其他的查詢說明。

defType

設定查詢解析器名稱。

timeAllowed

設定查詢超時時間。

omitHeader

設定是否忽略查詢結果返回頭資訊,預設為“false”。

indent

返回的結果是否縮排,預設關閉,用 indent=true|on 開啟,一般除錯json,php,phps,ruby輸出才有必要用這個引數。

version

查詢語法的版本,建議不使用它,由伺服器指定預設值。

debugQuery

設定返回結果是否顯示Debug資訊。

6.2.2查詢語法

1.匹配所有文件:*:*

2.強制、阻止和可選查詢:

1)    Mandatory:查詢結果中必須包括的(for example, only entry name containing the word make)

Solr/Lucene Statement:+make, +make +up ,+make +up +kiss

2)    prohibited:(for example, all documents except those with word believe)

Solr/Lucene Statement:+make +up -kiss

3)    optional:

Solr/Lucene Statement:+make +up kiss

3.布林操作:AND、OR和NOT布林操作(必須大寫)與Mandatory、optional和prohibited相似。

1)       make AND up = +make +up :AND左右兩邊的操作都是mandatory

2)       make || up = make OR up=make up :OR左右兩邊的操作都是optional

3)       +make +up NOT kiss = +make +up –kiss

4)       make AND up OR french AND Kiss不可以達到期望的結果,因為AND兩邊的操作都是mandatory的。

4. 子表示式查詢(子查詢):可以使用“()”構造子查詢。

示例:(make AND up) OR (french AND Kiss)

5.子表示式查詢中阻止查詢的限制:

示例:make (-up):只能取得make的查詢結果;要使用make (-up *:*)查詢make或者不包括up的結果。

6.多欄位fields查詢:通過欄位名加上分號的方式(fieldName:query)來進行查詢

示例:entryNm:make AND entryId:3cdc86e8e0fb4da8ab17caed42f6760c

7.萬用字元查詢(wildCard Query):

1)       萬用字元?和*:“*”表示匹配任意字元;“?”表示匹配出現的位置。

示例:ma?*(ma後面的一個位置匹配),ma??*(ma後面兩個位置都匹配)

2)       查詢字元必須要小寫:+Ma +be**可以搜尋到結果;+Ma +Be**沒有搜尋結果.

3)       查詢速度較慢,尤其是萬用字元在首位:主要原因一是需要迭代查詢欄位中的每個term,判斷是否匹配;二是匹配上的term被加到內部的查詢,當terms數量達到1024的時候,查詢會失敗。

4)       Solr中預設萬用字元不能出現在首位(可以修改QueryParser,設定

setAllowLeadingWildcard為true)

5)       set setAllowLeadingWildcard to true.

8.模糊查詢、相似查詢:不是精確的查詢,通過對查詢的欄位進行重新插入、刪除和轉換來取得得分較高的查詢解決(由Levenstein Distance Algorithm演算法支援)。

1)       一般模糊查詢:示例:make-believ~

2)       門檻模糊查詢:對模糊查詢可以設定查詢門檻,門檻是0~1之間的數值,門檻越高表面相似度越高。示例:make-believ~0.5、make-believ~0.8、make-believ~0.9

9.範圍查詢(Range Query):Lucene支援對數字、日期甚至文字的範圍查詢。結束的範圍可以使用“*”萬用字元。

示例:

1)       日期範圍(ISO-8601 時間GMT):sa_type:2 AND a_begin_date:[1990-01-01T00:00:00.000Z TO 1999-12-31T24:59:99.999Z]

2)       數字:salary:[2000 TO *]

3)       文字:entryNm:[a TO a]

10.日期匹配:YEAR, MONTH, DAY, DATE (synonymous with DAY) HOUR, MINUTE, SECOND, MILLISECOND, and MILLI (synonymous with MILLISECOND)可以被標誌成日期。

示例:

1)  r_event_date:[* TO NOW-2YEAR]:2年前的現在這個時間

2)  r_event_date:[* TO NOW/DAY-2YEAR]:2年前前一天的這個時間

6.2.3函式查詢(Function Query)

       函式查詢 可以利用 numeric欄位的值 或者 與欄位相關的的某個特定的值的函式,來對文件進行評分。

1.    使用函式查詢的方法

這裡主要有三種方法可以使用函式查詢,這三種s方法都是通過solr http介面的。

1)    使用FunctionQParserPlugin。ie: q={!func}log(foo)

2)    使用“_val_”內嵌方法

內嵌在正常的solr查詢表示式中。即,將函式查詢寫在 q這個引數中,這時候,我們使用“_val_”將函式與其他的查詢加以區別。

ie:entryNm:make && _val_:ord(entryNm)

3)    使用dismax中的bf引數

使用明確為函式查詢的引數,比如說dismax中的bf(boost function)這個引數。  注意:bf這個引數是可以接受多個函式查詢的,它們之間用空格隔開,它們還可以帶上權重。所以,當我們使用bf這個引數的時候,我們必須保證單個函式中是沒有空格出現的,不然程式有可能會以為是兩個函式。

示例:

q=dismax&bf="ord(popularity)^0.5 recip(rord(price),1,1000,1000)^0.3

2.    函式的格式(Function Query Syntax)

目前,function query 並不支援 a+b 這樣的形式,我們得把它寫成一個方法形式,這就是 sum(a,b).

3.    使用函式查詢注意事項

1)    用於函式查詢的field必須是被索引的;

2)    欄位不可以是多值的(multi-value)

4.    可以利用的函式 (available function)

1)    constant:支援有小數點的常量; 例如:1.5 ;SolrQuerySyntax:_val_:1.5

2)    fieldvalue:這個函式將會返回numeric field的值,這個欄位必須是indexd的,非multiValued的。格式很簡單,就是該欄位的名字。如果這個欄位中沒有這樣的值,那麼將會返回0。

3)    ord:對於一個欄位,它所有的值都將會按照字典順序排列,這個函式返回你要查詢的那個特定的值在這個順序中的排名。這個欄位,必須是非multiValued的,當沒有值存在的時候,將返回0。例如:某個特定的欄位只能去三個值,“apple”、“banana”、“pear”,那麼ord(“apple”)=1,ord(“banana”)=2,ord(“pear”)=3.需要注意的是,ord()這個函式,依賴於值在索引中的位置,所以當有文件被刪除、或者新增的時候,ord()的值就會發生變化。當你使用MultiSearcher的時候,這個值也就是不定的了。

4)    rord:這個函式將會返回與ord相對應的倒排序的排名。

格式: rord(myIndexedField)。

5)    sum:這個函式的意思就顯而易見啦,它就是表示“和”啦。

格式:sum(x,1) 、sum(x,y)、 sum(sqrt(x),log(y),z,0.5)

6)    product:product(x,y,...)將會返回多個函式的乘積。格式:product(x,2)、product(x,y)

7)    div:div(x,y)表示x除以y的值,格式:div(1,x)、div(sum(x,100),max(y,1))

8)    pow:pow表示冪值。pow(x,y) =x^y。例如:pow(x,0.5) 表示開方pow(x,log(y))

9)    abs:abs(x)將返回表示式的絕對值。格式:abs(-5)、 abs(x)

10)  log:log(x)將會返回基數為10,x的對數。格式: log(x)、 log(sum(x,100))

11)  Sqrt:sqrt(x) 返回 一個數的平方根。格式:sqrt(2)、sqrt(sum(x,100))

12)  Map:如果 x>=min,且x<=max,那麼map(x,min,max,target)=target.如果 x不在[min,max]這個區間內,那麼map(x,min,max,target)=x.

格式:map(x,0,0,1)

13)  Scale:scale(x,minTarget,maxTarget) 這個函式將會把x的值限制在[minTarget,maxTarget]範圍內。

14)  query :query(subquery,default)將會返回給定subquery的分數,如果subquery與文件不匹配,那麼將會返回預設值。任何的查詢型別都是受支援的。可以通過引用的方式,也可以直接指定查詢串。

例子:q=product(popularity, query({!dismax v='solr rocks'}) 將會返回popularity和通過dismax 查詢得到的分數的乘積。

q=product(popularity, query($qq)&qq={!dismax}solr rocks 跟上一個例子的效果是一樣的。不過這裡使用的是引用的方式

q=product(popularity, query($qq,0.1)&qq={!dismax}solr rocks 在前一個例子的基礎上又加了一個預設值。

15)  linear: inear(x,m,c)表示 m*x+c ,其中m和c都是常量,x是一個變數也可以是一個函式。例如: linear(x,2,4)=2*x+4.

16)  Recip:recip(x,m,a,b)=a/(m*x+b)其中,m、a、b是常量,x是變數或者一個函式。當a=b,並且x>=0的時候,這個函式的最大值是1,值的大小隨著x的增大而減小。例如:recip(rord(creationDate),1,1000,1000)

17)  Max: max(x,c)將會返回一個函式和一個常量之間的最大值。

例如:max(myfield,0)

6.3高亮顯示

      我們經常使用搜索引擎,比如在baidu 搜尋 java ,會出現如下結果,結果中與關鍵字匹配的地方是紅色顯示與其他內容區別開來。

solr 預設已經配置了highlight 元件(詳見 SOLR_HOME/conf/sorlconfig.xml)。通常我出只需要這樣請求http://localhost:8983/solr/ collection1 /select? q=%E4%B8%AD%E5%9B%BD&start=0&rows=1&fl=content+path+&wt=xml&indent=true&hl=true&hl.fl=content

       可以看到與比一般的請求多了兩個引數 "hl=true" 和 "hl.fl= content " 。

"hl=true" 是開啟高亮,"hl.fl= content " 是告訴solr 對 name 欄位進行高亮(如果你想對多個欄位進行高亮,可以繼續新增欄位,欄位間用逗號隔開,如 "hl.fl=name,name2,name3")。 高亮內容與關鍵匹配的地方,預設將會被 "<em>" 和 "</em>" 包圍。還可以使用hl.simple.pre" 和 "hl.simple.post"引數設定前後標籤.

查詢結果如下:

<?xml version="1.0" encoding="UTF-8"?>
<response>
<lst name="responseHeader">
<int name="status">0</int>
<int name="QTime">2</int>
<lst name="params">
<str name="fl">content path</str>
<str name="indent">true</str>
<str name="start">0</str>
<str name="q">中國</str>
<str name="hl.simple.pre"><em></str>
<str name="hl.simple.post"></em></str>
<str name="hl.fl">content</str>
<str name="wt">xml</str>
<str name="hl">true</str>
<str name="rows">1</str>
</lst>
</lst>
<result name="response" numFound="6799" start="0">
<doc>
<str name="path">E:\Reduced\IT\630.txt</str>
<str name="content">  本報訊 中國銀聯股份有限公司和中國電信集團日前在北京簽署全面戰略合作協議。這標誌著中國銀聯和中國電信將在通訊服務、資訊增值服務、新型支付產品合作開發等領域建立全面合作伙伴關係。  據悉,雙方簽署的全面戰略合作協議主要內容是:中國銀聯將選擇中國電信作為通訊資訊服務的主要提供商,雙方圍繞提高中國銀聯內部通訊的水平和銷售網路的服務水平開展全面、深入的合作;中國電信選擇中國銀聯作為銀行卡轉接支付服務的主要提供商,並圍繞開發、推廣新型支付終端產品和增值服務開展全面合作。(辛華)</str></doc>
</result>
<lst name="highlighting">
<lst name="7D919C61-03B3-4B6F-2D10-9E3CC92D2852">
<arr name="content">
<str>  本報訊 <em>中國</em>銀聯股份有限公司和<em>中國</em>電信集團日前在北京簽署全面戰略合作協議。這標誌著<em>中國</em>銀聯和<em>中國</em>電信將在通訊服務、資訊增值服務、新型支付產品合作開發等領域建立全面合作伙伴關係。  據悉,雙方簽署</str>
</arr>
</lst>
</lst>
</response>

使用SolrJ方法基本一樣也是設定這些個引數,只不過是SolrJ封裝起來了,程式碼如下:

SolrQuery query = new SolrQuery();

query.set("q","*.*");

query.setHighlight(true); // 開啟高亮元件

query.addHighlightField("content");// 高亮欄位

query.setHighlightSimplePre(PRE_TAG);// 標記

query.setHighlightSimplePost(POST_TAG);

QueryResponse rsp =server.query(query)

//…上面取結果的程式碼

//取出高亮結果

if (rsp.getHighlighting() != null) {

  if (rsp.getHighlighting().get(id) != null) {//先通過結果中的ID到高亮集合中取出文件高亮資訊

    Map<String, List<String>> map = rsp.getHighlighting().get(id);//取出高亮片段

    if (map.get(name) != null) {

      for (String s : map.get(name)) {

        System.out.println(s);

      }

    }

}

6.4拼寫檢查

       首先配置 solrconfig.xml,檔案可能已經有這兩個元素(如果沒有新增即可),需要根據我們自己的系統環境做些適當的修改。

<searchComponent name="spellcheck" class="solr.SpellCheckComponent">
     <str name="queryAnalyzerFieldType">text_spell</str> 
     <lst name="spellchecker"> 
       <str name="name">direct</str> 
       <str name="field">spell</str> 
       <str name="classname">solr.DirectSolrSpellChecker</str> 
       <str name="distanceMeasure">internal</str> 
       <float name="accuracy">0.5</float> 
       <int name="maxEdits">2</int> 
       <int name="minPrefix">1</int> 
       <int name="maxInspections">5</int> 
       <int name="minQueryLength">2</int> 
       <float name="maxQueryFrequency">0.01</float> 
</lst> 
  </searchComponent> 
  <requestHandler name="/spell" class="solr.SearchHandler" startup="lazy"&