1. ElasticSearch概述
Elaticsearch,簡稱為es, es是一個開源的高擴(kuò)展的分布式全文檢索引擎,它可以近乎實時的存儲、檢索數(shù)據(jù);本身擴(kuò)展性很好,可以擴(kuò)展到上百臺服務(wù)器,處理PB級別(大數(shù)據(jù)時代)的數(shù)據(jù)。es也使用Java開發(fā)并使用Lucene作為其核心來實現(xiàn)所有索引和搜索的功能,但是它的目的是通過簡單的RESTful API來隱藏Lucene的復(fù)雜性,從而讓全文搜索變得簡單。
據(jù)國際權(quán)威的數(shù)據(jù)庫產(chǎn)品評測機(jī)構(gòu)DB Engines的統(tǒng)計,在2016年1月,ElasticSearch已超過Solr等,成為排名第一的搜索引擎類應(yīng)用。
2. ES和solr的差別
2.1 Elasticsearch簡介
Elasticsearch是一個實時分布式搜索和分析引擎。它讓你以前所未有的速度處理大數(shù)據(jù)成為可能。
它用于全文搜索、結(jié)構(gòu)化搜索、分析以及將這三者混合使用:
維基百科使用Elasticsearch提供全文搜索并高亮關(guān)鍵字,以及輸入實時搜索(search-asyou-type)和搜索糾錯(did-you-mean)等搜索建議功能。
英國衛(wèi)報使用Elasticsearch結(jié)合用戶日志和社交網(wǎng)絡(luò)數(shù)據(jù)提供給他們的編輯以實時的反饋,以便及時了解公眾對新發(fā)表的文章的回應(yīng)。
StackOverflow結(jié)合全文搜索與地理位置查詢,以及more-like-this功能來找到相關(guān)的問題和答案。
Github使用Elasticsearch檢索1300億行的代碼。
但是Elasticsearch不僅用于大型企業(yè),它還讓像DataDog以及Klout這樣的創(chuàng)業(yè)公司將最初的想法變成可擴(kuò)展的解決方案。
Elasticsearch可以在你的筆記本上運行,也可以在數(shù)以百計的服務(wù)器上處理PB級別的數(shù)據(jù) 。
Elasticsearch是一個基于Apache Lucene(TM)的開源搜索引擎。無論在開源還是專有領(lǐng)域,Lucene可以被認(rèn)為是迄今為止最先進(jìn)、性能最好的、功能最全的搜索引擎庫。
但是,Lucene只是一個庫。想要使用它,你必須使用Java來作為開發(fā)語言并將其直接集成到你的應(yīng)用中,更糟糕的是,Lucene非常復(fù)雜,你需要深入了解檢索的相關(guān)知識來理解它是如何工作的。
Elasticsearch也使用Java開發(fā)并使用Lucene作為其核心來實現(xiàn)所有索引和搜索的功能,但是它的目的是通過簡單的RESTful API來隱藏Lucene的復(fù)雜性,從而讓全文搜索變得簡單。
2.2 Solr簡介
Solr 是Apache下的一個頂級開源項目,采用Java開發(fā),它是基于Lucene的全文搜索服務(wù)器。Solr提供了比Lucene更為豐富的查詢語言,同時實現(xiàn)了可配置、可擴(kuò)展,并對索引、搜索性能進(jìn)行了優(yōu)化
Solr可以獨立運行,運行在Jetty、Tomcat等這些Servlet容器中,Solr 索引的實現(xiàn)方法很簡單,用 POST方法向 Solr 服務(wù)器發(fā)送一個描述 Field 及其內(nèi)容的 XML 文檔,Solr根據(jù)xml文檔添加、刪除、更新索引。Solr 搜索只需要發(fā)送 HTTP GET 請求,然后對 Solr 返回Xml、json等格式的查詢結(jié)果進(jìn)行解析,組織頁面布局。Solr不提供構(gòu)建UI的功能,Solr提供了一個管理界面,通過管理界面可以查詢Solr的配置和運行情況。
solr是基于lucene開發(fā)企業(yè)級搜索服務(wù)器,實際上就是封裝了lucene。
Solr是一個獨立的企業(yè)級搜索應(yīng)用服務(wù)器,它對外提供類似于Web-service的API接口。用戶可以通過http請求,向搜索引擎服務(wù)器提交一定格式的文件,生成索引;也可以通過提出查找請求,并得到返回結(jié)果。
2.3 Lucene簡介
Lucene是apache軟件基金會4 jakarta項目組的一個子項目,是一個開放源代碼的全文檢索引擎工具包,但它不是一個完整的全文檢索引擎,而是一個全文檢索引擎的架構(gòu),提供了完整的查詢引擎和索引引擎,部分文本分析引擎(英文與德文兩種西方語言)。Lucene的目的是為軟件開發(fā)人員提供一個簡單易用的工具包,以方便的在目標(biāo)系統(tǒng)中實現(xiàn)全文檢索的功能,或者是以此為基礎(chǔ)建立起完整的全文檢索引擎。Lucene是一套用于全文檢索和搜尋的開源程式庫,由Apache軟件基金會支持和提供。Lucene提供了一個簡單卻強(qiáng)大的應(yīng)用程式接口,能夠做全文索引和搜尋。在Java開發(fā)環(huán)境里L(fēng)ucene是一個成熟的免費開源工具。就其本身而言,Lucene是當(dāng)前以及最近幾年最受歡迎的免費Java信息檢索程序庫。人們經(jīng)常提到信息檢索程序庫,雖然與搜索引擎有關(guān),但不應(yīng)該將信息檢索程序庫與搜索引擎相混淆。
Lucene是一個全文檢索引擎的架構(gòu)。那什么是全文搜索引擎?
全文搜索引擎是名副其實的搜索引擎,國外具代表性的有Google、Fast/AllTheWeb、AltaVista、Inktomi、Teoma、WiseNut等,國內(nèi)著名的有百度(Baidu)。它們都是通過從互聯(lián)網(wǎng)上提取的各個網(wǎng)站的信息(以網(wǎng)頁文字為主)而建立的數(shù)據(jù)庫中,檢索與用戶查詢條件匹配的相關(guān)記錄,然后按一定的排列順序?qū)⒔Y(jié)果返回給用戶,因此他們是真正的搜索引擎。
從搜索結(jié)果來源的角度,全文搜索引擎又可細(xì)分為兩種,一種是擁有自己的檢索程序(Indexer),俗稱“蜘蛛”(Spider)程序或“機(jī)器人”(Robot)程序,并自建網(wǎng)頁數(shù)據(jù)庫,搜索結(jié)果直接從自身的數(shù)據(jù)庫中調(diào)用,如上面提到的7家引擎;另一種則是租用其他引擎的數(shù)據(jù)庫,并按自定的格式排列搜索結(jié)果,如Lycos引擎。
2.4 Elasticsearch和Solr比較




