【轉載】solr初體驗

【1】http://cxshun.iteye.com/blog/1039445java

因爲工做緣由,這段時間接觸到solr,一個基於lucene的企業級搜索引擎。不怎麼了解它的童鞋能夠去GOOGLE一下。web

下面開始正題:apache

1)要開始solr的學習,首先固然是要下載它啦(這是一句廢話),能夠到http://www.apache.org/dyn/closer.cgi/lucene/solr/這裏去下載,最新的是1.4.1。下完後固然要解壓啦(這也是廢話)。咱們看到它的結構是這樣的。json


 相信搞JAVA的同志們應該都大概瞭解對應的文件夾的意思啦,在dist裏面是它的一些JAR包,當中包含了一個war包,這個是咱們作例子時用到的項目。直接把它丟到tomcat的webapps裏面去。瀏覽器

example目錄裏面有一些solr的索引數據,它自帶了一個jetty方便運行,能夠直接運行java -jar start.jar就能夠運行jetty,但jetty的默認端口是8983,這個是跟tomcat不一樣的地方,要注意啦。tomcat

2)搞定了這些以後,那麼咱們應該繼續來試運行一下這個東西啦。solr最重要的東西就是solr home,這個東西指定了solr創建的索引文件的存放位置。不知道是什麼東西,能夠先不用管它,一步步來也許就會明白了。服務器

進到tomcat文件夾conf\Catalina\localhost這個文件夾內,創建一個solr.xml(其實名字是隨便的,這裏起的名字跟之後訪問的項目名字一致,不過爲了好找,仍是跟部署的項目名同樣吧),這裏面的內容呢,其實很簡單,就和下面相似:app

 

Xml代碼   收藏代碼
  1. <Context docBase="D:/server/apache-tomcat-6.0.32/webapps/apache-solr-1.4.1.war" reloadable="true">  
  2.     <Environment name="solr/home" type="java.lang.String" value="E:/framework/libPack/apache-solr-1.4.1/example/solr" override="true" />  
  3. </Context>  

  這個Context相信你們都知道羅,它是指定了war包的位置,當啓動tomcat後它會自動被部署到webapps目錄下,這也是eclipse所集成tomcat用的部署方式。而reloadable="true"則代表能夠從新加載,即當這個部署內容改變時,它會自動進行加載。eclipse

下面的solr/home是重點啦,type是固定的,先無論,value指定的就是它用的索引目錄。override固然就是覆蓋啦,若是存在則覆蓋。webapp

這個solr/home其實在solr的下載包中已經帶有一個,咱們能夠找到solr目錄下的example/solr這個目錄,下面就是咱們所說的solr/home,其實當中最重要的仍是config目錄下的solrconfig.xml,這個是solr的主要配置文件,能夠在裏面找到<dataDir>${solr.data.dir:./solr/data}</dataDir>這樣一句,它指定了索引記錄放置的位置,咱們啓動tomcat後它會在咱們當前的目錄下生成solr/data文件夾,裏面就是索引文件。若是咱們從tomcat的bin啓動,那麼它會在bin目錄下生成solr/data文件夾,能夠根據本身須要進行修改,只要把./solr/data改爲想讓它放在目錄就能夠了。

這樣配置完成後,咱們啓動tomcat以後在瀏覽器輸入http://localhost:8080/solr/admin就能夠看到solr的管理界面啦。



 這樣咱們的配置就大功告成了。

曾經看過javaeye上一位朋友問過淘寶上的分面搜索是怎麼實現的,當時有一位高人說是用solr,沒想到它能夠作出這麼牛的東西,還有好多要學習呢。

 

 

 

---------------------------------------------------------------------------

【2】http://cxshun.iteye.com/blog/1040656

接着上篇http://cxshun.iteye.com/blog/1039445,咱們講了怎麼初始化配置solr,並運行。問題來了,當咱們配置完成後,索引當中並無任何東西,就是說咱們查詢獲得的結果永遠是0。

如今這篇文章,咱們要講的就是若是添加數據和刪除數據,並體驗一下solr的基本請求參數的用法。

1)首先,咱們必須知道,solr添加數據類型能夠有多種格式,最經常使用的是XML和JSON,這兩種的可讀性是最好的。在solr的example/exampledocs文件夾內有自帶一些XML格式的文件,便於咱們進行添加數據。

首先呢,又是一些廢話,固然是啓動example自帶的jetty啦,仍是上次的命令,java -jar start.jar。

