【Lucene3.6.2入門系列】第14節_SolrJ操作索引和搜索文檔以及整合中文分詞

  1. package com.jadyer.solrj;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. import org.apache.solr.client.solrj.SolrQuery;  
  7. import org.apache.solr.client.solrj.SolrServer;  
  8. import org.apache.solr.client.solrj.SolrServerException;  
  9. import org.apache.solr.client.solrj.impl.HttpSolrServer;  
  10. import org.apache.solr.client.solrj.response.QueryResponse;  
  11. import org.apache.solr.common.SolrDocument;  
  12. import org.apache.solr.common.SolrDocumentList;  
  13. import org.apache.solr.common.SolrInputDocument;  
  14.   
  15. import com.jadyer.model.MyMessage;  
  16.   
  17. /** 
  18.  * 【Lucene3.6.2入門系列】第14節_SolrJ操作索引和搜索文檔以及整合中文分詞 
  19.  * @see ------------------------------------------------------------------------------------------------------------------------- 
  20.  * @see 通過schema.xml使得Solr與中文分詞進行整合 
  21.  * @see 0)默認solr定義的大量域都不支持中文分詞,如果我們要加中文分詞的支持,那麼首先要加的就是<types><fieldType/></types> 
  22.  * @see   下面以MMSeg4j-1.8.5爲例,描述Solr與中文分詞器的整合方式(其核心就是在schema.xml中配置fieldType) 
  23.  * @see   關於MMSeg4j的介紹,詳見http://blog.csdn.net/jadyer/article/details/10049525 
  24.  * @see 1)將mmseg4j-all-1.8.5.jar拷到D:\Develop\apache-solr-3.6.2\server\solr\WEB-INF\lib\文件夾中 
  25.  * @see 2)新建D:\Develop\apache-solr-3.6.2\home\dic\文件夾 
  26.  * @see 3)將mmseg4j-1.8.5.zip\data\文件夾中的詞典文件拷貝到D:\Develop\apache-solr-3.6.2\home\dic\ 
  27.  * @see 4)在schame.xml中添加中文分詞的fieldType定義 
  28.  * @see   通常中文分詞的工具包中都會提供README.txt文件,裏面會描述擴展solr時需要配置的fieldType 
  29.  * @see   同理將mmseg4j-1.8.5.zip中的README.txt打開,拷貝里面描述的三個fieldType到schema.xml中第68行 
  30.  * @see 5)確認並修改這三個fileType中的dicPath屬性值爲"dic"(這裏的dic其實指的就是第二步新建的dic文件夾) 
  31.  * @see 6)最後測試一下中文分詞效果 
  32.  * @see   在solr控制檯上(http://127.0.0.1:8088/solr/admin/)點擊藍色粗體的[ANALYSIS] 
  33.  * @see   然後在Field Analysis下面將Field下拉框修改爲type,並在右面文本框輸入text_general(即schema.xml中定義的fieldType) 
  34.  * @see   接着在Field Value(Index)右面的文本框中輸入測試文本'我來自中國黑龍江省哈爾濱市巴彥縣興隆鎮長春鄉民權村4隊' 
  35.  * @see   再點擊下方的Analyze按鈕,我們就會發現text_general的分詞情況了,然後我們再修改text_general爲剛纔自定義的textComplex,就看到效果啦 
  36.  * @see   另外也可以勾選Field Value(Index)下面的verbose output選框,這樣也會將分詞的各個屬性(position,Offset,type等等)一併顯示出來 
  37.  * @see ------------------------------------------------------------------------------------------------------------------------- 
  38.  * @see 本例中合計用到9個jar,如下所示 
  39.  * @see apache-solr-core-3.6.2.jar 
  40.  * @see apache-solr-solrj-3.6.2.jar 
  41.  * @see commons-codec-1.6.jar 
  42.  * @see commons-io-2.1.jar 
  43.  * @see httpclient-4.1.3.jar 
  44.  * @see httpcore-4.1.4.jar 
  45.  * @see httpmime-4.1.3.jar 
  46.  * @see jcl-over-slf4j-1.6.1.jar 
  47.  * @see slf4j-api-1.6.1.jar 
  48.  * @see ------------------------------------------------------------------------------------------------------------------------- 
  49.  * @create Aug 7, 2013 11:06:20 PM 
  50.  * @author 玄玉<http://blog.csdn.net/jadyer> 
  51.  */  
  52. public enum HelloSolrJ {  
  53.     INSTANCE;  
  54.       
  55.     private SolrServer server;  
  56.       
  57.     private HelloSolrJ(){  
  58.         //創建SolrServer對象,它有兩個線程安全的子類EmbeddedSolrServer和CommonsHttpSolrServer  
  59.         //EmbeddedSolrServer-----內嵌式的,不需要啓動Web服務器  
  60.         //CommonsHttpSolrServer--需要啓動Web服務器,它是通過HTTP請求來獲取數據的  
  61.         //CommonsHttpSolrServer已不推薦直接使用了,而是推薦使用HttpSolrServer類  
  62.         //同樣的StreamingUpdateSolrServer也不推薦使用了,推薦使用ConcurrentUpdateSolrServer  
  63.         server = new HttpSolrServer("http://127.0.0.1:8088/solr");  
  64.     }  
  65.       
  66.     /** 
  67.      * 刪除全部索引 
  68.      */  
  69.     public void deleteAllIndex(){  
  70.         try {  
  71.             //刪除所有的索引,刪除完記得commit才能生效  
  72.             server.deleteByQuery("*:*");  
  73.             server.commit();  
  74.         } catch (Exception e) {  
  75.             e.printStackTrace();  
  76.         }  
  77.     }  
  78.       
  79.       
  80.     /** 
  81.      * 添加索引 
  82.      * @see 這裏之所以沒有硬編碼指定my_title和my_content的中文分詞器 
  83.      * @see 是由於schema.xml中在定義這倆<field>時已通過type屬性指定了中文分詞器 
  84.      */  
  85.     public void addIndex(){  
  86.         List<SolrInputDocument> docs = new ArrayList<SolrInputDocument>();  
  87.         for(int i=1; i<4; i++){  
  88.             SolrInputDocument doc = new SolrInputDocument();  
  89.             //對於Solr而言,默認的id是唯一的主鍵(如果我們沒有自定義主鍵的話),當多次添加的時候,最後添加的相同id的域會覆蓋已有的  
  90.             doc.addField("id", Integer.toString(i));  
  91.             //這裏使用的是自定義的Field,所以就需要在schema.xml中爲其添加<field>描述,並通過type屬性指定其使用的分詞器  
  92.             doc.addField("my_title""這是我的第" + i + "個SolrJ程序");  
  93.             doc.addField("my_content""my第" + i + "個SolrJ程序的運行情況");  
  94.             docs.add(doc);  
  95.         }  
  96.         try {  
  97.             //可以只添加一個Document,也可以一次添加多個Document,這裏添加多個  
  98.             server.add(docs);  
  99.             //commit後方能生效,否則搜索到的還是add前的索引信息  
  100.             server.commit();  
  101.         } catch (Exception e) {  
  102.             e.printStackTrace();  
  103.         }  
  104.     }  
  105.       
  106.       
  107.     /** 
  108.      * 使用JavaBean來添加索引 
  109.      */  
  110.     public void addIndexByBean(){  
  111.         List<MyMessage> msgs = new ArrayList<MyMessage>();  
  112.         //由於MyMessage()的第三個參數允許傳入多個值,此時就要在Solr的schema.xml中配置<field my_content multiValued="true"/>支持多值域  
  113.         //並且在MyMessage.java中要使用@Field註解標註,可以標註在屬性或setter方法上,並通過註解的默認值來指定所要存儲的Field的名字  
  114.         msgs.add(new MyMessage("4""這是我的第4個SolrJ程序"new String[]{"第4個SolrJ程序誕生於中國""它是通過SolrJ OF JavaBean4誕生添加的"}));  
  115.         msgs.add(new MyMessage("5""這是我的第5個SolrJ程序"new String[]{"第5個SolrJ程序誕生於哈爾濱""它是通過SolrJ OF JavaBean5誕生添加的"}));  
  116.         try {  
  117.             server.addBeans(msgs);  
  118.             server.commit();  
  119.         } catch (Exception e) {  
  120.             e.printStackTrace();  
  121.         }  
  122.     }  
  123.       
  124.       
  125.     /** 
  126.      * 搜索文檔 
  127.      */  
  128.     public void searchFile(){  
  129.         //設置查詢字符串  
  130.         SolrQuery query = new SolrQuery("my_content:誕生");  
  131.         //設置了setStart和setRows就可以實現分頁效果了  
  132.         query.setStart(0);  
  133.         query.setRows(3);  
  134.         QueryResponse resp = null;  
  135.         try {  
  136.             resp = server.query(query);  
  137.         } catch (SolrServerException e) {  
  138.             e.printStackTrace();  
  139.         }  
  140.         //搜索出來的結果都保存在SolrDocumentList中  
  141.         SolrDocumentList sdl = resp.getResults();  
  142.         //這裏獲取到的是搜索到的總數量,與query.setRows(3)無關  
  143.         System.out.println("本次搜索到[" + sdl.getNumFound() + "]條數據");  
  144.         for(SolrDocument sd : sdl){  
  145.             //System.out.println(sd)會輸出SolrDocument[{id=4, my_title=這是我的第4個SolrJ程序, my_content=[第4個....於中國, 它是....進來的]}]  
  146.             System.out.println("my_title=" + sd.getFieldValue("my_title") + "        my_content=" + sd.getFieldValue("my_content"));  
  147.         }  
  148.     }  
  149.   
  150.       
  151.     /** 
  152.      * 使用JavaBean接收文檔搜索結果 
  153.      */  
  154.     public void searchFileByBean(){  
  155.         SolrQuery query = new SolrQuery("id:*");  
  156.         query.setStart(0);  
  157.         query.setRows(3);  
  158.         QueryResponse resp = null;  
  159.         try {  
  160.             resp = server.query(query);  
  161.         } catch (SolrServerException e) {  
  162.             e.printStackTrace();  
  163.         }  
  164.         List<MyMessage> list = resp.getBeans(MyMessage.class);  
  165.         //這裏獲取到的不是搜索到的總數量,而是與query.setRows(3)有關的值  
  166.         //若實際的SolrQuery("id:*")能搜索到5條,則這裏得到的就是3,若實際能搜索到的是2條,則這裏得到的就是2條  
  167.         System.out.println("本次搜索到[" + list.size() + "]條數據");  
  168.         for(MyMessage msg : list) {  
  169.             System.out.println(msg.getTitle() + "         " + msg.getContent()[0]);  
  170.         }  
  171.     }  
  172. }  