2.5 ElasticSearch vs Solr 總結(jié)
- es基本是開箱即用(解壓就可以用 ! ),非常簡單。Solr安裝略微復(fù)雜一丟丟!
- Solr 利用 Zookeeper 進(jìn)行分布式管理,而 Elasticsearch 自身帶有分布式協(xié)調(diào)管理功能。
- Solr 支持更多格式的數(shù)據(jù),比如JSON、XML、CSV,而 Elasticsearch 僅支持json文件格式。
- Solr 官方提供的功能更多,而 Elasticsearch 本身更注重于核心功能,高級功能多有第三方插件提供,例如圖形化界面需要kibana友好支撐~!
- Solr 查詢快,但更新索引時慢(即插入刪除慢),用于電商等查詢多的應(yīng)用;
- ES建立索引快(即查詢慢),即實時性查詢快,用于facebook新浪等搜索。
- Solr 是傳統(tǒng)搜索應(yīng)用的有力解決方案,但 Elasticsearch 更適用于新興的實時搜索應(yīng)用。
- Solr比較成熟,有一個更大,更成熟的用戶、開發(fā)和貢獻(xiàn)者社區(qū),而 Elasticsearch相對開發(fā)維護(hù)者較少,更新太快,學(xué)習(xí)使用成本較高。(趨勢!)
3. ElasticSearch安裝
聲明:JDK1.8 ,最低要求! ElasticSearch 客戶端,界面工具!
Java開發(fā),ElasticSearch 的版本和我們之后對應(yīng)的 Java 的核心jar包! 版本對應(yīng)!JDK 環(huán)境是正常!
下載
官網(wǎng):https://www.elastic.co/
下載地址:https://www.elastic.co/cn/downloads/elasticsearch
window 下安裝!
3.1 解壓就可以使用了!

