1. 程式人生 > >快速入門全文搜尋服務 -- solr 7.4.0 (有java的增刪改查程式碼)

快速入門全文搜尋服務 -- solr 7.4.0 (有java的增刪改查程式碼)

solr圖示簡介

在這裡插入圖片描述

看了上面的圖示介紹,你可能會問,那資料庫在solr中有什麼用呢?是不是有了solr的索引庫我們就不需要建立索引庫了呢?

其實不然
第一,資料庫可以作為索引庫資料的備份,當索引庫損壞時,可以將資料庫中的資料匯入到索引庫中。
第二,當你要升級solr的版本,這時候原來的索引庫已經不能夠相容solr新的版本了,怎麼辦?沒錯,從資料庫中匯入。

在tomcat上部署solr

[solr下載](http://lucene.apache.org/solr/mirrors-solr-latest-redir.html)
下載solr後我們可以看到它的目錄結構

這裡寫圖片描述

solr內建了一個jetty伺服器,我們不使用它,使用tomcat伺服器。



(1)複製solr-7.4.0/server/solr-webapp目錄下的webapp檔案複製到一個tomcat伺服器的webapp目錄下,並且重新命名為solr。(目的是將solr專案釋出)
這裡寫圖片描述

這裡寫圖片描述

(2)接下來,將solr-7.4.0/server/lib下以m開頭的jar、gmetric4j-1.0.7.jar包和ext下所有的包拷貝到tomcat的webapps/solr/WEB-INF/lib下
這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述


(3)拷貝solr-7.4.0/server/resources下的log4j2.xml到webapps/solr/WEB-INF目錄下的classes(沒有classes檔案就建立一個) 注:步驟3、6、9、10是配置solr的日誌,不做也可

這裡寫圖片描述
這裡寫圖片描述



(4)複製solr-7.4.0/server/下的solr到任意地方,並取名solr_home(取名任意),這是存放索引庫的地方。並在tomcat中webapp/solr/WEB-INF/web.xml中配置solr_home的路徑,開啟web.xml,在第41行找到並解開<env-entry>

的註釋,並配置<env-entry-value>為你自己的solr_home路徑。

<env-entry>
	<env-entry-name>solr/home</env-entry-name>
	<env-entry-value>D:/csdn/solr/solr_home</env-entry-value>
	<env-entry-type>java.lang.String</env-entry-type>
</env-entry>




(5)然後翻到web.xml的最後幾行程式碼,註釋掉他們,取消許可權控制。
這裡寫圖片描述





(6)複製solr-7.4.0目錄下的contrib和dist到solr_home下。(配置日誌)
這裡寫圖片描述



(7)在solr_home目錄下建立一個資料夾(它對應資料庫中的表),名字任意,這裡我們取名為goods。然後將configsets/_default下的conf資料夾複製到新建的goods資料夾下,並在goods目錄下建立資料夾data。

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述



(8)然後再在goods目錄下建立檔案core.properties,內容為name=goods
這裡寫圖片描述



(9)開啟tomcat下bin目錄的catalian.bat,在206行的程式碼塊最後新增一行程式碼。(配置日誌)
這裡寫圖片描述

if not "%JSSE_OPTS%" == "" goto gotJsseOpts
set JSSE_OPTS="-Djdk.tls.ephemeralDHKeySize=2048"
:gotJsseOpts
set "JAVA_OPTS=%JAVA_OPTS% %JSSE_OPTS%" 
-- 下面一行是新增的,D:\csdn\solr\solr_home\log為你存放日誌的路徑
set "JAVA_OPTS=%JAVA_OPTS% -Dsolr.log.dir=D:\csdn\solr\solr_home\log" 




(10)將solr_home/goods/conf下的solrconfig.xml的第76到86行改為:(可以註釋掉再新增)(配置日誌)

<lib dir="${solr.install.dir:../}/contrib/extraction/lib" regex=".*\.jar" />  
<lib dir="${solr.install.dir:../}/dist/" regex="solr-cell-\d.*\.jar" />  

<lib dir="${solr.install.dir:../}/contrib/clustering/lib/" regex=".*\.jar" />  
<lib dir="${solr.install.dir:../}/dist/" regex="solr-clustering-\d.*\.jar" />  

<lib dir="${solr.install.dir:../}/contrib/langid/lib/" regex=".*\.jar" />  
<lib dir="${solr.install.dir:../}/dist/" regex="solr-langid-\d.*\.jar" />  

<lib dir="${solr.install.dir:../}/contrib/velocity/lib" regex=".*\.jar" />  
<lib dir="${solr.install.dir:../}/dist/" regex="solr-velocity-\d.*\.jar" />  
    
<lib dir="${solr.install.dir:../}/dist/" regex="ojdbc\d.*\.jar" />  
<lib dir="${solr.install.dir:../}/dist/" regex="solr-dataimporthandler\d.*\.jar" />  

下圖是要被修改的地方
這裡寫圖片描述



(11)然後雙擊tomcat中bin下的startup.bat檔案,啟動tomcat伺服器,然後在瀏覽器中輸入網址http://127.0.0.1:8080/solr/index.html 即可訪問solr的管理介面。

這裡寫圖片描述

solr管理介面簡介

![這裡寫圖片描述](https://img-blog.csdn.net/20180916095538853?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzMTU4NDM2/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)

這裡寫圖片描述

這裡寫圖片描述

索引表字段的新增以及匯入資料庫中的資料到索引表

(1)我們首先看看資料庫中表的欄位

這裡寫圖片描述



(2)然後我們給goods索引表配備分詞器,並新增欄位。先下載ik分詞器(智慧分詞,很好用)連結:https://pan.baidu.com/s/1mirMgX_Dl8u6jNZCnvhp0Q 密碼:t9x7。
將ik分詞器的jar包放入tomcat的webapps/solr/WEB-INF/lib下。



(3)開啟solr_home\goods\conf下的managed-schema檔案,我們可以看到113行已經有4個預設欄位了,其中包含id。
這裡寫圖片描述

我們在下面新增一些配置

<!-- 配置ik分詞器 -->
<fieldType name="text_ik" class="solr.TextField">
	<analyzer type="index">
		<tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="false" conf="ik.conf"/>
		<filter class="solr.LowerCaseFilterFactory"/>
	</analyzer>
	<analyzer type="query">
		<tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="true" conf="ik.conf"/>
		<filter class="solr.LowerCaseFilterFactory"/>
	</analyzer>
</fieldType>
<!-- 配置欄位 -->
<field name="name" type="text_ik" indexed="true" stored="true" multiValued="false" />
<field name="price" type="pdouble" indexed="false" stored="true" multiValued="false" />
<field name="manufacturer" type="text_ik" indexed="true" stored="true" multiValued="false" />

其中,filed的type如果填寫配置的分詞器的name,就可以使用該分詞器分詞,如果是string、plong、pdouble就不能被分詞,indexed選項是是否建立索引,建立索引後就能被分詞搜尋,stored是是否儲存該資料,multiValued是是否支援多值。

然後我們重啟tomcat後進入管理介面就可以看到我們建立的欄位了。
這裡寫圖片描述

我們選擇type下的text_ik分詞器,然後在左邊的輸入框輸入四川成都有什麼好玩的地方,可以看到這一句話被分詞器分詞了。
這裡寫圖片描述



(4)從資料庫中匯入資料到索引庫。
將mysql的驅動mysql-connector-java-5.1.37-bin.jar與solr-7.4.0/dist中的solr-dataimporthandler-7.4.0.jar和solr-dataimporthandler-extras-7.4.0.jar放入apache-tomcat-8.5.27\webapps\solr\WEB-INF\lib下。

這裡寫圖片描述



(5)將solr-7.4.0/example/example-DIH/solr/db/conf下的db-data-config.xml複製到solr_home/goods/conf下。
這裡寫圖片描述

這裡寫圖片描述

並將裡面的內容改為

<dataConfig>
    <dataSource type="JdbcDataSource"
				 driver="com.mysql.jdbc.Driver" 
				 url="jdbc:mysql://127.0.0.1:3306/test"
				 user="root"
				 password="root" />
	<document>
		<entity name="goods" 
				query="select id,name,price,manufacturer from goods">
		</entity>
	</document>
</dataConfig>




(6)開啟該目錄下的solrconfig.xml檔案,
這裡寫圖片描述

在1000行左右,新增如下配置,要與<requestHandler>標籤同級

  <requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
	<lst name="defaults">
		<str name="config">db-data-config.xml</str>
	</lst>
  </requestHandler>




(7)重啟tomcat,進入官網,選擇goods索引表,點選Dataimport,然後選擇匯入的資料庫表名字,最後點選Excute,然後重新整理一下就(Refresh Status)ok了。

這裡寫圖片描述

資料庫中的資料

這裡寫圖片描述

匯入資料庫後,查詢索引表,可以看到有4條資料了

這裡寫圖片描述


程式碼實現(solrj)solr的增刪改查以及查詢結果高亮顯示

(1)首先建立一個java project工程,匯入jar包。將solr-7.4.0/dist中solrj-lib資料夾下的所有jar包與solr-solrj-7.4.0.jar複製到工程lib資料夾下,並build path。

這裡寫圖片描述



工程目錄結構
這裡寫圖片描述



(2)實體類

public class Goods {
	private int id;
	private String name;
	private double price;
	private String manufacturer;
	
	// 無參有參構造方法
	// getter setter
	// 重寫toString方法
}




(3)GoodsSolrDao中的增加或更新方法

	/**
	 * id不重複則增加,有相同的則更新
	 */
	public void insertOrUpdate(Goods goods) {
        // 建立solrClient同時指定超時時間
        HttpSolrClient client = new HttpSolrClient.Builder("http://127.0.0.1:8080/solr/goods").withConnectionTimeout(10000).build();

        // 建立文件doc
        SolrInputDocument doc = new SolrInputDocument();
        
        // 新增內容
        doc.addField("id", goods.getId());
        doc.addField("name", goods.getName());
        doc.addField("price", goods.getPrice());
        doc.addField("manufacturer", goods.getManufacturer());
        
        // 新增到client,並且提交(commit)
        try {
			client.add(doc);
			client.commit();
		} catch (SolrServerException | IOException e) {
			e.printStackTrace();
		}
	}

TestGoodsSolrDao中的測試方法–測試增加,啟動tomcat,執行測試方法

	@Test
	public void testInsertOrUpdate() {
		GoodsSolrDao goodsSolrDao = new GoodsSolrDao();
		Goods goods = new Goods(5, "vivo max3 A", 1800, "vivo");
		goodsSolrDao.insertOrUpdate(goods);
	}

結果,增加成功
這裡寫圖片描述

TestGoodsSolrDao中的測試方法–測試更新(id相同則更新)

	@Test
	public void testInsertOrUpdate1() {
		GoodsSolrDao goodsSolrDao = new GoodsSolrDao();
		Goods goods = new Goods(5, "vivo X23", 3498, "vivo");
		goodsSolrDao.insertOrUpdate(goods);
	}

結果,更新成功
這裡寫圖片描述



(4)GoodsSolrDao中的刪除方法

	/**
	 * 刪除索引
	 */
	public void delete(int id) {
  	  // 獲取連線
  	  HttpSolrClient client = new HttpSolrClient.Builder("http://127.0.0.1:8080/solr/goods").withConnectionTimeout(10000).build();
      try {
    	  // 通過id刪除
    	  client.deleteById(String.valueOf(id));
	      // 提交
	      client.commit();
	      // 關閉資源
	      client.close();
      } catch (SolrServerException | IOException e) {
		e.printStackTrace();
      }
	}

TestGoodsSolrDao中的測試方法,啟動tomcat,執行測試方法

	@Test
	public void testDelete() {
		GoodsSolrDao goodsSolrDao = new GoodsSolrDao();
		goodsSolrDao.delete(5);
	}

結果,刪除成功
這裡寫圖片描述



(5)GoodsSolrDao中的根據關鍵字name查詢的方法

	/**
	 * @param keyWord 搜尋的關鍵句子
	 * @param isHighLight 是否返回高亮物件列表,true則返回高亮物件列表,
	 *	  false返回普通物件列表
	 * @return List<Goods>
	 */
	public List<Goods> search(String keyWord, boolean isHighLight){
    	//建立solrClient同時指定超時時間
		HttpSolrClient client = new HttpSolrClient.Builder("http://127.0.0.1:8080/solr/goods").withConnectionTimeout(10000).build();
		
		// 建立SolrQuery,查詢時用到
		SolrQuery solrQuery = new SolrQuery();
		// 設定關鍵詞
		solrQuery.setQuery(keyWord);
		// 過濾條件 
		//solrQuery.set("fq", "price:[0 TO 5000]");// "price:[10 TO *]"
		// 分頁
		//solrQuery.setStart(0);
		//solrQuery.setRows(16);
		// 預設搜尋欄位
		solrQuery.set("df", "name");
		// 只查詢指定域 相當於select id,name,price,manufacturer from goods.
		solrQuery.set("fl", "id,name,price,manufacturer");
		// 開啟高亮開關
		solrQuery.setHighlight(true);
		// 指定高亮域
		solrQuery.addHighlightField("name");
		// 關鍵詞字首
		solrQuery.setHighlightSimplePre("<font color='red'>");
		// 關鍵詞字尾
		solrQuery.setHighlightSimplePost("</font>");

		// 執行查詢
		QueryResponse response = null;
		try {
			response = client.query(solrQuery);
		} catch (SolrServerException | IOException e) {
			e.printStackTrace();
		}
		// 普通結果集
		SolrDocumentList docs = response.getResults();
		
        // 獲取高亮結果集
		// 1.Map<String, Map<String, List<String>>>的key是id,
		//   value是查詢到的資料
		// 2.Map<String, List<String>>的key是欄位名,value是值,
		//   如果支援多值,它的值就是集合,不支援值就是該集合的第一個元素
		Map<String, Map<String, List<String>>> highlighting = response.getHighlighting();
		
		// 總條數
		long totalNum = docs.getNumFound();
		System.out.println("totalNum:"+totalNum);
		
		// 普通查詢物件列表
		List<Goods> goods = new ArrayList<Goods>();
		// 高亮查詢物件列表
		List<Goods> highLightGoods = new ArrayList<Goods>();
		//遍歷結果集
		for (SolrDocument doc : docs) {
			Goods _good = new Goods();
			Goods _highLightGood = new Goods();
			
			// 設定普通結果到_good中
			_good.setId(Integer.valueOf((String)doc.get("id")));
			_good.setName((String)doc.get("name"));
			_good.setPrice((double)doc.get("price"));
			_good.setManufacturer((String)doc.get("manufacturer"));
			
			// 設定高亮結果到_highLightGood中
			// 得到該條資料
			Map<String, List<String>> map = 
			  highlighting.get((String)doc.get("id"));
			// 設定各個欄位 不支援多值的欄位,
			//   其值就是List<String>中的第一個值
			// 如果被搜尋的欄位不包含搜尋的關鍵字,則會被置為空,
			//   所以需要判定是否為空,為空則使用普通結果
			_highLightGood.setId(_good.getId());
			String name = map.get("name").get(0);
			_highLightGood.setName(name == null ? _good.getName() : name);
			_highLightGood.setPrice(_good.getPrice());
			_highLightGood.setManufacturer(_good.getManufacturer());
			
			// 將_good與_highLightGood分別新增到普通物件劉表與高亮物件列表中
			goods.add(_good);
			highLightGoods.add(_highLightGood);
		}
		// isHighLight為真,返回高亮物件列表,否則返回普通結果物件列表
		if(isHighLight) {
			return highLightGoods;
		}else {
			return goods;
		}
	}

TestGoodsSolrDao中的測試方法,啟動tomcat,執行測試方法

	@Test
	public void testSearch() {
		GoodsSolrDao goodsSolrDao = new GoodsSolrDao();
		List<Goods> goods = goodsSolrDao.search("蘋果", true);
		System.out.println(goods);
	}

結果
這裡寫圖片描述

我們可以看到,solr對要搜尋的欄位name中的“蘋果”進行了高亮處理。
但是有一點我要提醒下大家,ik不會對1個數字進行分詞,你搜索“蘋果8”,只會對”蘋果“兩字進行高亮處理。
例:
這裡寫圖片描述

但是數字達到兩位,它進行分詞了,如下
這裡寫圖片描述



非常感謝大家閱讀我的部落格。