- package com.jadyer.solrj;
- import java.util.ArrayList;
- import java.util.List;
- import org.apache.solr.client.solrj.SolrQuery;
- import org.apache.solr.client.solrj.SolrServer;
- import org.apache.solr.client.solrj.SolrServerException;
- import org.apache.solr.client.solrj.impl.HttpSolrServer;
- import org.apache.solr.client.solrj.response.QueryResponse;
- import org.apache.solr.common.SolrDocument;
- import org.apache.solr.common.SolrDocumentList;
- import org.apache.solr.common.SolrInputDocument;
- import com.jadyer.model.MyMessage;
- /**
- * 【Lucene3.6.2入門系列】第14節_SolrJ操作索引和搜索文檔以及整合中文分詞
- * @see -------------------------------------------------------------------------------------------------------------------------
- * @see 通過schema.xml使得Solr與中文分詞進行整合
- * @see 0)默認solr定義的大量域都不支持中文分詞,如果我們要加中文分詞的支持,那麼首先要加的就是<types><fieldType/></types>
- * @see 下面以MMSeg4j-1.8.5爲例,描述Solr與中文分詞器的整合方式(其核心就是在schema.xml中配置fieldType)
- * @see 關於MMSeg4j的介紹,詳見http://blog.csdn.net/jadyer/article/details/10049525
- * @see 1)將mmseg4j-all-1.8.5.jar拷到D:\Develop\apache-solr-3.6.2\server\solr\WEB-INF\lib\文件夾中
- * @see 2)新建D:\Develop\apache-solr-3.6.2\home\dic\文件夾
- * @see 3)將mmseg4j-1.8.5.zip\data\文件夾中的詞典文件拷貝到D:\Develop\apache-solr-3.6.2\home\dic\
- * @see 4)在schame.xml中添加中文分詞的fieldType定義
- * @see 通常中文分詞的工具包中都會提供README.txt文件,裏面會描述擴展solr時需要配置的fieldType
- * @see 同理將mmseg4j-1.8.5.zip中的README.txt打開,拷貝里面描述的三個fieldType到schema.xml中第68行
- * @see 5)確認並修改這三個fileType中的dicPath屬性值爲"dic"(這裏的dic其實指的就是第二步新建的dic文件夾)
- * @see 6)最後測試一下中文分詞效果
- * @see 在solr控制檯上(http://127.0.0.1:8088/solr/admin/)點擊藍色粗體的[ANALYSIS]
- * @see 然後在Field Analysis下面將Field下拉框修改爲type,並在右面文本框輸入text_general(即schema.xml中定義的fieldType)
- * @see 接着在Field Value(Index)右面的文本框中輸入測試文本'我來自中國黑龍江省哈爾濱市巴彥縣興隆鎮長春鄉民權村4隊'
- * @see 再點擊下方的Analyze按鈕,我們就會發現text_general的分詞情況了,然後我們再修改text_general爲剛纔自定義的textComplex,就看到效果啦
- * @see 另外也可以勾選Field Value(Index)下面的verbose output選框,這樣也會將分詞的各個屬性(position,Offset,type等等)一併顯示出來
- * @see -------------------------------------------------------------------------------------------------------------------------
- * @see 本例中合計用到9個jar,如下所示
- * @see apache-solr-core-3.6.2.jar
- * @see apache-solr-solrj-3.6.2.jar
- * @see commons-codec-1.6.jar
- * @see commons-io-2.1.jar
- * @see httpclient-4.1.3.jar
- * @see httpcore-4.1.4.jar
- * @see httpmime-4.1.3.jar
- * @see jcl-over-slf4j-1.6.1.jar
- * @see slf4j-api-1.6.1.jar
- * @see -------------------------------------------------------------------------------------------------------------------------
- * @create Aug 7, 2013 11:06:20 PM
- * @author 玄玉<http://blog.csdn.net/jadyer>
- */
- public enum HelloSolrJ {
- INSTANCE;
- private SolrServer server;
- private HelloSolrJ(){
- //創建SolrServer對象,它有兩個線程安全的子類EmbeddedSolrServer和CommonsHttpSolrServer
- //EmbeddedSolrServer-----內嵌式的,不需要啓動Web服務器
- //CommonsHttpSolrServer--需要啓動Web服務器,它是通過HTTP請求來獲取數據的
- //CommonsHttpSolrServer已不推薦直接使用了,而是推薦使用HttpSolrServer類
- //同樣的StreamingUpdateSolrServer也不推薦使用了,推薦使用ConcurrentUpdateSolrServer
- server = new HttpSolrServer("http://127.0.0.1:8088/solr");
- }
- /**
- * 刪除全部索引
- */
- public void deleteAllIndex(){
- try {
- //刪除所有的索引,刪除完記得commit才能生效
- server.deleteByQuery("*:*");
- server.commit();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- /**
- * 添加索引
- * @see 這裏之所以沒有硬編碼指定my_title和my_content的中文分詞器
- * @see 是由於schema.xml中在定義這倆<field>時已通過type屬性指定了中文分詞器
- */
- public void addIndex(){
- List<SolrInputDocument> docs = new ArrayList<SolrInputDocument>();
- for(int i=1; i<4; i++){
- SolrInputDocument doc = new SolrInputDocument();
- //對於Solr而言,默認的id是唯一的主鍵(如果我們沒有自定義主鍵的話),當多次添加的時候,最後添加的相同id的域會覆蓋已有的
- doc.addField("id", Integer.toString(i));
- //這裏使用的是自定義的Field,所以就需要在schema.xml中爲其添加<field>描述,並通過type屬性指定其使用的分詞器
- doc.addField("my_title", "這是我的第" + i + "個SolrJ程序");
- doc.addField("my_content", "my第" + i + "個SolrJ程序的運行情況");
- docs.add(doc);
- }
- try {
- //可以只添加一個Document,也可以一次添加多個Document,這裏添加多個
- server.add(docs);
- //commit後方能生效,否則搜索到的還是add前的索引信息
- server.commit();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- /**
- * 使用JavaBean來添加索引
- */
- public void addIndexByBean(){
- List<MyMessage> msgs = new ArrayList<MyMessage>();
- //由於MyMessage()的第三個參數允許傳入多個值,此時就要在Solr的schema.xml中配置<field my_content multiValued="true"/>支持多值域
- //並且在MyMessage.java中要使用@Field註解標註,可以標註在屬性或setter方法上,並通過註解的默認值來指定所要存儲的Field的名字
- msgs.add(new MyMessage("4", "這是我的第4個SolrJ程序", new String[]{"第4個SolrJ程序誕生於中國", "它是通過SolrJ OF JavaBean4誕生添加的"}));
- msgs.add(new MyMessage("5", "這是我的第5個SolrJ程序", new String[]{"第5個SolrJ程序誕生於哈爾濱", "它是通過SolrJ OF JavaBean5誕生添加的"}));
- try {
- server.addBeans(msgs);
- server.commit();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- /**
- * 搜索文檔
- */
- public void searchFile(){
- //設置查詢字符串
- SolrQuery query = new SolrQuery("my_content:誕生");
- //設置了setStart和setRows就可以實現分頁效果了
- query.setStart(0);
- query.setRows(3);
- QueryResponse resp = null;
- try {
- resp = server.query(query);
- } catch (SolrServerException e) {
- e.printStackTrace();
- }
- //搜索出來的結果都保存在SolrDocumentList中
- SolrDocumentList sdl = resp.getResults();
- //這裏獲取到的是搜索到的總數量,與query.setRows(3)無關
- System.out.println("本次搜索到[" + sdl.getNumFound() + "]條數據");
- for(SolrDocument sd : sdl){
- //System.out.println(sd)會輸出SolrDocument[{id=4, my_title=這是我的第4個SolrJ程序, my_content=[第4個....於中國, 它是....進來的]}]
- System.out.println("my_title=" + sd.getFieldValue("my_title") + " my_content=" + sd.getFieldValue("my_content"));
- }
- }
- /**
- * 使用JavaBean接收文檔搜索結果
- */
- public void searchFileByBean(){
- SolrQuery query = new SolrQuery("id:*");
- query.setStart(0);
- query.setRows(3);
- QueryResponse resp = null;
- try {
- resp = server.query(query);
- } catch (SolrServerException e) {
- e.printStackTrace();
- }
- List<MyMessage> list = resp.getBeans(MyMessage.class);
- //這裏獲取到的不是搜索到的總數量,而是與query.setRows(3)有關的值
- //若實際的SolrQuery("id:*")能搜索到5條,則這裏得到的就是3,若實際能搜索到的是2條,則這裏得到的就是2條
- System.out.println("本次搜索到[" + list.size() + "]條數據");
- for(MyMessage msg : list) {
- System.out.println(msg.getTitle() + " " + msg.getContent()[0]);
- }
- }
- }
下面是用到的JavaBean類
- package com.jadyer.model;
- import org.apache.solr.client.solrj.beans.Field;
- public class MyMessage {
- @Field
- private String id;
- @Field("my_title")
- private String title;
- @Field("my_content")
- private String[] content;
- /*-- 三個屬性的setter和getter略 --*/
- public MyMessage() {}
- public MyMessage(String id, String title, String[] content) {
- this.id = id;
- this.title = title;
- this.content = content;
- }
- }
最後是JUnit4.x寫的一個小測試
- package com.jadyer.test;
- import org.junit.Test;
- import com.jadyer.solrj.HelloSolrJ;
- public class HelloSolrJTest {
- @Test
- public void deleteAllIndex(){
- HelloSolrJ.INSTANCE.deleteAllIndex();
- }
- @Test
- public void addIndexAndSearchFile(){
- HelloSolrJ.INSTANCE.addIndex();
- HelloSolrJ.INSTANCE.searchFile();
- }
- @Test
- public void addIndexAndSearchFileByBean(){
- HelloSolrJ.INSTANCE.addIndexByBean();
- HelloSolrJ.INSTANCE.searchFileByBean();
- }
- }