閱讀947 返回首頁    go 阿裏雲 go 技術社區[雲棲]


Solr配置搜索服務

背景

我用Lucene3.6,為php語言搭建的平台提供一套搜索服務,但是lucene隻是個提供索引操作的庫,需要一個web-service來提供給java外的語言,使之可以通過http方式發送搜索請求並得到如json, xml格式的查詢結果集數據。而Solr是一個二次包裝了Lucene庫的搜索服務容器,兼容lucene的api,可以在jetty或者Tomcat這樣的容器裏以web服務的方式啟動並提供一套自己的索引建立,更新,刪除,查詢接口,以及更高級更全麵的接口服務。


關於Solr

Solr版本隨著lucene版本的更新而兼容更新,目前已經發布4.0,我使用的是3.6版本。在配置中文分詞庫以及使用Solrj來訪問solr服務的時候,也因為版本比較新,遇到了一些問題,我會在下麵詳細說明。我初步感受,Solr和lucene有以下一些區別:

Solr的索引建立主要有通過xml文件讀取需要建索引的數據、通過solrj用api來addDocument,此外還有讀取CVS文件,獲取post來的json數據以及直接從數據庫讀(DIH)。來講講主要的索引建立方法。其實通過Solrj用api裏的類和函數來建索引是類似於Lucene的做法的,差別是兩者的api長的不一樣。但凡使用過lucene的人,就會覺得solrj的關鍵類和使用方法還是一目了然,比如下麵這樣:

String url = "https://localhost:8080/solr";
SolrServer server = new HttpSolrServer(url);
SolrQuery query = new SolrQuery();
SolrInputDocument doc1 = new SolrInputDocument();
doc1.addField( "id", "id1", 1.0f );
doc1.addField( "name", "doc1", 1.0f );
doc1.addField( "price", 10 );
SolrInputDocument doc2 = new SolrInputDocument();
doc2.addField( "id", "id2", 1.0f );
doc2.addField( "name", "doc2", 1.0f );
doc2.addField( "price", 20 );
Collection<SolrInputDocument> docs = new ArrayList<SolrInputDocument>();
docs.add( doc1 );
docs.add( doc2 );
server.add( docs ); 
server.commit();

下載solr後,在 {solr.home}/example/exampledocs 內會有一些xml,就是通過第一種建索引的方式用xml文件導入數據。比如下麵這樣:

<add><doc>
  <field name="id">3007WFP</field>
  <field name="name">Dell Widescreen UltraSharp 3007WFP</field>
  <field name="manu">Dell, Inc.</field>
  <field name="cat">electronics</field>
  <field name="cat">monitor</field>
  <field name="features">30" TFT active matrix LCD, 2560 x 1600, .25mm dot pitch, 700:1 contrast</field>
  <field name="includes">USB cable</field>
  <field name="weight">401.6</field>
  <field name="price">2199</field>
  <field name="popularity">6</field>
  <field name="inStock">true</field>
  <!-- Buffalo store -->
  <field name="store">43.17614,-90.57341</field>
</doc></add>
這兩者都有個共同的問題,關於不同Filed的分詞,STORE,Analyze是怎麼處理的?

solr有兩個重要的配置文件:scheme.xml和solrconfig.xml

scheme.xml主要配置:

每個fieldtype來自哪個類,是solr自帶的主要類型,還是你自己要加入的類,比如中文分詞的類,各舉一個例子:

<fieldType name="string"  sortMissingLast="true" />
<fieldType name="boolean"  sortMissingLast="true"/>
<fieldType name="text_ik" > 
      <analyzer /> 
</fieldType>
上麵第二個配置是我加的中文分詞,使用的是IKAnalyzer,版本是2012u6,最新的版本。配置了filedtype之後,要在scheme.xml裏配置將要建立的索引字段的類型和信息

<field name="goods_id" type="string" indexed="false" stored="true"/>
<field name="brand_name" type="text_ik" indexed="true" stored="true"/>
這樣應該解釋清楚了。至於,solrconfig.xml,主要是一些係統依賴,緩存配置,各種http的requestHandler的請求處理類等。

總結,就是solr的索引配置主要在xml裏,甚至數據也可以寫成xml,然後在cmd裏添加數據文件,這就是封裝了lucene的結果,比lucene更高層一點,而我認為這樣的配置不怎麼方便,我的選擇是把自己用lucene建出來的索引塊直接丟到solr索引目錄裏,並在scheme.xml裏添加好字段,包括配置好中文分詞工具,因為solr和lucene是兼容的,而包裝到來的效果就是api不夠底層。
再舉幾個小的方麵,其實也可以說是solr比lucene進步的地方。lucene源碼裏,core包之外的隨後整合的附加功能包highlighting在solr裏是已經配置完整,並且solr的搜索url裏可以整合排序和高亮等要求,給幾個例子(hl是highlighting縮寫):

