快速入門全文搜尋服務 -- 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”,只會對”蘋果“兩字進行高亮處理。
例:
但是數字達到兩位,它進行分詞了,如下
非常感謝大家閱讀我的部落格。