下面是用到的JavaBean類

  1. package com.jadyer.model;  
  2.   
  3. import org.apache.solr.client.solrj.beans.Field;  
  4.   
  5. public class MyMessage {  
  6.     @Field  
  7.     private String id;  
  8.     @Field("my_title")  
  9.     private String title;  
  10.     @Field("my_content")  
  11.     private String[] content;  
  12.       
  13.     /*-- 三個屬性的setter和getter略 --*/  
  14.       
  15.     public MyMessage() {}  
  16.   
  17.     public MyMessage(String id, String title, String[] content) {  
  18.         this.id = id;  
  19.         this.title = title;  
  20.         this.content = content;  
  21.     }  
  22. }  

最後是JUnit4.x寫的一個小測試

  1. package com.jadyer.test;  
  2.   
  3. import org.junit.Test;  
  4.   
  5. import com.jadyer.solrj.HelloSolrJ;  
  6.   
  7. public class HelloSolrJTest {  
  8.     @Test  
  9.     public void deleteAllIndex(){  
  10.         HelloSolrJ.INSTANCE.deleteAllIndex();  
  11.     }  
  12.       
  13.     @Test  
  14.     public void addIndexAndSearchFile(){  
  15.         HelloSolrJ.INSTANCE.addIndex();  
  16.         HelloSolrJ.INSTANCE.searchFile();  
  17.     }  
  18.       
  19.     @Test  
  20.     public void addIndexAndSearchFileByBean(){  
  21.         HelloSolrJ.INSTANCE.addIndexByBean();  
  22.         HelloSolrJ.INSTANCE.searchFileByBean();  
  23.     }  
  24. }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章