[開篇語]按照慣例應該寫一篇技術文章了,此次結合Lucene/Solr來分享一下開發經驗。 java
Lucene是一個使用Java語言寫的全文檢索開發包(API),利用它能夠實現強大的檢索功能,它的詳細介紹你們能夠去Google上搜索一下,本文重點放在Solr相關的討論上。 linux
[概述]目前國內研究Solr的人很少,並且大可能是由於項目開發須要。Solr師承Lucene,爲Apache基金會下的一個項目,具體的說它仍是Lucene下的一個子項目。Solr出身豪門,並且具備本身的技術特色,填補了以往Lucene僅僅做爲開發工具包的遺憾,它是一個完完整整地應用。換句話說,它是一個全文檢索服務器,它開箱即用,讓咱們能立馬體會到Lucene的強大功能,爲Lucene產品化走出了一大步。
Solr分詞原理演示界面 web
[淵源]最初,CNET Networks使用Lucene
API來開發了一些應用,並在這個基礎上產生了Solr的雛形,後來Apache Software
Foundation在Lucene頂級項目的支持下獲得了Solr,這已是2006年1月份的事了。2006年1月17日,Solr正是加入Apache基金會的孵化項目,在整個項目孵化期間,Solr
穩步地積累各類特性並吸引了一個穩定的user羣體、developer羣體和Committer羣體,並於1年以後的17日正式醞釀成熟,在這以前已經成功發佈了1.1.0版。目前的穩定版本是1.2,Solr在9月份的2007Apache年會上大放異彩,在今年11月底未來到香港參加2007亞洲開源軟件峯會,遺憾的是爲何不來北京:-( 數據庫
[初識Solr]Solr服務器不一樣於普通的關係型數據庫,不只僅在於它核心本質的不一樣(面向結構化和非結構化數據的不一樣),很大的不一樣還在於它的體系架構上。Solr服務器通常狀況下須要部署於應用服務器/Java容器上(若是是本機通訊不涉及RPC能夠不使用Java容器,如採用嵌入方式使用Solr),沒法獨立工做於JVM上。
Solr架構圖
Solr服務器能夠存儲數據並經過索引對其進行快速高效檢索。對外提供HTTP/XML和Json
API接口,這使得它可以在多語言環境下集成,好比針對它的客戶端的開發。Solr目前的客戶端面向的有Java、PHP、Python、C#、Json和Ruby等,遺憾的是沒有面向C/C++(這也是本人目前在研究的),研究音樂搜索分類的Brian
Whitman曾在蘋果平臺上使用JNI技術在C代碼中嵌入Solr實現檢索,不過是一個Cocoa工程。有了這些客戶端,使用者能很方便地將Solr集成到具體運用中。目前最完善的當屬Java客戶端Solrj,以及加入到Solr
trunk,並將在1.3版本中正式發佈。 apache
若是不研究開發Solr,只是使用Solr,只須要關注Solr的如下幾個方面:
一、Solr服務器的配置在solrconfig.xml中完成,包括對緩存,servlet的個性化配置等等,即系統全局的配置;
二、索引方法、索引域(字段)等等在schema.xml中完成,這個配置是針對Solr實例的;
三、索引數據文件默認放在Solr文檔根目錄下的data/index目錄下,這個路徑能夠經過第1點配置,同時能夠將這個目錄下的文件進行復制粘貼,便可完成索引的複用;
四、創建索引的時間至關長,我採用按詞無字典索引方式對2G110萬條中文記錄進行索引,花了將近2個半小時的時間(固然這個時間和不少因素有關,有興趣的話你們能夠留言和我討論),相對而言,在linux下建索引時間要比windows下快不少,可使用commit操做使新增索引生效,同時注意索引的優化,索引優化也是很費資源和時間的,可是優化索引也是提升檢索速度的重要方法,所以須要好好權衡這一點;
五、安裝完後的Solr目錄下有這麼幾個文件夾:bin文件夾裏主要是用於創建鏡像和完成遠程同步的腳本;conf文件夾下主要是一、2點中提到的配置文件;admin文件夾下是的主要是提供web管理界面的文件;
六、目前Solr1.2不具有安全性設計,沒有用戶組及權限設置,在進行具體應用時須要注意安全,目前最有效的方法是經過應用服務器上的受權實現。
本文永久連接:http://www.jinsehupan.com/blog/?p=25 windows
[Solr的安裝]Solr發行版中已經有一個使用Jetty爲servlet容器的小例子,可使用這個例子來體驗,那正在在本身想部署的平臺和應用服務器上該怎麼一個步驟呢? 瀏覽器
要開始使用 Solr,需安裝如下軟件:
一、Java 1.5
或更高版本;
二、Ant 1.6.x 或更高版本(用於編譯管理Solr工程,我的推薦,固然可使用eclipse);
三、Web
瀏覽器,用來查看管理頁面(官方建議使用Firefox,但實際沒有發現和IE有什麼差異);
四、servlet 容器,如Tomcat
5.5(不建議使用6版本)。本文以Tomcat 在 8080 端口上運行爲例。若是運行的是其餘 servlet
容器或在其餘的端口上運行,則可能要修改代碼中的URL才能訪問示例應用程序和 Solr。 緩存
下面開始安裝配置: tomcat
1、使用Ant編譯工程或下載示例應用程序,將Solr WAR 文件複製到
servlet 容器的webapps目錄中;
二、獲得Solr文件夾,以備隨後將其複製到當前目錄,可使用ant
build獲得,也能夠在下載的壓縮包中找到,以它爲模板以備以後的修改;
三、能夠經過如下三種方式之一設置 Solr 的主位置:
設置 java
系統屬性 solr.solr.home (沒錯,就是 solr.solr.home,通常在嵌入式集成中用得多);
配置
java:comp/env/solr/home 的一個 JNDI 查找指向 solr
目錄,創建/tomcat55/conf/Catalina/localhost/solr.xml文件,注意這個xml文件名將是Solr實例名稱,2中的當前目錄被指定爲下面中的f:/solrhome,文件內容以下: 安全
在包含 solr 目錄的目錄中啓動 servlet 容器(默認的 Solr
主目錄是當前工做目錄下的
solr);
四、最後一點就是若是有CJK(中日韓文字)應用,出現亂碼問題,採用以下方法解決(其實已經不算是solr配置問題,而是應用服務器配置問題),修改Tomcat的conf/server.xml文件中對於端口(本文爲8080)的鏈接器統一資源編碼爲UTF-8,由於Solr1.2內核支持UTF-8編碼:
[Solr分詞順序]Solr創建索引和對關鍵詞進行查詢都得對字串進行分詞,在向索引庫中添加全文檢索類型的索引的時候,Solr會首先用空格進行分詞,而後把分詞結果依次使用指定的過濾器進行過濾,最後剩下的結果纔會加入到索引庫中以備查詢。分詞的順序以下:
索引
1:空格whitespaceTokenize
2:過濾詞StopFilter
3:拆字WordDelimiterFilter
4:小寫過濾LowerCaseFilter
5:英文相近詞EnglishPorterFilter
6:去除重複詞RemoveDuplicatesTokenFilter
查詢
1:查詢相近詞
2:過濾詞
3:拆字
4:小寫過濾
5:英文相近詞
6:去除重複詞
以上是針對英文,中文的除了空格,其餘都相似
[Solr中文應用的一個實例]
1、首先配置schema.xml,這個至關於數據表配置文件,它定義了加入索引的數據的數據類型的。1.2版本的schema.xml主要包括types、fields和其餘的一些缺省設置。
A、首先須要在types結點內定義一個FieldType子結點,包括name,class,positionIncrementGap等等一些參數,name就是這個FieldType的名稱,class指向org.apache.solr.analysis包裏面對應的class名稱,用來定義這個類型的行爲。在FieldType定義的時候最重要的就是定義這個類型的數據在創建索引和進行查詢的時候要使用的分析器analyzer,包括分詞和過濾。在例子中text這個FieldType在定義的時候,在index的analyzer中使用solr.WhitespaceTokenizerFactory這個分詞包,就是空格分詞,而後使用solr.StopFilterFactory,solr.WordDelimiterFilterFactory,solr.LowerCaseFilterFactory,solr.EnglishPorterFilterFactory,solr.RemoveDuplicatesTokenFilterFactory這幾個過濾器。在向索引庫中添加text類型的索引的時候,Solr會首先用空格進行分詞,而後把分詞結果依次使用指定的過濾器進行過濾,最後剩下的結果纔會加入到索引庫中以備查詢。Solr的analysis包並無帶支持中文的包,在這裏咱們採用lucene裏的語言包(在下載後的solr壓縮包內,lib目錄下有一個lucene-analyzers-2.2.0.jar包,裏面含有中文處理的cn和cjk類),有cn和cjk兩個類能夠支持中文。咱們採用cjk類,並在schema.xml中加入以下配置:
支持類型定義完成了。
B、接下來的工做就是在fields結點內定義具體的字段(相似數據庫中的字段),就是filed,filed定義包括name,type(爲以前定義過的各類FieldType),indexed(是否被索引),stored(是否被儲存),multiValued(是否有多個值)等等。例如定義以下:
field的定義至關重要,有幾個技巧需注意一下,對可能存在多值得字段儘可能設置multiValued屬性爲true,避免建索引是拋出錯誤;若是不須要存儲相應字段值,儘可能將stored屬性設爲false。
C、建議創建了一個拷貝字段,將全部的全文字段複製到一個字段中,以便進行統一的檢索:
並在拷貝字段結點處完成拷貝設置:
D、除此以外,還能夠定義動態字段,所謂動態字段就是不用指定具體的名稱,只要定義字段名稱的規則,例如定義一個dynamicField,name爲*_i,定義它的type爲text,那麼在使用這個字段的時候,任何以_i結尾的字段都被認爲是符合這個定義的,例如name_i,gender_i,school_i等。
2、配置solrconfig.xml,用來配置Solr的一些系統屬性,比較重要的一個就是能夠經過更改其中的dataDir屬性來指定索引文件的存放位置,對於有大數據量的狀況下還要進行自動commit操做配置,如下設置爲當內存索引量達到20W條時自動進行往磁盤寫操做,以避免堆溢出,這也是解決單個入庫xml文件最好不要超過30M的有效方法:
3、配置好這些後,須要從新啓動Solr服務器使配置生效,而後向其中添加數據。
4、添加數據是經過向服務器的update Servlet POST
xml格式的數據來實現的,xml結構是這樣的add中間有不少個doc,每一個doc中有不少個field。添加到索引庫中的每條記錄都必須指定惟一的數字id來惟一標識這條索引。創建好xml文件(例如solr.xml)以後,在exampledocs目錄下執行:java
-jar post.jar
solr.xml來添加索引數據。對於post的jar包,若是從新配置了應用服務器,如使用了comcat,端口改成8080,實例名稱改成solrx了須要從新生成相應的post.jar包進行操做。
另附ronghao實現中文分詞的案例供你們參考:
對全文檢索而言,中文分詞很是的重要,這裏採用了qieqie庖丁分詞(很是不錯:))。集成很是的容易,我下載的是2.0.4-alpha2版本,其中它支持最多切分和按最大切分。建立本身的一箇中文TokenizerFactory繼承自solr的BaseTokenizerFactory。
**
* Created by IntelliJ IDEA.
* User: ronghao
* Date: 2007-11-3
* Time: 14:40:59
* 中文切詞 對庖丁切詞的封裝
*/
public class ChineseTokenizerFactory
extends BaseTokenizerFactory {
/**
* 最多切分 默認模式
*/
public static final String
MOST_WORDS_MODE = 「most-words」;
/**
* 按最大切分
*/
public static final String
MAX_WORD_LENGTH_MODE = 「max-word-length」;
private String mode = null;
public void setMode(String mode)
{
if
(mode==null||MOST_WORDS_MODE.equalsIgnoreCase(mode)
|| 「default」.equalsIgnoreCase(mode))
{
this.mode=MOST_WORDS_MODE;
} else if
(MAX_WORD_LENGTH_MODE.equalsIgnoreCase(mode)) {
this.mode=MAX_WORD_LENGTH_MODE;
}
else {
throw new
IllegalArgumentException(」不合法的分析器Mode參數設置:」 + mode);
}
}
@Override
public void init(Map args) {
super.init(args);
setMode(args.get(」mode」));
}
public TokenStream create(Reader input)
{
return new PaodingTokenizer(input,
PaodingMaker.make(),
createTokenCollector());
}
private TokenCollector
createTokenCollector() {
if(
MOST_WORDS_MODE.equals(mode))
return new
MostWordsTokenCollector();
if(
MAX_WORD_LENGTH_MODE.equals(mode))
return new
MaxWordLengthTokenCollector();
throw new Error(」never
happened」);
}
}
在schema.xml的字段text配置里加入該分詞器。
1. <fieldtype name="text"
class="solr.TextField" positionIncrementGap="100">
2.
3. <analyzer
type="index">
4.
5.
<tokenizer
class="com.ronghao.fulltextsearch.analyzer.ChineseTokenizerFactory"
mode="most-words"/>
6.
7.
8. <filter
class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt"/>
9.
10. <filter
class="solr.WordDelimiterFilterFactory" generateWordParts="1"
generateNumberParts="1" catenateWords="1" catenateNumbers="1"
catenateAll="0"/>
11.
12. <filter
class="solr.LowerCaseFilterFactory"/>
13.
14.
15. <filter
class="solr.RemoveDuplicatesTokenFilterFactory"/>
16.
17.
</analyzer>
18.
19. <analyzer
type="query">
20.
21.
<tokenizer
class="com.ronghao.fulltextsearch.analyzer.ChineseTokenizerFactory"
mode="most-words"/>
22.
23. <filter
class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true"
expand="true"/>
24.
25. <filter
class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt"/>
26.
27. <filter
class="solr.WordDelimiterFilterFactory" generateWordParts="1"
generateNumberParts="1" catenateWords="0" catenateNumbers="0"
catenateAll="0"/>
28.
29. <filter
class="solr.LowerCaseFilterFactory"/>
30.
31. <filter
class="solr.RemoveDuplicatesTokenFilterFactory"/>
32.
33.
</analyzer>
34.
35.
</fieldtype>
完成後重啓tomcat,便可在http://localhost:8080/solr/admin/analysis.jsp
體驗到庖丁的中文分詞。注意要將paoding-analysis.jar複製到solr的lib下,注意修改jar包裏字典的home。
[Solr的檢索運算符]
「:」 指定字段查指定值,如返回全部值*:*²
「?」²表示單個任意字符的通配
「*」
表示多個任意字符的通配(不能在檢索的項開始使用*或者?符號)²
「~」²表示模糊檢索,如檢索拼寫相似於」roam」的項這樣寫:roam~將找到形如foam和roams的單詞;roam~0.8,檢索返回類似度在0.8以上的記錄。
²鄰近檢索,如檢索相隔10個單詞的」apache」和」jakarta」,」jakarta
apache」~10
「^」²控制相關度檢索,如檢索jakarta
apache,同時但願去讓」jakarta」的相關度更加好,那麼在其後加上」^」符號和增量值,即jakarta^4
apache
布爾操做符AND、||²
布爾操做符OR、²&&
布爾操做符NOT、!、-²(排除操做符不能單獨與項使用構成查詢)
「+」
存在操做符,要求符號」+」後的項必須在文檔相應的域中存在²
( ) 用於構成子查詢²
² [] 包含範圍檢索,如檢索某時間段記錄,包含頭尾,date:[200707 TO
200710]
{}²不包含範圍檢索,如檢索某時間段記錄,不包含頭尾
date:{200707
TO 200710}
" 轉義操做符,特殊字符包括+ -² && || ! ( ) { } [ ] ^ 」 ~ * ? : "