3.2 熟悉目錄!
bin 啟動文件
config 配置文件
log4j2 日志配置文件
jvm.options java 虛擬機(jī)相關(guān)的配置
elasticsearch.yml elasticsearch 的配置文件! 默認(rèn) 9200 端口! 跨域!
lib 相關(guān)jar包
logs 日志!
modules 功能模塊
plugins 插件!
3.3 啟動,訪問9200;
啟動不起來在elasticsearch.yml末尾添加
xpack.ml.enabled: false

3.4 訪問測試!

安裝可視化界面 es head的插件
需要node.js環(huán)境
-
啟動
npm install npm run start -
連接測試發(fā)現(xiàn),存在跨域問題:配置es
http.cors.enabled: true http.cors.allow-origin: "*" -
重啟es服務(wù)器,然后再次連接
初學(xué),就把es當(dāng)做一個數(shù)據(jù)庫! (可以建立索引(庫),文檔(庫中的數(shù)據(jù)!))
這個head我們就把它當(dāng)做數(shù)據(jù)展示工具!我們后面所有的查詢,Kibana!
了解 ELK
ELK是Elasticsearch、Logstash、Kibana三大開源框架首字母大寫簡稱。市面上也被成為ElasticStack。其中Elasticsearch是一個基于Lucene、分布式、通過Restful方式進(jìn)行交互的近實時搜索平臺框架。像類似百度、谷歌這種大數(shù)據(jù)全文搜索引擎的場景都可以使用Elasticsearch作為底層支持框架,可見Elasticsearch提供的搜索能力確實強(qiáng)大,市面上很多時候我們簡稱Elasticsearch為es。Logstash是ELK的中央數(shù)據(jù)流引擎,用于從不同目標(biāo)(文件/數(shù)據(jù)存儲/MQ)收集的不同格式數(shù)據(jù),經(jīng)過過濾后支持輸出到不同目的地(文件/MQ/redis/elasticsearch/kafka等)。Kibana可以將elasticsearch的數(shù)據(jù)通過友好
的頁面展示出來,提供實時分析的功能。
市面上很多開發(fā)只要提到ELK能夠一致說出它是一個日志分析架構(gòu)技術(shù)棧總稱,但實際上ELK不僅僅適用于日志分析,它還可以支持其它任何數(shù)據(jù)分析和收集的場景,日志分析和收集只是更具有代表性。并非唯一性。