接着另外開一下cmd,進入到example/exampledocs文件夾內,運行java -jar post.jar *.xml,這裏的*.xml表明文件夾內的全部XML文件,固然你也能夠選擇其餘一個進行添加,執行後咱們看到執行結果。

看到最後一句,它代表提交此次索引全部的變化。這個提交的設置咱們在後面會看到它的用法。

2)這裏咱們再進入到solr的管理頁面,http://localhost:8983/solr/admin,咱們直接搜索solr,看到頁面大概以下:


 咱們進行搜索的結果默認是用XML格式顯示,固然咱們可讓它用JSON格式來顯示,只要加上wt=json便可,加上後咱們看到的結果爲:



  能夠看到正確的結果。

http://localhost:8983/solr/select/?q=solr&version=2.2&start=0&rows=10&indent=on&wt=json下面咱們分析一下這個連接中參數的意義,q固然是搜索的內容啦,version暫時能夠無論,用處不在,start和rows與hibernate中的分頁參數相似,指開始的記錄位置和查詢的條數,indent指返回代碼的縮進,能夠試一下不加這個和加這個的區別,wt則是返回的結果格式。

3)上面是咱們用的它自帶的XML文件提交的結果,下面咱們本身來寫一個。爲了方便,咱們就參照它的救命文件寫一個。咱們找到schema.xml能夠看到:



  這個是它容許咱們提交的field的名稱,咱們就參照這些字段寫幾個試試吧。我把這個文件命名爲test.xml

 

Xml代碼   收藏代碼
  1. <add>  
  2.     <doc>  
  3.             <field name="id">Donnie Yen</field>  
  4.             <field name="text">Great</field>  
  5.     </doc>      
  6. </add>  

  接着咱們用java -jar post.jar test.xml出現下面的結果:

  這代表咱們的數據已經提交成功,咱們能夠搜索一下:

http://localhost:8983/solr/select/?q=text:great&version=2.2&start=0&rows=10&indent=on

  這代表咱們提交的數據已經成功更新到索引了。

4)說了添加,如今也該來刪除一些東西了,咱們想刪除咱們剛纔添加的那條記錄,咱們能夠發送命令java -Ddata=args -jar post.jar "<delete><id>Donnie Yen</id></delete>"(這個命令中的-Ddata=args代表數據是中參數中獲取),出現

  則咱們刪除成功,不肯定?那麼咱們再去查一下:

  沒了吧,證實咱們刪除成功了。

這些東西不難吧。solr用得比較多的東西就是分面瀏覽,也就是facet navigation。下面咱們來學習一下。

5)分面瀏覽指的是像淘寶的功能同樣,咱們搜索一種產品,它會在上面再根據類別分出好多小類,直接看圖:


  咱們看到它又分出了好多類,這種效果就叫分面瀏覽。

solr能夠輕鬆作到分面瀏覽,好比咱們在瀏覽器輸入http://localhost:8983/solr/select/?q=solr&version=2.2&start=0&rows=10&indent=on&facet=true&facet.field=name&facet.query=price:[300%20TO%20400],咱們能夠看到:



  這就是分面瀏覽的結果,它根據每一個值再從新統計,統計出該類別下有多少個值。分面瀏覽的參數比較多,你們能夠上WIKi上面看看http://wiki.apache.org/solr/SimpleFacetParameters

 

--------------------------------------------------------------------------------------------------------------

【3】http://cxshun.iteye.com/blog/1041742

前兩天,學習了solr的基本用法,接下來咱們就開始真正來學習一下solr。學習一下它的文件結構,配置文件等。

以咱們如今學習的階段,最重要的文件夾就是example文件夾,這個裏面包含了許多咱們要學習的東西。

咱們再來看一下該文件夾結構

咱們看到這樣的文件結構,文件夾的意思你們確定都看得懂,這裏只介紹兩個文件夾,multicore和solr。

multicore是多個solr實例時才須要用到,如今咱們暫時沒用,先無論它。solr是自帶的一個solr.home,這個是咱們這次介紹的重點。

進入此文件夾,咱們能夠看到以下的結構:

bin文件夾爲咱們有額外的處理腳本時,須要放在這裏,這裏暫時沒用到,咱們先跳過。

conf是solr的配置文件所在,這裏是重點。

data爲索引目錄。

因爲我覺得運行過,因此有這個data.bak目錄,這具是之前的備份。

咱們主要來看一下conf文件夾內的配置文件:

這裏帶副本的是個人備份文件。最主要的文件是schema.xml和solrconfig.xml,其他的如stopwords.txt爲停頓詞,當索引和查詢時遇到這些詞會自動忽略,其餘文件,咱們暫時不用,先不講了。

打開solrconfig.xml咱們能夠看到<dataDir>這個標籤,默認狀況下是這樣的

<dataDir>${solr.data.dir:./solr/data}</dataDir>

  它默認在當前目錄下的solr目錄下建立data目錄來存放索引。這就是爲何當咱們把solr.home設置成這個時,在tomcat的bin文件夾內啓動時會生成solr/data文件夾。由於咱們啓動tomat時的當前目錄爲bin。

固然這個不是solr配置錯誤,對於它自帶的jetty服務器來講,它是正確的,由於當前目錄,正好是solr的目錄。

這個文件咱們須要配置的東西很少,先講到這裏,之後用到時再慢慢講解。

接下來咱們看一下重點的schema.xml,這個文件是對咱們索引字段的說明,咱們能夠索引什麼field都在這裏進行了說明。

咱們能夠看到裏面有一大堆註釋,其實看裏面的註釋,大部分都是能夠理解的。這個文件的配置跟咱們之後須要進行的中文分詞的集成有很大關係,因此這個文件要多看看。

咱們看到types標籤,而在它裏面有一大堆fieldType,裏面也有一大堆屬性,這裏大概介紹一下:

fieldType是定義索引的field類型,它有好幾個屬性,最主要的是name和class:

name是類型的名稱,class是相應的solr中的類。還有兩個屬性看英文註釋可能比較難理解,是sortMissingLast和sortMissingFirst,這兩個屬性是指當查找出來的內容爲空時,它被排在哪裏,當sortMissingLast爲true時,表示放在最後,sortMissingFirst爲true時,表示放在最前。爲false時相反。

注意,咱們看到後面時發現有fieldType裏面有<Analyzer>標籤,這個是用於配置分詞器的,這個咱們之後再說。

接着是<fields>標籤和在它裏面的<field>,field固然就是咱們在索引的內容啦。

它有屬性indexed和stored分別對應是否索引和保存,另外還有一個multiValued表示是否容許多值。

這裏咱們看到features有好幾個值,而咱們看到配置文件中配置的features也是這樣的:

Xml代碼   收藏代碼
  1. <field name="features" type="text" indexed="true" stored="true" multiValued="true"/>  

它表示咱們索引的field有多個值,若是這裏沒配置,在發送數據的時候會報錯。

這裏的type是對應咱們前面配置的fieldType。

另外有一個<dynamicField>這是一個動態匹配的域,

Xml代碼   收藏代碼
  1. <dynamicField name="*_i"  type="int"    indexed="true"  stored="true"/>  

咱們看到它的name指定了通配符,它指的是能夠匹配全部以_i結尾的名稱的field,若是咱們指定

Xml代碼   收藏代碼
  1. <dynamicField name="*"/>  

那咱們就能夠匹配全部的field。

接下來,咱們看到:

 

Xml代碼   收藏代碼
  1.  <uniqueKey>id</uniqueKey>  
Xml代碼   收藏代碼
  1. <defaultSearchField>text</defaultSearchField>  
Xml代碼   收藏代碼
  1. <solrQueryParser defaultOperator="OR"/>  
  2.  <copyField source="cat" dest="text"/>  

        這裏應該看英文就能夠看明白了,最主要是最下面的copyField,它是指複製field,它會把在source field裏的值拷貝到text field裏面,這樣方便進行索引。注意,這裏通常也只有對多值的纔會這樣作,也便是配置了multiValued爲true的field才用copyField.

  
--------------------------------------------------------------------------------------------------------------

 

【4】http://cxshun.iteye.com/blog/1043200

 

前幾回咱們講到了solr的基本用法和配置文件,接下來就開始進入咱們真正的代碼之旅啦。

1)首先以一個簡單的程序來開頭:

Java代碼   收藏代碼
  1. public static void main(String[] args) throws SolrServerException, IOException, ParserConfigurationException, SAXException{  
  2.         
  3.           //設置solr.home,注意這時經過環境變量是solr.solr.home  
  4.       System.setProperty("solr.solr.home","E:\\solr");  
  5.           //初始化容器,讓它加載solr.home的配置文件  
  6.       CoreContainer.Initializer initializer = new CoreContainer.Initializer();  
  7.       CoreContainer coreContainer = initializer.initialize();  
  8.         
  9.       EmbeddedSolrServer solrServer = new EmbeddedSolrServer(coreContainer,"");  
  10.       //構造參數列表  
  11.       SolrQuery solrQuery = new SolrQuery();   
  12.       Map<String,String> map = new HashMap<String,String>();  
  13.       map.put(FacetParams.FACET_DATE, "manufacturedate_dt");  
  14.       map.put(FacetParams.FACET_DATE_START,"2004-01-01T00:00:00Z");  
  15.       map.put(FacetParams.FACET_DATE_END,"2010-01-01T00:00:00Z");  
  16.       map.put(FacetParams.FACET_DATE_GAP,"+1YEAR");  
  17.       map.put("indent","on");  
  18.       map.put("wt","xml");  
  19.       map.put("hl.fl","name");  
  20.       SolrParams params = new MapSolrParams(map);  
  21.       solrQuery.add(params);  
  22.       solrQuery.setFacet(true);  
  23.       solrQuery.setFields("name,price,score");  
  24.       solrQuery.setQuery("solr");  
  25.       solrQuery.setSortField("price",SolrQuery.ORDER.asc);  
  26.       solrQuery.setHighlight(true);  
  27.         
  28.       System.out.println(solrQuery.toString());  
  29.             
  30.       QueryResponse queryResponse = solrServer.query(solrQuery);   
  31.       System.out.println(queryResponse.toString());  
  32.       System.out.println("共找到:"+queryResponse.getResults().getNumFound()+"個結果");  
  33.           //解析返回的參數  
  34.       SolrDocumentList sdl = (SolrDocumentList)queryResponse.getResponse().get("response");  
  35.       for (int i = 0; i< sdl.size(); i++){  
  36.           Object obj = sdl.get(i).get("manufacturedate_dt");  
  37.           String date = "";  
  38.           if (obj!= null){  
  39.               date = new SimpleDateFormat("yyyy-MM-dd").format((Date)obj);  
  40.           }  
  41.             
  42.           System.out.println(((SolrDocument)sdl.get(i)).get("name")+":"+date+":"+(sdl.get(i).get("price")));  
  43.       }  
  44.   }  

  這時咱們所用到的是EmbeddedSolrServer,它是用於嵌入式地solr服務,這裏咱們不須要向外提供服務,因此咱們就用到這個。另外有一個

CommonsHttpSolrServer這個類是用於發送指令的服務,例如咱們須要發送HTTP命令來查詢,就能夠用這個。

下面咱們分析一下代碼,首先,咱們設置了一個環境變量的名稱爲solr.solr.home,是這個,你沒看錯,確實是要這樣。接下來咱們初始化容器,讓它加載solr.home的配置文件等。接下來的一系統代碼就是構造參數列表。

咱們構造完成後的參數列表是這樣的:facet.date.start=2004-01-01T00%3A00%3A00Z&indent=on&facet.date=manufacturedate_dt&hl.fl=name&facet.date.gap=%2B1YEAR&wt=xml&facet.date.end=2010-01-01T00%3A00%3A00Z&facet=true&fl=name%2Cprice%2Cscore&q=solr&sort=price+asc&hl=true

跟咱們直接在瀏覽器輸入的不太同樣,由於它是進行過編碼的。構造完成後咱們就能夠用solrServer進行查詢了。

查詢獲得的結果是JSON格式的,注意,經過程序來查詢獲得的都是JSON格式,而不是XML格式,不過這樣更好,方便咱們進行接下來的解析。

接下來的代碼就是解析內容啦,應該很容易看懂的。

2)接下來的咱們就嘗試本身寫一個程序來進行索引,而不用post.jar。

程序代碼以下:

Java代碼   收藏代碼
  1. public static void main(String[] args) throws IOException, ParserConfigurationException, SAXException{  
  2.           
  3.         System.setProperty("solr.solr.home","e:\\solrIndex");  
  4.           
  5.                 //這下面三行代碼主要是用於加載配置文件  
  6.         SolrConfig solrConfig = new SolrConfig("E:\\solrIndex\\conf\\solrconfig.xml");  
  7.         FileInputStream fis = new FileInputStream("E:\\solrIndex\\conf\\schema.xml");  
  8.         IndexSchema indexSchema = new IndexSchema(solrConfig,"solrconfig",fis);  
  9.           
  10.         SolrIndexWriter siw = new SolrIndexWriter("solrIndex","E:\\solrIndex",new StandardDirectoryFactory()  
  11.                 ,true,indexSchema);  
  12.         Document document = new Document();  
  13.         document.add(new Field("text","測試一下而已",Field.Store.YES,Field.Index.ANALYZED,Field.TermVector.WITH_POSITIONS_OFFSETS));  
  14.         document.add(new Field("test_t","再測試一下而已",Field.Store.YES,Field.Index.ANALYZED,Field.TermVector.WITH_POSITIONS_OFFSETS));  
  15.         siw.addDocument(document);  
  16.           
  17.         siw.commit();  
  18.         siw.close();  
  19.           
  20.         SolrCore solrCore = new SolrCore("E:\\solrIndex",indexSchema);  
  21.           
  22.         SolrIndexSearcher sis = new SolrIndexSearcher(solrCore,indexSchema,"solrIndex",  
  23.                         new StandardDirectoryFactory().open("E:\\solrIndex"),true);  
  24.         TopDocs docs = sis.search(new TermQuery(new Term("test_t","再")),1);  
  25.           
  26.         System.out.println("找到"+docs.totalHits+"個結果 ");  
  27.           
  28.         for (int i = 0; i < docs.scoreDocs.length; i++) {  
  29.             System.out.println(sis.doc(docs.scoreDocs[i].doc).get("test_t"));  
  30.         }  
  31.           
  32.     }  

  代碼不難理解,因此就沒寫註釋了。主要是那段加載配置文件的代碼。接下來是添加索引,而後是查詢索引,刪除的比較簡單,直接一句代碼

Java代碼   收藏代碼
  1. solrServer.solrServer.deleteById("SOLR1000");  

  或者

Java代碼   收藏代碼
  1. solrServer.deleteByQuery()  

  都比較簡單。

3)接下來咱們講一下,極可能會在項目中用到的,就是中文分詞,中文分詞有蠻多的,有IK,Paoding,mmseg4j,還有另一些中科院什麼地方的。但我的建議用IK或者mmseg4j,這兩個有solr都有比較直接的支持,paoding也能夠,但可能須要本身寫類繼承BaseTokenizerFactory而後再進行配置,不難。

上面的例子就是用到中文分詞了,若是你發現找不到結果,那很正常,由於還沒添加中文分詞,你能夠把中文改爲英文,再查一下,就能夠查出來了。

須要添加中文分詞,咱們要在schema.xml中作文章。找到types標籤,在裏面找到你想要進行中文分詞的類型,好比text類型,咱們想要讓它的內容用中文分詞來進行分析,能夠進行配置:

Xml代碼   收藏代碼
  1. <analyzer type="index">  
  2.         <tokenizer class="org.wltea.analyzer.solr.IKTokenizerFactory"/>  
  3.         <filter class="solr.StopFilterFactory"  
  4.                 ignoreCase="true"  
  5.                 words="stopwords.txt"  
  6.                 enablePositionIncrements="true"  
  7.                 />  
  8.         <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>  
  9.         <filter class="solr.LowerCaseFilterFactory"/>  
  10.         <filter class="solr.SnowballPorterFilterFactory" language="English" protected="protwords.txt"/>  
  11.       </analyzer>  
  12.       <analyzer type="query">  
  13.         <tokenizer class="org.wltea.analyzer.solr.IKTokenizerFactory"/>  
  14.         <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>  
  15.         <filter class="solr.StopFilterFactory"  
  16.                 ignoreCase="true"  
  17.                 words="stopwords.txt"  
  18.                 enablePositionIncrements="true"  
  19.                 />  
  20.         <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="1"/>  
  21.         <filter class="solr.LowerCaseFilterFactory"/>  
  22.         <filter class="solr.SnowballPorterFilterFactory" language="English" protected="protwords.txt"/>  
  23.       </analyzer>  

  你能夠先不理解filter的那些東西,但你必定要理解tokenizer這些地方的配置,它配置了你想要應用的分詞器,它必須繼承於BaseTokenizerFactory。咱們看到analyzer有一個type屬性,它表示你要在哪一個階段運用此分詞器,若是索引和查詢都要用,咱們能夠不寫type,這樣solr就會在索引和查詢時都使用此分詞器,這樣配置完成後就能夠進行中文分詞的測試啦。咱們從新把上面的例子添加中文進行索引,而後查詢出來,看有沒有問題。個人運行結果以下:

 


  咱們找到告終果,證實咱們的中文分詞已經沒問題了。

相關文章
相關標籤/搜索