javascript
Solr及Spring-Data-Solr入门学习
2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
Solr的安裝與配置
多數(shù)搜索引擎應(yīng)用都必須具有某種搜索功能,而搜索功能往往大量的消耗資源導(dǎo)致應(yīng)用程序運(yùn)行緩慢。為此,出現(xiàn)了各種用于構(gòu)建搜索的應(yīng)用程序,我們要學(xué)習(xí)的solr正是其中的一款開源搜索平臺(tái)。
Apache Solr 是建立在Lucene(全文搜索引擎)之上,幫助我從大量的數(shù)據(jù)中尋找所需信息。不僅限于搜索,Solr也可用于儲(chǔ)存目的。像其他NoSQL數(shù)據(jù)庫(kù)一樣,它是一種非關(guān)系數(shù)據(jù)儲(chǔ)存和處理技術(shù)。
<!--more-->
下面我們開始喜聞樂見的手摸手教學(xué),教你優(yōu)雅的整合SSM框架和Solr搜索框架。
- 項(xiàng)目開源地址: Github
項(xiàng)目中使用了SSM + Shiro + Redis + Solr + Vue.JS + ElementUI技術(shù),優(yōu)雅的整合了SSM框架階段幾個(gè)常見的企業(yè)框架;并用Vue.js + ElementUI寫了超漂亮的前端頁(yè)面;如果覺得可以,就點(diǎn)亮右上角star吧(#^.^#)。
如果你對(duì)Shiro+用戶-角色-權(quán)限整合不是很懂,你或許可以看下我的這個(gè)項(xiàng)目: 手摸手教你SSM整合Shiro框架后的開發(fā)。
日常學(xué)習(xí)記錄,如果想支持我,希望能在Github上看到你點(diǎn)亮的星星(#^.^#)。
<br/>
- 本例中使用的Solr和Tomcat我已經(jīng)上傳到了Github,倉(cāng)庫(kù)地址: Tomcat搭建Solr運(yùn)行環(huán)境,集成Ik 中文分詞器
<br/>
安裝
在 Apache Solr官網(wǎng) 下載最新版的Solr,在 Apache Tomcat官網(wǎng) 下載Tomcat。
解壓solr,發(fā)現(xiàn)其中有如下目錄結(jié)構(gòu)
新版本的Solr和老版本的不同,老版本中直接提供的是war文件,新版本則是提供了直接可運(yùn)行的項(xiàng)目;其次需要導(dǎo)入項(xiàng)目中的的文件也有所不同的。下面我們介紹一下完整的配置和Solr項(xiàng)目的啟動(dòng):
- 1、將solr-7.4.0/server/solr-webapp/下的webapp文件夾拷貝到Tomcat下的webapps目錄下(并重命名為solr)。
- 2、將solr-7.4.0/server/lib/ext/下的所有Jar文件全部拷貝到Tomcat下webapps/solr/WEB-INF/lib目錄下。
- 3、將solr-7.4.0/server/lib下所有metrics開頭的jar文件全部拷貝到webapps/solr/WEB-INF/lib目錄下。
- 4、將solr/7.4.0/server/solr文件夾復(fù)制到任意一個(gè)位置并重命名為solrhome。
- 5、修改tomcat/webapps/solr/WEB-INF/web.xml文件的第41行,指定solrhome所在的目錄。
- 6、在webapps/solr/WEB-INF/web.xml下的第125行出添加注釋,也就是注釋<security-constraint></secirity-constraint>節(jié)點(diǎn)下的配置。
- 7、啟動(dòng)Tomcat,在瀏覽器中訪問http://localhost:8080/solr/index.html即可訪問到solr Admin
如上所示,你會(huì)發(fā)現(xiàn)其左下角顯示的是No cores,這和老版本的可能又有所差別,所以我們點(diǎn)擊No cores,創(chuàng)建一個(gè)新的cores,那么會(huì)在我們指定的solrhome文件夾內(nèi)產(chǎn)生一個(gè)new_core的空文件夾,并且頁(yè)面會(huì)報(bào)錯(cuò):Can't find resource 'solrconfig.xml' in xxx,表示的就是在這個(gè)新core下的conf文件夾下沒有找到solrconfig.xml文件:
我們需要將復(fù)制來的configsets/_default/conf這個(gè)文件夾(或者solr-7.4.0/server/solr/configsets/_default/conf文件夾)復(fù)制到solrhome/new_core/文件夾下。
- 8、重啟Tomcat服務(wù)器,發(fā)現(xiàn)還是沒有出現(xiàn)新的core,點(diǎn)擊No cores那里點(diǎn)擊add core,此時(shí)就會(huì)完整的創(chuàng)建一個(gè)新的core,在solrhome/new_core文件夾下會(huì)生成新的文件:
- 至此Solr已經(jīng)安裝完成。
<br/>
中文分詞器
上面我們成功的安裝了solr,下面就要進(jìn)行相關(guān)的配置。因?yàn)閟olr是一個(gè)開源的搜索平臺(tái),主要功能就是把用戶輸入的搜索信息分類匯總并進(jìn)行數(shù)據(jù)庫(kù)的查詢,而中文眾所周知語(yǔ)義比較復(fù)雜,而且中文所占的字節(jié)和英文也有所不同,所以就出現(xiàn)了中文分詞器,實(shí)現(xiàn)模擬中文語(yǔ)義對(duì)數(shù)據(jù)進(jìn)行分詞衍化。IK Analyzer正是其中的一種分詞器。
IK Analyzer在solr工程中的配置如下:
- 1、下載ikanalyzer相關(guān)配置文件,因?yàn)镸aven倉(cāng)庫(kù)中的ikanalyzer版本太老,solr5以上的版本都不支持,所以這里提供一個(gè)新版本: 傳送門
- 2、將下載的jar文件copy到webapps/solr/WEB-INF/lib文件夾下
- 3、在webapps/solr/WEB-INF/下創(chuàng)建classes文件夾,將上面下載的文件夾中的ext.dic、IKAnalyzer.cfg.xml、stopword.dic三個(gè)文件復(fù)制到webapps/solr/WEB-INF/classes/文件夾下。
- 4、在solrhome/conf/目錄下我們發(fā)現(xiàn)并沒有schema.xml文件,這和老版本又有所不同,老版本直接生成好了schema.xml文件,在新版本中我們可以發(fā)現(xiàn)/conf文件夾中存在一個(gè)managed-schema文件,這個(gè)其實(shí)就是我們要的schema.xml文件。但是我們又不能直接用,具體原因參考 博文
- 5、直接將managed-schema文件重命名為schema.xml。并在schema.xml的最后添加<fieldType>節(jié)點(diǎn):
- 6、重啟Tomcat服務(wù)器,重新訪問項(xiàng)目,點(diǎn)擊new_core下的Schema功能,在select下拉框中輸入text_ik如果出現(xiàn)剛創(chuàng)建的text_ik,說明IK中文分詞器安裝成功。
測(cè)試
未使用分詞器效果:
使用了分詞器的效果顯而易見:
<br>
配置域
solr和其他NoSQL數(shù)據(jù)庫(kù)一樣可以實(shí)現(xiàn)數(shù)據(jù)存儲(chǔ),所以我們可以以數(shù)據(jù)庫(kù)的思想想象一下solr,之前我們新創(chuàng)建的core就類似一個(gè)數(shù)據(jù)庫(kù),那么下面要配置的域就相當(dāng)于數(shù)據(jù)庫(kù)的表字段,因此要手動(dòng)的去定義系統(tǒng)中需要的字段Field(域)。
通常我們創(chuàng)建的一種Field分別對(duì)應(yīng)這一類數(shù)據(jù),用戶對(duì)同一種數(shù)據(jù)進(jìn)行相同的操作。域常用的屬性有:
- name: 指定域的名稱
- type: 指定域的類型
- indexed: 是否索引
- stored: 是否儲(chǔ)存
- required: 是否必須
- multiValued: 是否多值
域的介紹
如上面的介紹,域類似數(shù)據(jù)庫(kù)中的表字段,而我們做項(xiàng)目時(shí)數(shù)據(jù)庫(kù)的字段都是根據(jù)項(xiàng)目需求創(chuàng)建的,所以域也是如此,它是根據(jù)搜索平臺(tái)需要搜索的信息對(duì)應(yīng)的數(shù)據(jù)庫(kù)表字段來創(chuàng)建的。
比如,在淘寶商城購(gòu)買商品,我們可能會(huì)搜索:1、品牌(對(duì)應(yīng)數(shù)據(jù)庫(kù)中brand字段);2、價(jià)格(對(duì)應(yīng)數(shù)據(jù)庫(kù)中price字段);3、商品介紹名稱(對(duì)應(yīng)數(shù)據(jù)庫(kù)中title字段)等等...
每一中域(字段)都用<field>字段設(shè)定,比如如上的搜索數(shù)據(jù),我們可以設(shè)置為:
<field name="item_title" type="text_ik" indexed="true" stored="true"/> <field name="item_price" type="pdouble" indexed="true" stored="true"/> <field name="item_image" type="string" indexed="false" stored="true" /> <field name="item_category" type="string" indexed="true" stored="true" /> <field name="item_seller" type="text_ik" indexed="true" stored="true" /> <field name="item_brand" type="string" indexed="true" stored="true" />在新版本的solr中,type屬性不能單單設(shè)置為基本的數(shù)據(jù)類型名稱了,具體用法要參考schema.xml文件中之前已存在的配置,例如:long要寫成plong,double要寫為pdouble,不然就會(huì)報(bào)錯(cuò)。
注意:
-
你會(huì)奇怪域的設(shè)定不就是根據(jù)用戶搜索的數(shù)據(jù)分類來設(shè)定的嗎,那為何還要指定indexed="true",原因:可能有些數(shù)據(jù)是不是用戶輸入的查詢的,但是還是需要在用戶搜索的同時(shí)檢索出來。
-
你會(huì)奇怪為何要設(shè)定stored,原因:大多數(shù)域都是要進(jìn)行存儲(chǔ)的,但是也有不需要存儲(chǔ)的,比如復(fù)制域。
復(fù)制域
復(fù)制域的作用在于將某一個(gè)Field中的數(shù)據(jù)復(fù)制到另一個(gè)域中。 由于用戶輸入的數(shù)據(jù)可能是查詢的價(jià)格,也可能是商品的title,又或者是商品的品牌等... 我們無法預(yù)測(cè)用戶要查詢的是什么,由此出現(xiàn)了搜索引擎平臺(tái),幫助我們對(duì)查詢數(shù)據(jù)進(jìn)行分類。 所以,solr的目標(biāo)是實(shí)現(xiàn)兩種不同的域可以在同一個(gè)域中查詢(發(fā)送一次請(qǐng)求),而復(fù)制域的出現(xiàn)正可解決這一問題。
如此,我們?yōu)樯厦嬉樵兊淖侄卧O(shè)定復(fù)制域:
<field name="item_keywords" type="text_ik" indexed="true" stored="false" multiValued="true"/> <copyField source="item_title" dest="item_keywords"/> <copyField source="item_category" dest="item_keywords"/> <copyField source="item_seller" dest="item_keywords"/>其中的source屬性值要和<field>中的name保持一致。
動(dòng)態(tài)域
在項(xiàng)目中,商品的數(shù)據(jù)可能會(huì)動(dòng)態(tài)的添加或減少,比如原來沒有的數(shù)據(jù),但是后來又完善添加上去了,那么就需要?jiǎng)討B(tài)的配置從而實(shí)現(xiàn)用戶能及時(shí)查詢到。
<dynamicField name="item_conf_*" type="string" indexed="true" stored="true"><br/>
Spring Data Solr入門
經(jīng)過上面的安裝和配置大家應(yīng)該已經(jīng)知道如何配置Solr,那么就會(huì)思考一個(gè)問題了:這個(gè)solr項(xiàng)目和我們實(shí)際的項(xiàng)目查詢有什么關(guān)系呢?是怎么結(jié)合的呢?
solr官方提供了solrj API,就是一個(gè)jar文件,我們可以通過solr官方提供的接口來實(shí)現(xiàn)本地項(xiàng)目和solr項(xiàng)目的交互;而這里我們要介紹的是Spring Data Solr,它是Spring Data家族對(duì)solrj進(jìn)行封裝后的框架。
- 注意 上面我們?cè)赥omcat中部署的solr項(xiàng)目是不需要再進(jìn)行位置上的變動(dòng)的,也就是他必須是已經(jīng)在Tomcat中部署好的,而我們自己的項(xiàng)目啟動(dòng)時(shí)不能再使用8080端口(因?yàn)閟olr本身就占用了Tomcat的端口,而我們的項(xiàng)目是可以改變運(yùn)行端口的,總之兩者無論是不是在同一個(gè)Tomcat服務(wù)器中部署都不能使用同一端口)。我們通過配置文件就能訪問到這個(gè)指定端口的solr項(xiàng)目(Tomcat必須是啟動(dòng)著的),通過Spring Data Solr提供的接口就能實(shí)現(xiàn)交互: 所謂交互 --> 等價(jià)于查詢solr中以存在的數(shù)據(jù),然后將結(jié)果返回:
- 用戶查詢,請(qǐng)求接口將查詢條件交給solr(通過Spring Data Solr提供的接口訪問Solr服務(wù)),solr對(duì)自身已存在的數(shù)據(jù)進(jìn)行查找
準(zhǔn)備
導(dǎo)入jar文件
<dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-solr</artifactId><version>1.5.5.RELEASE</version> </dependency>創(chuàng)建配置文件
既然是Spring家族的框架,當(dāng)然要進(jìn)行配置使用了,創(chuàng)建spring-solr.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:solr="http://www.springframework.org/schema/data/solr"xsi:schemaLocation="http://www.springframework.org/schema/data/solrhttp://www.springframework.org/schema/data/solr/spring-solr-1.0.xsdhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- solr服務(wù)器地址 --><solr:solr-server id="solrServer" url="http://127.0.0.1:8080/solr/new_core"/><!-- solr模板,使用solr模板可對(duì)索引庫(kù)進(jìn)行CRUD的操作 --><bean id="solrTemplate" class="org.springframework.data.solr.core.SolrTemplate"><constructor-arg ref="solrServer"/></bean> </beans>- 注意:
一定要注意solr配置中solr服務(wù)器地址的配置,這個(gè)url一定是solr項(xiàng)目訪問地址 + /core實(shí)例名稱組合的路徑。一般我們新建的core實(shí)例名稱就是new_core。
為實(shí)體類屬性添加@Field注解
上面完成了基本的環(huán)境配置,下面則需要為實(shí)體類中屬性添加@Field注解標(biāo)識(shí)。
一般我們定義的實(shí)體類屬性名稱和數(shù)據(jù)庫(kù)的字段名稱相似,但是,如果使用了Solr搜索,每次查詢數(shù)據(jù)將不再查詢數(shù)據(jù)庫(kù),那么Solr怎么獲取到你要查詢的是商品的title還是price呢?
這里就需要使用@Field注解,保證實(shí)體類屬性名稱和Solr索引庫(kù)中定義的Field域名稱對(duì)應(yīng),如果當(dāng)前屬性名稱和Solr索引庫(kù)域Field名稱相同,就添加@Field名稱,如果不相同就添加@Field("域名稱")注解。
這里我們這樣定義實(shí)體類 Goods
public class Goods implements Serializable{@Fieldprivate Long id; //商品ID@Field("item_title")private String title; //商品標(biāo)題@Field("item_price")private String price; //商品價(jià)格@Field("item_image")private String image; //商品圖片@Field("item_category")private String category; //商品類別@Field("item_brand")private String brand; //商品品牌@Field("item_seller")private String seller; //商品賣家 }- 注意:溫馨提示一下,大家創(chuàng)建實(shí)體類的時(shí)候盡量養(yǎng)成一個(gè)習(xí)慣:實(shí)現(xiàn)Serializable序列化接口。不序列化遲早會(huì)遇到問題。
實(shí)例
本例詳細(xì)代碼請(qǐng)參看: Github
由于我們創(chuàng)建的是測(cè)試類,需要使用@RunWith和@ContextConfiguration注解加載配置文件。
在測(cè)試類中用注入Spring Data Solr操作Solr索引庫(kù)的核心類SolrTemplate
添加
@Test public void testAdd() {Goods goods = new Goods(1L, "IPhone SE", "120", "手機(jī)", "Apple", "Apple");solrTemplate.saveBean(goods);solrTemplate.commit(); //提交 }實(shí)現(xiàn)數(shù)據(jù)的添加:
按主鍵查詢
@Test public void testFindById() {Goods goods = solrTemplate.getById(1, Goods.class);System.out.println("--------" + goods.getTitle()); }按主鍵刪除
@Test public void testDeleteById() {solrTemplate.deleteById("1");solrTemplate.commit(); //提交 }批量插入數(shù)據(jù)
@Test public void testAddList() {List<Goods> list = new ArrayList<Goods>();//循環(huán)插入100條數(shù)據(jù)for (int i = 0; i < 100; i++) {Goods goods = new Goods(i + 1L, "華為Mate" + i, String.valueOf(2000 + i), "手機(jī)", "手機(jī)", "華為專賣店");list.add(goods);}solrTemplate.saveBeans(list); //添加集合對(duì)象,調(diào)用saveBeans();添加普通對(duì)象類型數(shù)據(jù),使用saveBean();solrTemplate.commit(); //提交 }分頁(yè)查詢
@Test public void testPageQuery() {Query query = new SimpleQuery("*:*");query.setOffset(20); //開始索引(默認(rèn)0)query.setRows(20); //每頁(yè)記錄數(shù)(默認(rèn)10)ScoredPage<Goods> page = solrTemplate.queryForPage(query, Goods.class);System.out.println("總記錄數(shù):" + page.getTotalElements());List<Goods> list = page.getContent(); }上面使用new SimpleQuery方式是聲明一個(gè)Query實(shí)例,而("*:*")表示查詢Solr索引庫(kù)中的所有數(shù)據(jù)。Solr默認(rèn)查詢的數(shù)據(jù)是前十條記錄,也就是即便使用了("*:*")查詢,也僅僅是查詢到十條記錄。 不過Solr提供了分頁(yè)查詢的方法:setOffset()設(shè)置開始索引位置,setRows()設(shè)置結(jié)束索引位置(默認(rèn)10);調(diào)用solrTemplate.queryForPage(query, clazz)即是分頁(yè)查詢。
分頁(yè)查詢到的結(jié)果存儲(chǔ)在page對(duì)象中,使用page.getTotalElements()可以獲取到查詢的總記錄數(shù),使用page.getContent()獲取到查詢的數(shù)據(jù)。
條件查詢
@Test public void testPageQueryMutil() {Query query = new SimpleQuery("*:*");Criteria criteria = new Criteria("item_title").contains("2");criteria = criteria.and("item_title").contains("5");query.addCriteria(criteria);ScoredPage<Goods> page = solrTemplate.queryForPage(query, Goods.class);System.out.println("總記錄數(shù):" + page.getTotalElements());List<Goods> list = page.getContent(); }如上,使用分頁(yè)插件需要實(shí)例化Criteria類添加查詢條件,查詢是根據(jù)schema.xml中定義的Field域名稱查詢的,相當(dāng)于根據(jù)數(shù)據(jù)庫(kù)的字段名稱查詢一樣。
刪除所有
@Test public void deleteAll(){Query query = new SimpleQuery("*:*");solrTemplate.delete(query); }<br/>
交流
如果大家有興趣,歡迎大家加入我的Java交流群:671017003 ,一起交流學(xué)習(xí)Java技術(shù)。博主目前一直在自學(xué)JAVA中,技術(shù)有限,如果可以,會(huì)盡力給大家提供一些幫助,或是一些學(xué)習(xí)方法,當(dāng)然群里的大佬都會(huì)積極給新手答疑的。所以,別猶豫,快來加入我們吧!
<br/>
聯(lián)系
If you have some questions after you see this article, you can contact me or you can find some info by clicking these links.
- [Blog@TyCoding's blog](http://www.tycoding.cn)
- [GitHub@TyCoding](https://github.com/TyCoding)
- [ZhiHu@TyCoding](https://www.zhihu.com/people/tomo-83-82/activities)
轉(zhuǎn)載于:https://my.oschina.net/u/3955926/blog/2208590
總結(jié)
以上是生活随笔為你收集整理的Solr及Spring-Data-Solr入门学习的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ACM-ICPC 2018 徐州赛区网络
- 下一篇: JS面向对象的程序设计之继承-继承的实现