q=video&sort=score desc
q=video&sort=inStock asc, score desc
q=video card&fl=name,id&hl=true&hl.fl=name,features

solr其實就是把lucene包裝之後,變成了一個web的服務,放在容器裏run起來後,可以通過http訪問,作為一個中間件的服務存在。如果你自己做,也就是把lucene開發好之後寫一些servlet的東西,也放在tomcat,jetty裏麵跑,然後接受url,做相應的response。solr的搜索請求和數據導入方式比較多樣,適合不同開發者選用方便的特性適應需求,在Solr Tutorial裏可以看到。


Solr的安裝和配置

網上有很多資料,Solr3.6版本的配置也沒有什麼特別的。下載解壓之後,可以選擇直接進入 {solr.home}/example 目錄,用 java -jar start.jar在8983端口啟動服務,是在jetty容器裏啟動的,在 {solr.home}/example 子目錄下已經為你部署好了jetty,jsp的jar包以及環境配置。你也可以啟動自己的tomcat,把solr.war放到tomcat的webapp目錄下,注意的是需要在 {tomcat.home}/conf/Catalina/localhost 下手動加一個solr.xml文件,作用是指向你的{solr.home}路徑,讓tomcat找到你要啟動的web服務。比如我的:

<Context docBase="E:\softs2\apache-tomcat-6.0.36\webapps\solr.war" debug="0" crossContext="true" >
   <Environment name="solr/home" type="java.lang.String" value="E:\softs2\apache-solr-3.6.2\example\solr" override="true" />
</Context>

啟動solr後,通過瀏覽器就可以訪問到你的solr服務,具體別的自己慢慢研究吧。


由於版本而導致的問題並解決方案
首先是中文分詞器。我使用的是IKAnalyzer2012_u6版本,IK,庖丁和mmseg是主流的三個支持lucene的分詞庫。但是中文分詞庫注定悲劇的地方在於總要跟著國外開源軟件的更新走,一旦lucene,solr更新了,某些基礎類改變或者接口變動,分詞器可能就不再支持了。IKTokenizerFactory繼承自solr的BaseTokenizerFactory,但是BaseTokenizerFactory在solr3.6之後版本已經不存在了,如果你按照以前的配置方式在scheme裏配置:

<fieldType name="text"  > 
  <analyzer type="index"> 
    <tokenizer  useSmart ="false"/> 
  </analyzer> 
  <analyzer type="query">   <tokenizer  useSmart ="false"/> 
  </analyzer> 
</fieldType>
啟動solr後報錯提示BaseTokenizerFactory類是找不到了的。所以隻能這樣配置:

<fieldType name="text_ik" > 
      <analyzer /> 
</fieldType> 
再者是solrj版本。我的solr是3.6版本,我在IDE裏使用的solrj是3.6.0版本的。通過maven的pom.xml裏的Dependencis查找solrj,並自動獲取相關包之後,還是會出現問題。原因是HttpSolrServer類還依賴別的包。那就是httpcomponents的httpclient和httpmime包,應該4.1後的版本是可以的,我依賴的是4.1.3。總之最後的pom.xml裏的配置是這樣的:

<dependencies>
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>3.8.1</version>
			<scope>test</scope>
	</dependency>
	<dependency>
		<groupId>mysql</groupId>
		<artifactId>mysql-connector-java</artifactId>
		<version>5.1.18</version>
	</dependency>
	<dependency>
		<groupId>IKAnalyzer</groupId>
		<artifactId>IKAnalyzer</artifactId>
		<version>2012u6</version>
		<scope>system</scope>
		<systemPath>${project.basedir}/lib/IKAnalyzer2012_u6.jar</systemPath>
	</dependency>
	<dependency>
		<groupId>org.apache.lucene</groupId>
		<artifactId>lucene-analyzers</artifactId>
		<version>3.6.0</version>
	</dependency>
	<dependency>
		<groupId>org.apache.solr</groupId>
		<artifactId>solr-solrj</artifactId>
		<version>3.6.0</version>
	</dependency>
	<dependency>
		<groupId>org.apache.httpcomponents</groupId>
		<artifactId>httpclient</artifactId>
		<version>4.1.3</version>
	</dependency>
	<dependency>
		<groupId>org.apache.httpcomponents</groupId>
		<artifactId>httpmime</artifactId>
		<version>4.1.3</version>
	</dependency>
</dependencies>
最後會依賴到下麵這些jar包:



有了solr服務,有了中文分詞,有了solrj,搭建自己的solr搜索服務平台就沒什麼問題了。最後給出一些相關基礎資料,方便使用solr:

Solrj: https://wiki.apache.org/solr/Solrj

Solr Tutorial: https://lucene.apache.org/solr/api-3_6_1/doc-files/tutorial.html

Solr中文網:https://www.solrcn.com



最後更新:2017-04-04 07:03:23

  上一篇:go 安卓BitmapFactory.decodeStream()返回null的問題解決方法
  下一篇:go 轉貼:STL之list之用法小結