目錄html
發表日期:2019年9月18日java
ElasticSearch是一個集數據存儲、數據搜索和數據分析爲一體的系統。它是分佈式的,因此能利用分佈式來提升其處理能力,具備高可用性和高伸縮性。若是你須要一個可以提供高性能的搜索服務的系統,那麼它或許是一個好的選擇。mysql
ElasticSearch是一個搜索系統,搜索就是從數據集合中搜索出咱們想要的數據,例如從大量的商品數據中搜索出咱們想要的某類商品。
如今提一個需求,例如我有一個「文章」的表,我想搜索文章表中字段content中包含有'java'的數據。
若是你不使用ES,那麼從開發角度來講,日常咱們都是使用關係型數據庫系統來存儲數據,而後使用相似select name,age,address from student where name like '%李%'
的語句經過模糊匹配來搜索符合指定條件的數據的。(對應到上面的需求應該是select name,author,content from article where content like '%java%'
)算法但其實上面這種基於模糊匹配的搜索方式的效率是比較低的,由於數據庫系統的搜索一般是逐一掃描的,也就是從頭至尾的來嘗試匹配,某個字段的數據越多,可能須要嘗試匹配的次數就會越多(試想一下從4000字的文章中從上到下只爲找到一個字),這種查找就好像最低級的遍歷查找(固然並非真的就是傻傻的遍歷了,各個數據庫系統都會採用各類算法來優化)。
而ElasticSearch因爲其內部創建了每一個詞的索引表,當搜索某個詞時,能夠根據這個詞從索引表中找到匹配的記錄,因此效率比較高(就好像記錄了某個詞的座標,有了座標,就能根據座標很是快地找到那個詞)。
(這裏舉個相似的栗子:相信你們都用過字典,那麼普通的數據庫搜索就好像從第一頁到最後一頁找一個詞,而ElasticSearch根據這個詞的部首結構從「部首-字的對應表」中直接查找到那個字的頁數,這個效率直接就是天差地別了!)sql另外,數據庫的搜索是根據指定詞直接查找的,它是很笨的!它不能查找到某些意義上「相似」的結果,好比我搜索「mother」,但若是某個記錄中包含「mom」這個詞,那這條記錄也應該被展現出來,而數據庫的普通搜索作不到。
而這個操做ElasticSearch就能夠作到,因爲它內部有分詞器,在創建索引的過程當中,分詞器能夠把數據中的某些詞都認爲是指定的某一個詞(好比把mother,mom統統都使用mom做爲索引詞),再用這個詞來創建索引,而後在進行搜索的時候,將輸入的詞也進行一樣的轉化,再根據這個詞從索引表中查找到符合的記錄結果,這樣就能夠把那些意義相近的結果也搜索出來。mongodb因此說,ElasticSearch解決了普通全文搜索的搜索效率低下和搜索不智能的問題。typescript
介紹兩個搜索方法:順序掃描查找、全文搜索數據庫
上面有說到數據庫的搜索和ElasticSearch的搜索。
常見的關係型數據庫的針對某個字段中的數據的搜索是順序掃描查找,從頭至尾去嘗試匹配,也就是所謂的遍歷查找,固然算法可能沒有那麼低級。(如今一些數據庫系統也在嘗試優化全文搜索功能。)json而ElasticSearch的搜索是全文搜索,而什麼是全文搜索?
全文搜索能夠根據必定方式把非結構化的數據對應到一種結構化的標識,從而能夠經過標識來檢索到指定的非結構化的數據記錄。
這句話可能有點難以理解,舉個例子理解,好比有一大堆食物你須要去認識,食物自己能夠被認做是非結構化的數據,由於他們都是獨特的,但若是咱們利用他們的顏色來劃分的話就能夠初步地將他們進行結構化劃分,這個就是一種簡單的將數據結構化的手段。在ElasticSearch中,這個把非結構化的數據對應到一種結構化的標識的方式就是倒排索引,下面介紹倒排索引來理解這個概念。windows在ElasticSearch中,處理這些非結構化的數據的方式就是創建倒排索引(Inverted Index)。
什麼是倒排索引呢?
倒排索引把數據進行了拆分(好比某個字段的數據爲hello world,那麼就會被拆分紅hello和world),咱們使用這些拆分的詞來做爲索引詞來創建索引表,在以hello爲索引詞的記錄中,有對hello world
的指向,world也是如此。
固然,這裏的拆分並非真實的拆分,原始的數據依然存儲在elasticsearch中,咱們另外建立了一個索引文件來存儲。下面是一個使用倒排索引搜索的示例
1.首先,假設咱們有一個字段的數據是"I thank my mother",當咱們把這個數據存儲到ElasticSearch中,ElasticSearch內部使用分詞器進行處理數據,分詞器用於將非結構化數據中的詞進行拆分和轉換,因而把"I thank my mother"拆解成了"I"、"thank"、"my"、"mother"。
2.當把數據拆分出來後(拆分紅的數據單位咱們稱爲「詞」),就會把這些詞創建索引,ElasticSearch內部有一個索引表,用於創建詞與數據的對應,結構相似以下(真實格式還會有詞的頻率、數據長度等信息),索引表存儲了詞和詞所在記錄的ID集合,因此能夠經過某個詞來快速搜索出相關的記錄,好比搜索"I",那麼會返回1和2,而後能夠快速根據ID來獲取對應的數據。【請注意,下圖只是方便理解,並非真實的格式】
3.而後咱們搜索的時候,分詞器也先把咱們輸入的內容處理(爲了與索引表的詞統一),而後再從索引表中查找,返回對應的數據記錄集合。
例如我輸入mother,mother會先轉成mom,而後從索引表中找到mom,返回包含mom的記錄的ID,而後根據ID獲取對應數據,也就是「I like my mom」
Lucene也是一種搜索引擎,爲何不直接使用Lucene?
ElasticSearch實際上底層使用的就是Lucene,雖然Lucene也有不少功能,但Lucene的使用難度較大(也正是使用難度高因此ElasticSearch纔對Lucene進行封裝),並且ElasticSearc的高級功能也很強大,ES支持了多樣的數據分析。除了基本的功能,集羣能力也是一個問題,Lucene一開始沒有考慮集羣,因此對於存儲在不一樣服務器上的大量數據的交互比較麻煩,而ElasticeSearch一開始就是集羣思想的,數據存儲以一個ElasticSearch節點爲單位,多個節點的數據能夠交流。
因爲底層是Lucene,因此,對於一些elasticsearch底層的東西,有時候你徹底能夠參照Lucene,好比索引詞文件的存儲等。爲何不是Solr?
Solr也是一個知名的搜索引擎,它與ElasticSearch各有好處,Solr適用於一些非實時搜索系統(新增的數據不要求立刻查出來的),而ElasticSearch適用於一些實時搜索要求較高的系統(電商平臺等要求新商品立刻可查的系統)。由於Solr在創建索引時,搜索效率降低,實時索引搜索效率不高,而ElasticSearch創建索引的速度較快。ElasticSearch有一個很是顯著的特性"NRT":NRT全稱Near Real Time,近實時,意思是你插入的數據幾乎能夠「立刻」就能夠被搜索出來。這也是爲何它能使用在實時更新要求高的場景的緣由。
上面提了詞的拆分,這裏提一些關於底層的搜索處理的內容。介紹一下ElasticSearch另外一個協助搜索的關鍵組件--分詞器。ElasticSearch的全文搜索離不開分詞器的幫助。
分詞器一般由分解器tokenizer和詞元過濾器token filter組成。
分詞器對數據的分詞處理:爲了提升索引的效率,ElasticSearch會數據進行處理,處理方式主要有字符過濾、詞轉換、詞拆分
字符過濾:過濾一些特殊字符,例如&
、||
、html標籤,由於這些詞一般搜索意義不大。詞轉換:把一些意義相同的詞統一轉成一個詞,(同詞義轉換)好比mom,mother統一轉成mom;(大小寫轉換)he,He統一歸爲He;還處理一些詞意義不大的詞(停用詞清除),好比英文的「the」,「to」,這些詞使用頻率很高,但沒有具體意義。
詞拆分:進行數據的拆分,拆分紅詞,好比把
good morning,mom
拆分紅good
,morining
,mom
。另外,詞拆分並不徹底是按照數據的最小單位分解的,某一些分詞器會把一些詞進行組合,由於一些詞的組合起來纔有索引的意義,好比中文的一些詞一般要組合起來纔有意義,好比「大」和「家」要組成「你們」纔有比較具體的意義,這是爲了確保索引詞的最小單位是有意義的(好比英文mom的最小單位是m,o,m,內部的分詞器要可以區分出mom整個是有意義的才能夠確保是採用mom做爲索引,而不是採用m和o,也正是由於這個問題,因此英文分詞器不能用於中文分詞器)。【分詞器有不少個,默認的分詞器是不能適當對中文數據分詞的,它只能把一個個數據按最小的單位拆分,由於英文分詞器不能分清楚怎麼把詞拆分纔有意義,因爲配置分詞器是一個較爲靠後的知識點,因此前期將以英文數據爲測試數據。】分詞文件的存儲:
分詞文件通常包括三種文件:詞典文件,頻率文件,位置文件。
詞典文件保存了關鍵詞(索引詞),還保留了指向頻率文件和位置文件的指針。
頻率文件記錄了詞出現的頻率。
位置文件記錄了這些詞出如今哪些數據中。
首先要說的是,ElasticSearch是一款軟件,有點相似MySQL,咱們要操做它的時候,也要給它發送它能識別的命令,而ElasticSearch是面向restful(不知道restful的自查吧)的,因此咱們發送的命令是有點相似發送http請求的。
mysql是3306端口,而elasticsearch支持9200和9300端口操做,其中9200面向http,9300面向tcp。9200可以使用普通的http請求來操做elasticsearch,9300須要鏈接elasticsearch以後再執行命令。
咱們首先來搭建好學習環境,主要是ElasticSearch和Kibana。【請注意,Elasticsearch依賴Java環境】
【Kibana是可選的,下面會介紹一下基於postman的對ElasticSearch操做。】,Kibana是一款對ElasticSearch進行管理的軟件,咱們能夠在Kibana上執行ElasticSearch的命令。
下載:
安裝:
運行:
elasticsearch-6.2.0\bin
中運行elasticsearch.bat
,當提示「started」時,表示運行成功。kibana-6.2.0-windows-x86_64\bin
中運行kibana.bat
,當提示「Server running at http://localhost:5601」時,表示運行成功。【要先運行ElasticSearch再運行Kibana,由於它要與ElasticSearch進行鏈接】ElasticSearch默認的TCP服務端口是9300,Kibana的服務端口是5601,當咱們啓動了Kibana以後,它會默認幫咱們鏈接上9300,因此咱們能夠從http://localhost:5601
中進入Kibana的管理界面來管理ElasticSearch。
若是你是第一次使用,那麼ElasticSearch會自動建立一個名爲elasticsearch
的集羣,Kibana會在這個節點中初始化一個index
咱們在Kibana的DevTools中執行一些命令來看一下ElasticSearch。【從http://localhost:5601
中進入】
在輸入命令GET /_cat/health?v
後,點擊該行右側的執行按鈕。【GET /_cat/health?v
是查看集羣的健康狀態的命令】
而後就能夠在右側的結果窗口中查看命令執行結果。
【你如今大概都是看不懂命令的意義和結果的意義的了,不過你應該知道哪裏輸入命令和哪裏看執行結果了】
postman是一個用來發請求的軟件,可使用restful風格的請求來操做elasticsearch。
好比上面的查看集羣的命令:GET /_cat/health?v
轉成基於restful的是:http://localhost:9200/_cat/health?v
即IP:9200+命令
,其中9200是用於接收restful請求的es監聽端口。
上面的第一次使用並無涉及到具體的知識,只是讓你熟悉一下如何使用Kibana來操做ElasticSearch。下面講到具體知識點纔會具體使用。
數據存儲在shard中,shard中的數據是以文檔document爲單位的。document存儲在index和type劃分的邏輯空間中。document以json爲格式,每個key-value中key能夠稱爲域Field。
{ "book_id": 1, "book_name": "Java Core ", "book_desc": "A good book, you know!", "category_id": "1", "category_name": "Computer" }
請求方法 | 對應操做 | 說明 |
---|---|---|
GET | 讀取 | 獲取數據 |
POST | 新增 | 新增數據 |
PUT | 修改 | 修改數據或增長數據 |
DELETE | 刪除 | 刪除數據 |
前面提了一下index,type,document,說了ElasticSearch的邏輯存儲空間。
下面以兩個實例:「寫document->讀document」和「寫document->搜索document「來初步演示一下如何存儲數據和獲取數據。
若是咱們要向ElasticSearch中寫入一份數據(document),命令的語法應該以下:
PUT /index名稱/type名稱/document的ID { document的數據 }
上面的語法的意思就是向一個index的一個type中插入一個document,document用id做爲標識,後面咱們取document的數據也將以這個id爲依據。其中index,type是能夠不須要咱們預建立的,在咱們還不會如何建立index和type的時候,你能夠先隨便打個名字(若是ElasticSearch檢測到咱們輸入的index和type是不存在的,那麼它就會以默認的規則幫咱們建立出來)。
請在kibana的devtool中執行如下命令來存儲一份document:
PUT /douban/book/1 { "book_id":1, "book_name":"A Clockwork Orange", "author":"Anthony Burgess", "summary":"Fully restored edition of Anthony Burgess' original text of A Clockwork Orange, with a glossary of the teen slang 'Nadsat', explanatory notes, pages from the original typescript, interviews, articles and reviews Edited by Andrew Biswell With a Foreword by Martin Amis 'It is a horrorshow story ...' Fifteen-year-old Alex likes lashings of ultraviolence. He and his gang of friends rob, kill and rape their way through a nightmarish future, until the State puts a stop to his riotous excesses. But what will his re-education mean? A dystopian horror, a black comedy, an exploration of choice, A Clockwork Orange is also a work of exuberant invention which created a new language for its characters. This critical edition restores the text of the novel as Anthony Burgess originally wrote it, and includes a glossary of the teen slang 'Nadsat', explanatory notes, pages from the original typescript, interviews, articles and reviews, shedding light on the enduring fascination of the novel's 'sweet and juicy criminality'. Anthony Burgess was born in Manchester in 1917 and educated at Xaverian College and Manchester University. He spent six years in the British Army before becoming a schoolmaster and colonial education officer in Malaya and Brunei. After the success of his Malayan Trilogy, he became a full-time writer in 1959. His books have been published all over the world, and they include The Complete Enderby, Nothing Like the Sun, Napoleon Symphony, Tremor of Intent, Earthly Powers and A Dead Man in Deptford. Anthony Burgess died in London in 1993. Andrew Biswell is the Professor of Modern Literature at Manchester Metropolitan University and the Director of the International Anthony Burgess Foundation. His publications include a biography, The Real Life of Anthony Burgess, which won the Portico Prize in 2006. He is currently editing the letters and short stories of Anthony Burgess.", "press":"Penguin Classic", "publication_date":"2000-02-22" }
若是要獲取ES中存儲的document,命令的語法應該以下:
GET /index名/type名/id
同樣的,請在kibana中執行下述命令來獲取咱們上面存儲的document:
GET /douban/book/1
返回結果:【返回index名稱,type名稱,id,原始文檔等數據】
很明顯地,咱們獲取到了咱們剛剛存儲進去的數據。
同樣的,咱們寫多一份數據進ES中:
PUT /douban/book/2 { "book_id":2, "book_name":"Kubernetes in Action", "author":"Marko Luksa", "summary":"Kubernetes in Action teaches you to use Kubernetes to deploy container-based distributed applications. You'll start with an overview of Docker and Kubernetes before building your first Kubernetes cluster. You'll gradually expand your initial application, adding features and deepening your knowledge of Kubernetes architecture and operation. As you navigate this comprehensive guide, you'll explore high-value topics like monitoring, tuning, and scaling.Kubernetes is Greek for \"helmsman,\" your guide through unknown waters. The Kubernetes container orchestration system safely manages the structure and flow of a distributed application, organizing containers and services for maximum efficiency. Kubernetes serves as an operating system for your clusters, eliminating the need to factor the underlying network and server infrastructure into your designs.", "press":"Manning Publications", "publish_date":"2017-08-31" }
下面將演示搜索的功能,搜索的其中一種語法是:
GET /index名/type名/_search { "query":{ "match":{ "字段Field名稱":"用於搜索的關鍵字" } } }
那麼,根據咱們以前存儲的數據,若是咱們要查詢summary字段有Orange的數據的話,命令以下:
GET /douban/book/_search { "query": { "match": { "summary":"Orange" } } }
返回的結果:
--To Be Continue