全文搜索引擎Solr原理和实战教程
Solr簡介
1.Solr是什么?
Solr它是一種開放源碼的、基于 Lucene Java 的搜索服務(wù)器,易于加入到 Web 應(yīng)用程序中。Solr 提供了層面搜索(就是統(tǒng)計)、命中醒目顯示并且支持多種輸出格式(包括XML/XSLT 和JSON等格式)。Solr是一個高性能,采用Java開發(fā),
基于Lucene的全文搜索服務(wù)器。同時對其進(jìn)行了擴展,提供了比Lucene更為豐富的查詢語言,同時實現(xiàn)了可配置、可擴展并對查詢性能進(jìn)行了優(yōu)化,并且提供了一個完善的功能管理界面,是一款非常優(yōu)秀的全文搜索引擎。
Solr是一個獨立的企業(yè)級搜索應(yīng)用服務(wù)器,它對外提供類似于Web-service的API接口。用戶可以通過http請求,向搜索引擎服務(wù)器提交一定格式的XML文件,生成索引;也可以通過Http Get操作提出查找請求,并得到XML格式的返回結(jié)果。
Solr易于安裝和配置,而且附帶了一個基于HTTP 的管理界面。可以使用 Solr 的表現(xiàn)優(yōu)異的基本搜索功能,也可以對它進(jìn)行擴展從而滿足企業(yè)的需要。
Solr架構(gòu)圖
Solr的特性
高效、靈活的緩存功能,垂直搜索功能,高亮顯示搜索結(jié)果,通過索引復(fù)制來提高可用性,提供一套強大Data Schema來定義字段,類型和設(shè)置文本分析,提供基于Web的管理界面等.
· 高級的全文搜索功能
· 專為高通量的網(wǎng)絡(luò)流量進(jìn)行的優(yōu)化
· 基于開放接口(XML和HTTP)的標(biāo)準(zhǔn)
· 綜合的HTML管理界面
· 可伸縮性-能夠有效地復(fù)制到另外一個Solr搜索服務(wù)器
· 使用XML配置達(dá)到靈活性和適配性
· 可擴展的插件體系
2. Lucene 是什么?
Lucene是一個基于Java的全文信息檢索工具包,它不是一個完整的搜索應(yīng)用程序,而是為你的應(yīng)用程序提供索引和搜索功能。Lucene 目前是 Apache Jakarta(雅加達(dá)) 家族中的一個開源項目。也是目前最為流行的基于Java開源全文檢索工具包。目前已經(jīng)有很多應(yīng)用程序的搜索功能是基于 Lucene ,比如Eclipse 幫助系統(tǒng)的搜索功能。Lucene能夠為文本類型的數(shù)據(jù)建立索引,所以你只要把你要索引的數(shù)據(jù)格式轉(zhuǎn)化的文本格式,Lucene 就能對你的文檔進(jìn)行索引和搜索。
3. Solr vs Lucene
Solr與Lucene 并不是競爭對立關(guān)系,恰恰相反Solr 依存于Lucene,因為Solr底層的核心技術(shù)是使用Lucene 來實現(xiàn)的,Solr和Lucene的本質(zhì)區(qū)別有以下三點:搜索服務(wù)器,企業(yè)級和管理。Lucene本質(zhì)上是搜索庫,不是獨立的應(yīng)用程序,而Solr是。Lucene專注于搜索底層的建設(shè),而Solr專注于企業(yè)應(yīng)用。Lucene不負(fù)責(zé)支撐搜索服務(wù)所必須的管理,而Solr負(fù)責(zé)。所以說,一句話概括 Solr: Solr是Lucene面向企業(yè)搜索應(yīng)用的擴展。
Solr與Lucene架構(gòu)圖:
Solr使用Lucene并且擴展了它!
· 一個真正的擁有動態(tài)字段(Dynamic Field)和唯一鍵(Unique Key)的數(shù)據(jù)模式(Data Schema)
· 對Lucene查詢語言的強大擴展!
· 支持對結(jié)果進(jìn)行動態(tài)的分組和過濾
· 高級的,可配置的文本分析
· 高度可配置和可擴展的緩存機制
· 性能優(yōu)化
· 支持通過XML進(jìn)行外部配置
· 擁有一個管理界面
· 可監(jiān)控的日志
· 支持高速增量式更新(Fast incremental Updates)和快照發(fā)布(Snapshot Distribution)
下載安裝
下載
https://mirrors.tuna.tsinghua.edu.cn/apache/lucene/solr/8.5.1/solr-8.5.1.tgz
解壓即可.目錄結(jié)構(gòu):
啟動命令
- cd ~/solr/bin 回車
- solr start -p 8983 回車,等待啟動成功
- solr stop -p 8983 這個是停止solr命令
啟動成功后,訪問 http://127.0.0.1:8983/solr/#/
可以看到Solr的管理界面:
JVM Runtime Oracle Corporation Java HotSpot(TM) 64-Bit Server VM 1.8.0_40 25.40-b25 Processors 12 Args -DSTOP.KEY=solrrocks-DSTOP.PORT=7983-Djetty.home=/Users/jack/soft/solr-8.5.1/server-Djetty.port=8983-Dsolr.data.home=-Dsolr.default.confdir=/Users/jack/soft/solr-8.5.1/server/solr/configsets/_default/conf-Dsolr.install.dir=/Users/jack/soft/solr-8.5.1-Dsolr.jetty.https.port=8983-Dsolr.jetty.inetaccess.excludes=-Dsolr.jetty.inetaccess.includes=-Dsolr.log.dir=/Users/jack/soft/solr-8.5.1/server/logs-Dsolr.log.muteconsole-Dsolr.solr.home=/Users/jack/soft/solr-8.5.1/server/solr-Duser.timezone=UTC-XX:+AlwaysPreTouch-XX:+ParallelRefProcEnabled-XX:+PerfDisableSharedMem-XX:+PrintGCApplicationStoppedTime-XX:+PrintGCDateStamps-XX:+PrintGCDetails-XX:+PrintGCTimeStamps-XX:+PrintHeapAtGC-XX:+PrintTenuringDistribution-XX:+UseG1GC-XX:+UseGCLogFileRotation-XX:+UseLargePages-XX:GCLogFileSize=20M-XX:MaxGCPauseMillis=250-XX:NumberOfGCLogFiles=9-XX:OnOutOfMemoryError=/Users/jack/soft/solr-8.5.1/bin/oom_solr.sh 8983 /Users/jack/soft/solr-8.5.1/server/logs-Xloggc:/Users/jack/soft/solr-8.5.1/server/logs/solr_gc.log-Xms512m-Xmx512m-Xss256k-verbose:gc啟動并重新啟動 Solr
您可以使用 start 命令來啟動 Solr,使用 restart 命令允許您在 Solr 已經(jīng)運行或者已經(jīng)停止的情況下重新啟動 Solr。
該 start 和 restart 命令有多種選擇,讓您在 SolrCloud 模式下運行,使用一個示例配置集,從一個不是默認(rèn)的主機名或端口開始并指向本地的 ZooKeeper 集合。
bin/solr start [options] bin/solr start -help bin/solr restart [options] bin/solr restart -help使用 restart 命令時,必須傳遞您在啟動 Solr 時最初傳遞的所有參數(shù)。在幕后,啟動了一個停止請求,所以 Solr 將在被再次啟動之前停止。如果沒有節(jié)點已經(jīng)運行,則重新啟動將跳過此步驟停止并繼續(xù)啟動 Solr。
啟動參數(shù)
bin/solr 腳本提供了許多選項,允許您以常見的方式自定義服務(wù)器,例如更改偵聽端口。但是,大多數(shù)默認(rèn)設(shè)置對于大多數(shù) Solr 安裝都是足夠的,特別是剛開始時。
-a "<string>"
使用額外的 JVM 參數(shù)(例如以 -X 開頭的參數(shù))啟動 Solr。如果您正在傳遞以 “-D” 開頭的 JVM 參數(shù),則可以省略 -a 選項。例如:
bin/solr start -a "-Xdebug -Xrunjdwp:transport=dt_socket, server=y,suspend=n,address=1044"-cloud
以 SolrCloud 模式啟動 Solr,該模式也將啟動 Solr 附帶的嵌入式 ZooKeeper 實例。
這個選項可以簡單地縮短為-c。
如果您已經(jīng)在運行您想要使用的 ZooKeeper 集合,而不是嵌入式(單節(jié)點)ZooKeeper,則還應(yīng)該傳遞 -z 參數(shù)。
有關(guān)更多詳細(xì)信息,請參閱下面的 SolrCloud 模式部分。例如:
bin/solr start -c -d <dir>定義一個服務(wù)器目錄,默認(rèn)為server(如,$SOLR_HOME/server)。重寫此選項的情況并不常見。在同一臺主機上運行多個 Solr 實例時,更常見的是為每個實例使用相同的服務(wù)器目錄,并使用 -s 選項使用唯一的Solr主目錄更為常見。例如:
bin/solr start -d newServerDir應(yīng)用示例
Building and Running SolrJ Applications: put the following dependency in the project’s pom.xml:
<dependency><groupId>org.apache.solr</groupId><artifactId>solr-solrj</artifactId><version>x.y.z</version> </dependency>Single node Solr client
String urlString = "http://localhost:8983/solr/techproducts"; SolrClient solr = new HttpSolrClient.Builder(urlString).build();SolrCloud client
// Using a ZK Host String String zkHostString = "zkServerA:2181,zkServerB:2181,zkServerC:2181/solr"; SolrClient solr = new CloudSolrClient.Builder().withZkHost(zkHostString).build();// Using already running Solr nodes SolrClient solr = new CloudSolrClient.Builder().withSolrUrl("http://localhost:8983/solr").build();Once you have a SolrClient, you can use it by calling methods like query(), add(), and commit().
客戶端API簡介
Solr的核心是一個Web應(yīng)用程序,但是由于它是建立在開放的協(xié)議之上的,任何類型的客戶端應(yīng)用程序都可以使用Solr。
HTTP是客戶端應(yīng)用程序和Solr之間使用的基本協(xié)議。客戶端提出請求,Solr做一些工作并提供響應(yīng)。客戶使用請求來請求Solr執(zhí)行查詢或索引文件等操作。
客戶端應(yīng)用程序可以通過創(chuàng)建HTTP請求和解析HTTP響應(yīng)到達(dá)Solr。客戶端API封裝了發(fā)送請求和解析響應(yīng)的大部分工作,這使得編寫客戶端應(yīng)用程序變得更加容易。
客戶使用Solr的五個基本操作來與Solr一起工作。這五個操作分別是:查詢、索引、刪除、提交和優(yōu)化。
查詢通過創(chuàng)建一個包含所有查詢參數(shù)的URL來執(zhí)行。Solr檢查請求URL,執(zhí)行查詢并返回結(jié)果。其他操作是相似的,雖然在某些情況下,HTTP請求是一個POST操作,并包含除請求URL中包含的任何信息之外的信息。例如,索引操作可能包含請求正文中的文檔。
Solr 還具有一個 EmbeddedSolrServer,它提供了一個 Java API 而不需要 HTTP 連接。
Setting XMLResponseParser
SolrJ uses a binary format, rather than XML, as its default response format. If you are trying to mix Solr and SolrJ versions where one is version 1.x and the other is 3.x or later, then you MUST use the XML response parser. The binary format changed in 3.x, and the two javabin versions are entirely incompatible. The following code will make this change:
solr.setParser(new XMLResponseParser());Performing Queries
Use query() to have Solr search for results. You have to pass a SolrQuery object that describes the query, and you will get back a QueryResponse (from the org.apache.solr.client.solrj.response package).
SolrQuery has methods that make it easy to add parameters to choose a request handler and send parameters to it. Here is a very simple example that uses the default request handler and sets the query string:
SolrQuery query = new SolrQuery(); query.setQuery(mQueryString);To choose a different request handler, there is a specific method available in SolrJ version 4.0 and later:
query.setRequestHandler("/spellCheckCompRH");You can also set arbitrary parameters on the query object. The first two code lines below are equivalent to each other, and the third shows how to use an arbitrary parameter q to set the query string:
query.set("fl", "category,title,price"); query.setFields("category", "title", "price"); query.set("q", "category:books");Once you have your SolrQuery set up, submit it with query():
QueryResponse response = solr.query(query);The client makes a network connection and sends the query. Solr processes the query, and the response is sent and parsed into a QueryResponse.
The QueryResponse is a collection of documents that satisfy the query parameters. You can retrieve the documents directly with getResults() and you can call other methods to find out information about highlighting or facets.
SolrDocumentList list = response.getResults();Indexing Documents
Other operations are just as simple. To index (add) a document, all you need to do is create a SolrInputDocument and pass it along to the SolrClient’s `add() method. This example assumes that the SolrClient object called 'solr' is already created based on the examples shown earlier.
SolrInputDocument document = new SolrInputDocument(); document.addField("id", "552199"); document.addField("name", "Gouda cheese wheel"); document.addField("price", "49.99"); UpdateResponse response = solr.add(document);// Remember to commit your changes!solr.commit();Uploading Content in XML or Binary Formats
SolrJ lets you upload content in binary format instead of the default XML format. Use the following code to upload using binary format, which is the same format SolrJ uses to fetch results. If you are trying to mix Solr and SolrJ versions where one is version 1.x and the other is 3.x or later, then you MUST stick with the XML request writer. The binary format changed in 3.x, and the two javabin versions are entirely incompatible.
solr.setRequestWriter(new BinaryRequestWriter());Lucence工作原理
lucence 是一個高性能的java全文檢索工具包,他使用倒排序文件索引結(jié)構(gòu),改結(jié)構(gòu)和相應(yīng)的生成算法如下:
一、設(shè)有兩篇文章1和2
文章1的內(nèi)容為:Tom lives in guangzhou,i live in guangzhou too
文章2的內(nèi)容為:He once lived in shanghai
由于lucence是基于關(guān)鍵詞索引和查詢的,因此我們首先要取得這兩篇文章的關(guān)鍵詞。通常我們要做一下處理:
a.我們現(xiàn)在有的是文章內(nèi)容,即一個字符串,我們先要找出字符串中的所有單詞,即分詞。英文單詞由于用空格分隔,比較好處理。中文單詞間是連在一起的需要特殊的分詞處理。
b.文章中的”in”, “once” “too”等詞沒有什么實際意義,中文中的“的”“是”等字通常也無具體含義,這些不代表概念的詞可以過濾掉
c.用戶通常希望查“He”時能把含“he”,“HE”的文章也找出來,所以所有單詞需要統(tǒng)一大小寫。
d.用戶通常希望查“l(fā)ive”時能把含“l(fā)ives”,“l(fā)ived”的文章也找出來,所以需要把“l(fā)ives”,“l(fā)ived”還原成“l(fā)ive”
e.文章中的標(biāo)點符號通常不表示某種概念,也可以過濾掉
在lucene中以上措施由Analyzer類完成
經(jīng)過上面處理后,
文章1的所有關(guān)鍵詞為:[tom] [live] [guangzhou] [live] [guangzhou]
文章2的所有關(guān)鍵詞為:[he] [live] [shanghai]**
| guangzhou | 1 |
| he | 2 |
| i | 1 |
| live | 1,2 |
| shanghai | 2 |
| tom | 1 |
通常僅知道關(guān)鍵詞在哪些文章中出現(xiàn)還不夠,我們還需要知道關(guān)鍵詞在文章中出現(xiàn)次數(shù)和出現(xiàn)的位置,通常有兩種位置:a)字符位置,即記錄該詞是文章中第幾個字符(優(yōu)點是關(guān)鍵詞亮顯時定位快);b)關(guān)鍵詞位置,即記錄該詞是文章中第幾個關(guān)鍵詞(優(yōu)點是節(jié)約索引空間、詞組(phase)查詢快),lucene 中記錄的就是這種位置。
加上“出現(xiàn)頻率”和“出現(xiàn)位置”信息后,我們的索引結(jié)構(gòu)變?yōu)?#xff1a;
| guangzhou | 1[2] | 3,6 |
| he | 2[1] | 1 |
| i | 1[1] | 4 |
| live | 1[2],2[1] | 2,5,2 |
| shanghai | 2[1] | 3 |
| tom | 1[1] | 1 |
以live 這行為例我們說明一下該結(jié)構(gòu):live在文章1中出現(xiàn)了2次,文章2中出現(xiàn)了一次,它的出現(xiàn)位置為“2,5,2”這表示什么呢?我們需要結(jié)合文章號和出現(xiàn)頻率來分析,文章1中出現(xiàn)了2次,那么“2,5”就表示live在文章1中出現(xiàn)的兩個位置,文章2中出現(xiàn)了一次,剩下的“2”就表示live是文章2中第 2個關(guān)鍵字。
以上就是lucene索引結(jié)構(gòu)中最核心的部分。我們注意到關(guān)鍵字是按字符順序排列的(lucene沒有使用B樹結(jié)構(gòu)),因此lucene可以用二元搜索算法快速定位關(guān)鍵詞。
實現(xiàn)時 lucene將上面三列分別作為詞典文件(Term Dictionary)、頻率文件(frequencies)、位置文件 (positions)保存。其中詞典文件不僅保存有每個關(guān)鍵詞,還保留了指向頻率文件和位置文件的指針,通過指針可以找到該關(guān)鍵字的頻率信息和位置信息。
Lucene中使用了field的概念,用于表達(dá)信息所在位置(如標(biāo)題中,文章中,url中),在建索引中,該field信息也記錄在詞典文件中,每個關(guān)鍵詞都有一個field信息(因為每個關(guān)鍵字一定屬于一個或多個field)。
為了減小索引文件的大小,Lucene對索引還使用了壓縮技術(shù)。首先,對詞典文件中的關(guān)鍵詞進(jìn)行了壓縮,關(guān)鍵詞壓縮為<堉?綴長度,后綴>,例如:當(dāng)前詞為“阿拉伯語”,上一個詞為“阿拉伯”,那么“阿拉伯語”壓縮為<3,語>。其次大量用到的是對數(shù)字的壓縮,數(shù)字只保存與上一個值的差值(這樣可以減小數(shù)字的長度,進(jìn)而減少保存該數(shù)字需要的字節(jié)數(shù))。例如當(dāng)前文章號是16389(不壓縮要用3個字節(jié)保存),上一文章號是16382,壓縮后保存7(只用一個字節(jié))。
下面我們可以通過對該索引的查詢來解釋一下為什么要建立索引。
假設(shè)要查詢單詞 “l(fā)ive”,lucene先對詞典二元查找、找到該詞,通過指向頻率文件的指針讀出所有文章號,然后返回結(jié)果。詞典通常非常小,因而,整個過程的時間是毫秒級的。
而用普通的順序匹配算法,不建索引,而是對所有文章的內(nèi)容進(jìn)行字符串匹配,這個過程將會相當(dāng)緩慢,當(dāng)文章數(shù)目很大時,時間往往是無法忍受的。
參考資料
https://lucene.apache.org/solr/guide/8_5/solr-tutorial.html
https://lucene.apache.org/solr/
https://www.jianshu.com/p/be9e4accb486
https://www.w3cschool.cn/solr_doc/solr_doc-emn62fs5.html
https://lucene.apache.org/solr/guide/6_6/using-solrj.html#UsingSolrJ-SettingXMLResponseParser
https://www.cnblogs.com/senlinyang/p/8064202.html
Kotlin開發(fā)者社區(qū)
專注分享 Java、 Kotlin、Spring/Spring Boot、MySQL、redis、neo4j、NoSQL、Android、JavaScript、React、Node、函數(shù)式編程、編程思想、"高可用,高性能,高實時"大型分布式系統(tǒng)架構(gòu)設(shè)計主題。
High availability, high performance, high real-time large-scale distributed system architecture design。
分布式框架:Zookeeper、分布式中間件框架等
分布式存儲:GridFS、FastDFS、TFS、MemCache、redis等
分布式數(shù)據(jù)庫:Cobar、tddl、Amoeba、Mycat
云計算、大數(shù)據(jù)、AI算法
虛擬化、云原生技術(shù)
分布式計算框架:MapReduce、Hadoop、Storm、Flink等
分布式通信機制:Dubbo、RPC調(diào)用、共享遠(yuǎn)程數(shù)據(jù)、消息隊列等
消息隊列MQ:Kafka、MetaQ,RocketMQ
怎樣打造高可用系統(tǒng):基于硬件、軟件中間件、系統(tǒng)架構(gòu)等一些典型方案的實現(xiàn):HAProxy、基于Corosync+Pacemaker的高可用集群套件中間件系統(tǒng)
Mycat架構(gòu)分布式演進(jìn)
大數(shù)據(jù)Join背后的難題:數(shù)據(jù)、網(wǎng)絡(luò)、內(nèi)存和計算能力的矛盾和調(diào)和
Java分布式系統(tǒng)中的高性能難題:AIO,NIO,Netty還是自己開發(fā)框架?
高性能事件派發(fā)機制:線程池模型、Disruptor模型等等。。。
合抱之木,生于毫末;九層之臺,起于壘土;千里之行,始于足下。不積跬步,無以至千里;不積小流,無以成江河。
總結(jié)
以上是生活随笔為你收集整理的全文搜索引擎Solr原理和实战教程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深入理解java虚拟机
- 下一篇: 友华PT925E,电信天翼网关3.0,光