安裝Kibana
Kibana是一個針對Elasticsearch的開源分析及可視化平臺,用來搜索、查看交互存儲在Elasticsearch索引中的數(shù)據(jù)。使用Kibana,可以通過各種圖表進(jìn)行高級數(shù)據(jù)分析及展示。Kibana讓海量數(shù)據(jù)更容易理解。它操作簡單,基于瀏覽器的用戶界面可以快速創(chuàng)建儀表板(dashboard)實時顯示Elasticsearch查詢動態(tài)。設(shè)置Kibana非常簡單。無需編碼或者額外的基礎(chǔ)架構(gòu),幾分鐘內(nèi)就可以完成Kibana安裝并啟動Elasticsearch索引監(jiān)測
官網(wǎng):https://www.elastic.co/cn/kibana
Kibana 版本要和 Es 一致!
啟動測試:
-
解壓后端的目錄
-
啟動
-
訪問測試
-
開發(fā)工具! (Post、curl、head、谷歌瀏覽器插件測試?。?/p>
-
漢化!自己修改kibana配置即可! zh-CN!
kibaba.yml文件末尾添加
i18n.locale: "zn-CH"
4. ES核心概念
- 索引
- 字段類型(mapping)
- 文檔(documents)
概述
在前面的學(xué)習(xí)中,我們已經(jīng)掌握了es是什么,同時也把es的服務(wù)已經(jīng)安裝啟動,那么es是如何去存儲數(shù)據(jù),數(shù)據(jù)結(jié)構(gòu)是什么,又是如何實現(xiàn)搜索的呢?我們先來聊聊ElasticSearch的相關(guān)概念吧!
集群,節(jié)點,索引,類型,文檔,分片,映射是什么?
elasticsearch是面向文檔,關(guān)系行數(shù)據(jù)庫 和 elasticsearch 客觀的對比!一切都是JSON!
| Relational DB | Elasticsearch |
|---|---|
| 數(shù)據(jù)庫(database) | 索引(indices) |
| 表(tables) | types |
| 行(rows) | documents |
| 字段(columns) | fields |
elasticsearch(集群)中可以包含多個索引(數(shù)據(jù)庫),每個索引中可以包含多個類型(表),每個類型下又包含多 個文檔(行),每個文檔中又包含多個字段(列)。
物理設(shè)計:
elasticsearch 在后臺把每個索引劃分成多個分片,每分分片可以在集群中的不同服務(wù)器間遷移
一個人就是一個集群!默認(rèn)的集群名稱就是 elaticsearh

邏輯設(shè)計:
一個索引類型中,包含多個文檔,比如說文檔1,文檔2。 當(dāng)我們索引一篇文檔時,可以通過這樣的一各順序找到 它: 索引 ? 類型 ? 文檔ID ,通過這個組合我們就能索引到某個具體的文檔。 注意:ID不必是整數(shù),實際上它是個字 符串。
文檔
就是我們的一條條數(shù)據(jù)
user
1 zhangsan 18
2 kuangshen 3
之前說elasticsearch是面向文檔的,那么就意味著索引和搜索數(shù)據(jù)的最小單位是文檔,elasticsearch中,文檔有幾個 重要屬性 :
- 自我包含,一篇文檔同時包含字段和對應(yīng)的值,也就是同時包含 key:value!
- 可以是層次型的,一個文檔中包含自文檔,復(fù)雜的邏輯實體就是這么來的! {就是一個json對象!fastjson進(jìn)行自動轉(zhuǎn)換!}
- 靈活的結(jié)構(gòu),文檔不依賴預(yù)先定義的模式,我們知道關(guān)系型數(shù)據(jù)庫中,要提前定義字段才能使用,在elasticsearch中,對于字段是非常靈活的,有時候,我們可以忽略該字段,或者動態(tài)的添加一個新的字段。
盡管我們可以隨意的新增或者忽略某個字段,但是,每個字段的類型非常重要,比如一個年齡字段類型,可以是字符 串也可以是整形。因為elasticsearch會保存字段和類型之間的映射及其他的設(shè)置。這種映射具體到每個映射的每種類型,這也是為什么在elasticsearch中,類型有時候也稱為映射類型。
類型

類型是文檔的邏輯容器,就像關(guān)系型數(shù)據(jù)庫一樣,表格是行的容器。 類型中對于字段的定義稱為映射,比如 name 映 射為字符串類型。 我們說文檔是無模式的,它們不需要擁有映射中所定義的所有字段,比如新增一個字段,那么elasticsearch是怎么做的呢?elasticsearch會自動的將新字段加入映射,但是這個字段的不確定它是什么類型,elasticsearch就開始猜,如果這個值是18,那么elasticsearch會認(rèn)為它是整形。 但是elasticsearch也可能猜不對, 所以最安全的方式就是提前定義好所需要的映射,這點跟關(guān)系型數(shù)據(jù)庫殊途同歸了,先定義好字段,然后再使用,別 整什么幺蛾子。
索引
就是數(shù)據(jù)庫!
索引是映射類型的容器,elasticsearch中的索引是一個非常大的文檔集合。索引存儲了映射類型的字段和其他設(shè)置。 然后它們被存儲到了各個分片上了。 我們來研究下分片是如何工作的。
物理設(shè)計 :節(jié)點和分片 如何工作

一個集群至少有一個節(jié)點,而一個節(jié)點就是一個elasricsearch進(jìn)程,節(jié)點可以有多個索引默認(rèn)的,如果你創(chuàng)建索引,那么索引將會有個5個分片 ( primary shard ,又稱主分片 ) 構(gòu)成的,每一個主分片會有一個副本 ( replica shard ,又稱復(fù)制分片 )

上圖是一個有3個節(jié)點的集群,可以看到主分片和對應(yīng)的復(fù)制分片都不會在同一個節(jié)點內(nèi),這樣有利于某個節(jié)點掛掉 了,數(shù)據(jù)也不至于丟失。 實際上,一個分片是一個Lucene索引,一個包含倒排索引的文件目錄,倒排索引的結(jié)構(gòu)使 得elasticsearch在不掃描全部文檔的情況下,就能告訴你哪些文檔包含特定的關(guān)鍵字。 不過,等等,倒排索引是什 么鬼?
倒排索引
elasticsearch使用的是一種稱為倒排索引的結(jié)構(gòu),采用Lucene倒排索作為底層。這種結(jié)構(gòu)適用于快速的全文搜索, 一個索引由文檔中所有不重復(fù)的列表構(gòu)成,對于每一個詞,都有一個包含它的文檔列表。 例如,現(xiàn)在有兩個文檔, 每個文檔包含如下內(nèi)容:
Study every day, good good up to forever # 文檔1包含的內(nèi)容
To forever, study every day, good good up # 文檔2包含的內(nèi)容
為了創(chuàng)建倒排索引,我們首先要將每個文檔拆分成獨立的詞(或稱為詞條或者tokens),然后創(chuàng)建一個包含所有不重 復(fù)的詞條的排序列表,然后列出每個詞條出現(xiàn)在哪個文檔 :
| term | doc_1 | doc_2 |
|---|---|---|
| Study | √ | x |
| To | x | x |
| every | √ | √ |
| forever | √ | √ |
| day | √ | √ |
| study | x | √ |
| good | √ | √ |
| every | √ | √ |
| to | √ | x |
| up | √ | √ |
現(xiàn)在,我們試圖搜索 to forever,只需要查看包含每個詞條的文檔 score
| term | doc_1 | doc_2 |
|---|---|---|
| to | √ | × |
| forever | √ | √ |
| total | 2 | 1 |
兩個文檔都匹配,但是第一個文檔比第二個匹配程度更高。如果沒有別的條件,現(xiàn)在,這兩個包含關(guān)鍵字的文檔都將返回。
再來看一個示例,比如我們通過博客標(biāo)簽來搜索博客文章。那么倒排索引列表就是這樣的一個結(jié)構(gòu) :

如果要搜索含有 python 標(biāo)簽的文章,那相對于查找所有原始數(shù)據(jù)而言,查找倒排索引后的數(shù)據(jù)將會快的多。只需要 查看標(biāo)簽這一欄,然后獲取相關(guān)的文章ID即可。完全過濾掉無關(guān)的所有數(shù)據(jù),提高效率!
elasticsearch的索引和Lucene的索引對比
在elasticsearch中, 索引 (庫)這個詞被頻繁使用,這就是術(shù)語的使用。 在elasticsearch中,索引被分為多個分片,每份 分片是一個Lucene的索引。所以一個elasticsearch索引是由多個Lucene索引組成的。別問為什么,誰讓elasticsearch使用Lucene作為底層呢! 如無特指,說起索引都是指elasticsearch的索引。
5. IK分詞器插件
什么是IK分詞器?
分詞:即把一段中文或者別的劃分成一個個的關(guān)鍵字,我們在搜索時候會把自己的信息進(jìn)行分詞,會把數(shù)據(jù)庫中或者索引庫中的數(shù)據(jù)進(jìn)行分詞,然后進(jìn)行一個匹配操作,默認(rèn)的中文分詞是將每個字看成一個詞,比如 “我愛狂神” 會被分為"我","愛","狂","神",這顯然是不符合要求的,所以我們需要安裝中文分詞器ik來解決這個問題。
如果要使用中文,建議使用ik分詞器!
IK提供了兩個分詞算法:ik_smart 和 ik_max_word,其中 ik_smart 為最少切分,ik_max_word為最細(xì)粒度劃分!
安裝
-
下載完畢之后,放入到我們的elasticsearch 插件即可!
-
重啟觀察ES,可以看到ik分詞器被加載了!
-
elasticsearch-plugin 可以通過這個命令來查看加載進(jìn)來的插件
使用kibana測試!
查看不同的分詞效果
其中 ik_smart 為最少切分

ik_max_word為最細(xì)粒度劃分!窮盡詞庫的可能!字典!

我們輸入 超級喜歡狂神說Java

發(fā)現(xiàn)問題:狂神說被拆開了!
這種自己需要的詞,需要自己加到我們的分詞器的字典中!
ik 分詞器增加自己的配置!

重啟es,看細(xì)節(jié)!

再次測試一下狂神說,看下效果!

6. Rest風(fēng)格說明
一種軟件架構(gòu)風(fēng)格,而不是標(biāo)準(zhǔn),只是提供了一組設(shè)計原則和約束條件。它主要用于客戶端和服務(wù)器交互類的軟件。基于這個風(fēng)格設(shè)計的軟件可以更簡潔,更有層次,更易于實現(xiàn)緩存等機(jī)制。
基本Rest命令說明:
| method | url地址 | 描述 |
|---|---|---|
| PUT | localhost:9200/索引名稱/類型名稱/文檔id | 創(chuàng)建文檔(指定文檔id) |
| POST | localhost:9200/索引名稱/類型名稱 | 創(chuàng)建文檔(隨機(jī)文檔id) |
| POST | localhost:9200/索引名稱/類型名稱/文檔id/_update | 修改文檔 |
| DELETE | localhost:9200/索引名稱/類型名稱/文檔id | 刪除文檔 |
| GET | localhost:9200/索引名稱/類型名稱/文檔id | 查詢文檔通過文檔id |
| POST | localhost:9200/索引名稱/類型名稱/_search | 查詢所有數(shù)據(jù) |
7. 關(guān)于索引的基本操作
7.1 創(chuàng)建一個索引!
PUT /索引名/~類型名~/文檔id
{請求體}

完成了自動增加了索引!數(shù)據(jù)也成功的添加了,這就是我說大家在初期可以把它當(dāng)做數(shù)據(jù)庫學(xué)習(xí)的原因!

那么 name 這個字段用不用指定類型呢。畢竟我們關(guān)系型數(shù)據(jù)庫 是需要指定類型的啊 !
- 字符串類型
text 、 keyword - 數(shù)值類型
long, integer, short, byte, double, float, half_float, scaled_float - 日期類型
date - 布爾值類型
boolean - 二進(jìn)制類型
binary - 等等.....
7.2 指定字段的類型

獲得這個規(guī)則! 可以通過 GET 請求獲取具體的信息!

7.3 查看默認(rèn)的信息


如果自己的文檔字段沒有指定,那么es 就會給我們默認(rèn)配置字段類型!
擴(kuò)展: 通過命令 elasticsearch 索引情況! 通過get _cat/ 可以獲得es的當(dāng)前的很多信息!

修改 提交還是使用PUT 即可! 然后覆蓋!最新辦法!
曾經(jīng)!

現(xiàn)在的方法!

刪除索引!
通過DELETE 命令實現(xiàn)刪除、 根據(jù)你的請求來判斷是刪除索引還是刪除文檔記錄!
使用RESTFUL 風(fēng)格是我們ES推薦大家使用的!
8. 關(guān)于文檔的基本操作(重點)
基本操作
8.1 添加數(shù)據(jù)
PUT /kuangshen/user/1
{
"name": "狂神說",
"age": 23,
"desc": "一頓操作猛如虎,一看工資2500",
"tags": ["技術(shù)宅","溫暖","直男"]
}

8.2 獲取數(shù)據(jù) GET

8.3 更新數(shù)據(jù) PUT

8.4 Post _update , 推薦使用這種更新方式!

8.5 簡單地搜索!
GET kuangshen/user/1
簡答的條件查詢,可以根據(jù)默認(rèn)的映射規(guī)則,產(chǎn)生基本的查詢!


8.6 復(fù)雜操作搜索 select ( 排序,分頁,高亮,模糊查詢,精準(zhǔn)查詢!)


輸出結(jié)果,不想要那么多!

我們之后使用Java操作es ,所有的方法和對象就是這里面的 key!
排序!

分頁查詢!

數(shù)據(jù)下標(biāo)還是從0開始的,和學(xué)的所有數(shù)據(jù)結(jié)構(gòu)是一樣的!
/search/{current}/{pagesize}
布爾值查詢
must (and),所有的條件都要符合 where id = 1 and name = xxx

should(or),所有的條件都要符合 where id = 1 or name = xxx

must_not (not)

過濾器 filter

- gt 大于
- gte 大于等于
- lt 小于
- lte 小于等于!

匹配多個條件!

精確查詢!
term 查詢是直接通過倒排索引指定的詞條進(jìn)程精確查找的!
關(guān)于分詞:
- term ,直接查詢精確的
- match,會使用分詞器解析?。ㄏ确治鑫臋n,然后在通過分析的文檔進(jìn)行查詢?。?/li>
兩個類型 text keyword



多個值匹配精確查詢

高亮查詢!


9. 集成SpringBoot
找官方文檔!



-
找到原生的依賴
<dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-high-level-client</artifactId> <version>7.6.2</version> </dependency> -
找對象
- 分析這個類中的方法即可!
配置基本的項目
問題:一定要保證 我們的導(dǎo)入的依賴和我們的es 版本一致


源碼中提供對象!

雖然這里導(dǎo)入3個類,靜態(tài)內(nèi)部類,核心類就一個!
/**
* Elasticsearch rest client infrastructure configurations.
*
* @author Brian Clozel
* @author Stephane Nicoll
*/
class RestClientConfigurations {
@Configuration(proxyBeanMethods = false)
static class RestClientBuilderConfiguration {
// RestClientBuilder
@Bean
@ConditionalOnMissingBean
RestClientBuilder elasticsearchRestClientBuilder(RestClientProperties
properties,
ObjectProvider<RestClientBuilderCustomizer> builderCustomizers) {
HttpHost[] hosts =
properties.getUris().stream().map(HttpHost::create).toArray(HttpHost[]::new);
RestClientBuilder builder = RestClient.builder(hosts);
PropertyMapper map = PropertyMapper.get();
map.from(properties::getUsername).whenHasText().to((username) -> {
CredentialsProvider credentialsProvider = new
BasicCredentialsProvider();
Credentials credentials = new
UsernamePasswordCredentials(properties.getUsername(),
properties.getPassword());
credentialsProvider.setCredentials(AuthScope.ANY, credentials);
builder.setHttpClientConfigCallback(
(httpClientBuilder) ->
httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider));
});
builder.setRequestConfigCallback((requestConfigBuilder) -> {
map.from(properties::getConnectionTimeout).whenNonNull().asInt(Duration::toMill
is)
.to(requestConfigBuilder::setConnectTimeout);
map.from(properties::getReadTimeout).whenNonNull().asInt(Duration::toMillis)
.to(requestConfigBuilder::setSocketTimeout);
return requestConfigBuilder;
});
builderCustomizers.orderedStream().forEach((customizer) ->
customizer.customize(builder));
return builder;
}
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RestHighLevelClient.class)
static class RestHighLevelClientConfiguration {
// RestHighLevelClient 高級客戶端,也是我們這里要講,后面項目會用到的客戶端
@Bean
@ConditionalOnMissingBean
RestHighLevelClient elasticsearchRestHighLevelClient(RestClientBuilder
restClientBuilder) {
return new RestHighLevelClient(restClientBuilder);
}
@Bean
@ConditionalOnMissingBean
RestClient elasticsearchRestClient(RestClientBuilder builder,
ObjectProvider<RestHighLevelClient> restHighLevelClient) {
RestHighLevelClient client = restHighLevelClient.getIfUnique();
if (client != null) {
return client.getLowLevelClient();
}
return builder.build();
}
}
@Configuration(proxyBeanMethods = false)
static class RestClientFallbackConfiguration {
// RestClient 普通的客戶端!
@Bean
@ConditionalOnMissingBean
RestClient elasticsearchRestClient(RestClientBuilder builder) {
return builder.build();
}
}
}
具體的Api測試!
- 創(chuàng)建索引
- 判斷索引是否存在
- 刪除索引
- 創(chuàng)建文檔
- crud文檔!
@SpringBootTest
class KuangshenEsApiApplicationTests {
// 面向?qū)ο髞聿僮? @Autowired
@Qualifier("restHighLevelClient")
private RestHighLevelClient client;
// 測試索引的創(chuàng)建 Request PUT kuang_index
@Test
void testCreateIndex() throws IOException {
// 1、創(chuàng)建索引請求
CreateIndexRequest request = new CreateIndexRequest("kuang_index");
// 2、客戶端執(zhí)行請求 IndicesClient,請求后獲得響應(yīng)
CreateIndexResponse createIndexResponse =
client.indices().create(request, RequestOptions.DEFAULT);
System.out.println(createIndexResponse);
}
// 測試獲取索引,判斷其是否存在
@Test
void testExistIndex() throws IOException {
GetIndexRequest request = new GetIndexRequest("kuang_index2");
boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
System.out.println(exists);
}
// 測試刪除索引
@Test
void testDeleteIndex() throws IOException {
DeleteIndexRequest request = new DeleteIndexRequest("kuang_index");
// 刪除
AcknowledgedResponse delete = client.indices().delete(request,
RequestOptions.DEFAULT);
System.out.println(delete.isAcknowledged());
}
// 測試添加文檔
@Test
void testAddDocument() throws IOException {
// 創(chuàng)建對象
User user = new User("狂神說", 3);
// 創(chuàng)建請求
IndexRequest request = new IndexRequest("kuang_index");
// 規(guī)則 put /kuang_index/_doc/1
request.id("1");
request.timeout(TimeValue.timeValueSeconds(1));
request.timeout("1s");
// 將我們的數(shù)據(jù)放入請求 json
request.source(JSON.toJSONString(user), XContentType.JSON);
// 客戶端發(fā)送請求 , 獲取響應(yīng)的結(jié)果
IndexResponse indexResponse = client.index(request,
RequestOptions.DEFAULT);
System.out.println(indexResponse.toString()); //
System.out.println(indexResponse.status()); // 對應(yīng)我們命令返回的狀態(tài)
CREATED
}
// 獲取文檔,判斷是否存在 get /index/doc/1
@Test
void testIsExists() throws IOException {
GetRequest getRequest = new GetRequest("kuang_index", "1");
// 不獲取返回的 _source 的上下文了
getRequest.fetchSourceContext(new FetchSourceContext(false));
getRequest.storedFields("_none_");
boolean exists = client.exists(getRequest, RequestOptions.DEFAULT);
System.out.println(exists);
}
// 獲得文檔的信息
@Test
void testGetDocument() throws IOException {
GetRequest getRequest = new GetRequest("kuang_index", "1");
GetResponse getResponse = client.get(getRequest,
RequestOptions.DEFAULT);
System.out.println(getResponse.getSourceAsString()); // 打印文檔的內(nèi)容
System.out.println(getResponse); // 返回的全部內(nèi)容和命令式一樣的
}
// 更新文檔的信息
@Test
void testUpdateRequest() throws IOException {
UpdateRequest updateRequest = new UpdateRequest("kuang_index","1");
updateRequest.timeout("1s");
User user = new User("狂神說Java", 18);
updateRequest.doc(JSON.toJSONString(user),XContentType.JSON);
UpdateResponse updateResponse = client.update(updateRequest,
RequestOptions.DEFAULT);
System.out.println(updateResponse.status());
}
// 刪除文檔記錄
@Test
void testDeleteRequest() throws IOException {
DeleteRequest request = new DeleteRequest("kuang_index","1");
request.timeout("1s");
DeleteResponse deleteResponse = client.delete(request,
RequestOptions.DEFAULT);
System.out.println(deleteResponse.status());
}
// 特殊的,真的項目一般都會批量插入數(shù)據(jù)!
@Test
void testBulkRequest() throws IOException {
BulkRequest bulkRequest = new BulkRequest();
bulkRequest.timeout("10s");
ArrayList<User> userList = new ArrayList<>();
userList.add(new User("kuangshen1",3));
userList.add(new User("kuangshen2",3));
userList.add(new User("kuangshen3",3));
userList.add(new User("qinjiang1",3));
userList.add(new User("qinjiang1",3));
userList.add(new User("qinjiang1",3));
// 批處理請求
for (int i = 0; i < userList.size() ; i++) {
// 批量更新和批量刪除,就在這里修改對應(yīng)的請求就可以了
bulkRequest.add(
new IndexRequest("kuang_index")
.id(""+(i+1))
.source(JSON.toJSONString(userList.get(i)),XContentType.JSON));
}
BulkResponse bulkResponse = client.bulk(bulkRequest,
RequestOptions.DEFAULT);
System.out.println(bulkResponse.hasFailures()); // 是否失敗,返回 false 代表
成功!
}
// 查詢
// SearchRequest 搜索請求
// SearchSourceBuilder 條件構(gòu)造
// HighlightBuilder 構(gòu)建高亮
// TermQueryBuilder 精確查詢
// MatchAllQueryBuilder
// xxx QueryBuilder 對應(yīng)我們剛才看到的命令!
@Test
void testSearch() throws IOException {
SearchRequest searchRequest = new SearchRequest("kuang_index");
// 構(gòu)建搜索條件
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.highlighter()
// 查詢條件,我們可以使用 QueryBuilders 工具來實現(xiàn)
// QueryBuilders.termQuery 精確
// QueryBuilders.matchAllQuery() 匹配所有
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name",
"qinjiang1");
// MatchAllQueryBuilder matchAllQueryBuilder =
QueryBuilders.matchAllQuery();
sourceBuilder.query(termQueryBuilder);
sourceBuilder.timeout(new TimeValue(60,TimeUnit.SECONDS));
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = client.search(searchRequest,
RequestOptions.DEFAULT);
System.out.println(JSON.toJSONString(searchResponse.getHits()));
System.out.println("=================================");
for (SearchHit documentFields : searchResponse.getHits().getHits()) {
System.out.println(documentFields.getSourceAsMap());
}
}
}
參考:B站狂神說Java








