Elasticsearch 权威教程 - 入门
入門
Elasticsearch是一個實時分布式搜索和分析引擎。它讓你以前所未有的速度處理大數據成為可能。
它用于全文搜索、結構化搜索、分析以及將這三者混合使用:
維基百科使用Elasticsearch提供全文搜索并高亮關鍵字,以及輸入實時搜索(search-as-you-type)和搜索糾錯(did-you-mean)等搜索建議功能。
英國衛報使用Elasticsearch結合用戶日志和社交網絡數據提供給他們的編輯以實時的反饋,以便及時了解公眾對新發表的文章的回應。
StackOverflow結合全文搜索與地理位置查詢,以及more-like-this功能來找到相關的問題和答案。
Github使用Elasticsearch檢索1300億行的代碼。
但是Elasticsearch不僅用于大型企業,它還讓像DataDog以及Klout這樣的創業公司將最初的想法變成可擴展的解決方案。Elasticsearch可以在你的筆記本上運行,也可以在數以百計的服務器上處理PB級別的數據。
Elasticsearch所涉及到的每一項技術都不是創新或者革命性的,全文搜索,分析系統以及分布式數據庫這些早就已經存在了。它的革命性在于將這些獨立且有用的技術整合成一個一體化的、實時的應用。它對新用戶的門檻很低,當然它也會跟上你技能和需求增長的步伐。
如果你打算看這本書,說明你已經有數據了,但光有數據是不夠的,除非你能對這些數據做些什么事情。
很不幸,現在大部分數據庫在提取可用知識方面顯得異常無能。的確,它們能夠通過時間戳或者精確匹配做過濾,但是它們能夠進行全文搜索,處理同義詞和根據相關性給文檔打分嗎?它們能根據同一份數據生成分析和聚合的結果嗎?最重要的是,它們在沒有大量工作進程(線程)的情況下能做到對數據的實時處理嗎?
這就是Elasticsearch存在的理由:Elasticsearch鼓勵你瀏覽并利用你的數據,而不是讓它爛在數據庫里,因為在數據庫里實在太難查詢了。
Elasticsearch是你新認識的最好的朋友。
為了搜索,你懂的
Elasticsearch是一個基于Apache Lucene(TM)的開源搜索引擎。無論在開源還是專有領域,Lucene可以被認為是迄今為止最先進、性能最好的、功能最全的搜索引擎庫。
但是,Lucene只是一個庫。想要使用它,你必須使用Java來作為開發語言并將其直接集成到你的應用中,更糟糕的是,Lucene非常復雜,你需要深入了解檢索的相關知識來理解它是如何工作的。
Elasticsearch也使用Java開發并使用Lucene作為其核心來實現所有索引和搜索的功能,但是它的目的是通過簡單的RESTful API來隱藏Lucene的復雜性,從而讓全文搜索變得簡單。
不過,Elasticsearch不僅僅是Lucene和全文搜索,我們還能這樣去描述它:
- 分布式的實時文件存儲,每個字段都被索引并可被搜索
- 分布式的實時分析搜索引擎
- 可以擴展到上百臺服務器,處理PB級結構化或非結構化數據
而且,所有的這些功能被集成到一個服務里面,你的應用可以通過簡單的RESTful API、各種語言的客戶端甚至命令行與之交互。
上手Elasticsearch非常容易。它提供了許多合理的缺省值,并對初學者隱藏了復雜的搜索引擎理論。它開箱即用(安裝即可使用),只需很少的學習既可在生產環境中使用。
Elasticsearch在Apache 2 license下許可使用,可以免費下載、使用和修改。
隨著你對Elasticsearch的理解加深,你可以根據不同的問題領域定制Elasticsearch的高級特性,這一切都是可配置的,并且配置非常靈活。
模糊的歷史
多年前,一個叫做Shay Banon的剛結婚不久的失業開發者,由于妻子要去倫敦學習廚師,他便跟著也去了。在他找工作的過程中,為了給妻子構建一個食譜的搜索引擎,他開始構建一個早期版本的Lucene。
直接基于Lucene工作會比較困難,所以Shay開始抽象Lucene代碼以便Java程序員可以在應用中添加搜索功能。他發布了他的第一個開源項目,叫做“Compass”。
后來Shay找到一份工作,這份工作處在高性能和內存數據網格的分布式環境中,因此高性能的、實時的、分布式的搜索引擎也是理所當然需要的。然后他決定重寫Compass庫使其成為一個獨立的服務叫做Elasticsearch。
第一個公開版本出現在2010年2月,在那之后Elasticsearch已經成為Github上最受歡迎的項目之一,代碼貢獻者超過300人。一家主營Elasticsearch的公司就此成立,他們一邊提供商業支持一邊開發新功能,不過Elasticsearch將永遠開源且對所有人可用。
Shay的妻子依舊等待著她的食譜搜索……
安裝Elasticsearch
理解Elasticsearch最好的方式是去運行它,讓我們開始吧!
安裝Elasticsearch唯一的要求是安裝官方新版的Java,地址:www.java.com
你可以從 elasticsearch.org\/download 下載最新版本的Elasticsearch。
curl -L -O http://download.elasticsearch.org/PATH/TO/VERSION.zip <1> unzip elasticsearch-$VERSION.zip cd elasticsearch-$VERSION提示:
在生產環境安裝時,除了以上方法,你還可以使用Debian或者RPM安裝包,地址在這里:downloads page,或者也可以使用官方提供的 Puppet module 或者
Chef cookbook。
安裝Marvel
Marvel是Elasticsearch的管理和監控工具,在開發環境下免費使用。它包含了一個叫做Sense的交互式控制臺,使用戶方便的通過瀏覽器直接與Elasticsearch進行交互。
Elasticsearch線上文檔中的很多示例代碼都附帶一個View in Sense的鏈接。點擊進去,就會在Sense控制臺打開相應的實例。安裝Marvel不是必須的,但是它可以通過在你本地Elasticsearch集群中運行示例代碼而增加與此書的互動性。
Marvel是一個插件,可在Elasticsearch目錄中運行以下命令來下載和安裝:
./bin/plugin -i elasticsearch/marvel/latest你可能想要禁用監控,你可以通過以下命令關閉Marvel:
echo 'marvel.agent.enabled: false' >> ./config/elasticsearch.yml運行Elasticsearch
Elasticsearch已經準備就緒,執行以下命令可在前臺啟動:
./bin/elasticsearch啟動后,如果只有本地可以訪問,嘗試修改配置文件 elasticsearch.yml
中network.host(注意配置文件格式不是以#開頭的要空一格, :后要空一格) 為network.host: 0.0.0.0
如果想在后臺以守護進程模式運行,添加-d參數。
打開另一個終端進行測試:
curl 'http://localhost:9200/?pretty'你能看到以下返回信息:
{"status": 200,"name": "Shrunken Bones","version": {"number": "1.4.0","lucene_version": "4.10"},"tagline": "You Know, for Search" }這說明你的ELasticsearch集群已經啟動并且正常運行,接下來我們可以開始各種實驗了。
集群和節點
節點(node)是一個運行著的Elasticsearch實例。集群(cluster)是一組具有相同cluster.name的節點集合,他們協同工作,共享數據并提供故障轉移和擴展功能,當然一個節點也可以組成一個集群。
你最好找一個合適的名字來替代cluster.name的默認值,比如你自己的名字,這樣可以防止一個新啟動的節點加入到相同網絡中的另一個同名的集群中。
你可以通過修改config/目錄下的elasticsearch.yml文件,然后重啟ELasticsearch來做到這一點。當Elasticsearch在前臺運行,可以使用Ctrl-C快捷鍵終止,或者你可以調用shutdown API來關閉:
curl -XPOST 'http://localhost:9200/_shutdown'查看Marvel和Sense
如果你安裝了Marvel(作為管理和監控的工具),就可以在瀏覽器里通過以下地址訪問它:
http:\/\/localhost:9200\/_plugin\/marvel\/
你可以在Marvel中通過點擊dashboards,在下拉菜單中訪問Sense開發者控制臺,或者直接訪問以下地址:
http:\/\/localhost:9200\/_plugin\/marvel\/sense\/
與Elasticsearch交互
如何與Elasticsearch交互取決于你是否使用Java。
Java API
Elasticsearch為Java用戶提供了兩種內置客戶端:
節點客戶端(node client):
節點客戶端以無數據節點(none data node)身份加入集群,換言之,它自己不存儲任何數據,但是它知道數據在集群中的具體位置,并且能夠直接轉發請求到對應的節點上。
傳輸客戶端(Transport client):
這個更輕量的傳輸客戶端能夠發送請求到遠程集群。它自己不加入集群,只是簡單轉發請求給集群中的節點。
兩個Java客戶端都通過9300端口與集群交互,使用Elasticsearch傳輸協議(Elasticsearch Transport Protocol)。集群中的節點之間也通過9300端口進行通信。如果此端口未開放,你的節點將不能組成集群。
TIP
Java客戶端所在的Elasticsearch版本必須與集群中其他節點一致,否則,它們可能互相無法識別。
關于Java API的更多信息請查看相關章節:Java API
基于HTTP協議,以JSON為數據交互格式的RESTful API
其他所有程序語言都可以使用RESTful API,通過9200端口的與Elasticsearch進行通信,你可以使用你喜歡的WEB客戶端,事實上,如你所見,你甚至可以通過curl命令與Elasticsearch通信。
NOTE
Elasticsearch官方提供了多種程序語言的客戶端——Groovy,Javascript, .NET,PHP,Perl,Python,以及 Ruby——還有很多由社區提供的客戶端和插件,所有這些可以在文檔中找到。
向Elasticsearch發出的請求的組成部分與其它普通的HTTP請求是一樣的:
curl -X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' -d '<BODY>'- VERB HTTP方法:GET, POST, PUT, HEAD, DELETE
- PROTOCOL http或者https協議(只有在Elasticsearch前面有https代理的時候可用)
- HOST Elasticsearch集群中的任何一個節點的主機名,如果是在本地的節點,那么就叫localhost
- PORT Elasticsearch HTTP服務所在的端口,默認為9200
- PATH API路徑(例如_count將返回集群中文檔的數量),PATH可以包含多個組件,例如_cluster/stats或者_nodes/stats/jvm
- QUERY_STRING 一些可選的查詢請求參數,例如?pretty參數將使請求返回更加美觀易讀的JSON數據
- BODY 一個JSON格式的請求主體(如果請求需要的話)
舉例說明,為了計算集群中的文檔數量,我們可以這樣做:
curl -XGET 'http://localhost:9200/_count?pretty' -d ' {"query": {"match_all": {}} } 'Elasticsearch返回一個類似200 OK的HTTP狀態碼和JSON格式的響應主體(除了HEAD請求)。上面的請求會得到如下的JSON格式的響應主體:
{"count" : 0,"_shards" : {"total" : 5,"successful" : 5,"failed" : 0} }我們看不到HTTP頭是因為我們沒有讓curl顯示它們,如果要顯示,使用curl命令后跟-i參數:
curl -i -XGET 'localhost:9200/'對于本書的其余部分,我們將簡寫curl請求中重復的部分,例如主機名和端口,還有curl命令本身。
一個完整的請求形如:
curl -XGET 'localhost:9200/_count?pretty' -d ' {"query": {"match_all": {}} }'我們將簡寫成這樣:
GET /_count {"query": {"match_all": {}} }事實上,在Sense控制臺中也使用了與上面相同的格式。
面向文檔
應用中的對象很少只是簡單的鍵值列表,更多時候它擁有復雜的數據結構,比如包含日期、地理位置、另一個對象或者數組。
總有一天你會想到把這些對象存儲到數據庫中。將這些數據保存到由行和列組成的關系數據庫中,就好像是把一個豐富,信息表現力強的對象拆散了放入一個非常大的表格中:你不得不拆散對象以適應表模式(通常一列表示一個字段),然后又不得不在查詢的時候重建它們。
Elasticsearch是面向文檔(document oriented)的,這意味著它可以存儲整個對象或文檔(document)。然而它不僅僅是存儲,還會索引(index)每個文檔的內容使之可以被搜索。在Elasticsearch中,你可以對文檔(而非成行成列的數據)進行索引、搜索、排序、過濾。這種理解數據的方式與以往完全不同,這也是Elasticsearch能夠執行復雜的全文搜索的原因之一。
JSON
ELasticsearch使用**Javascript對象符號(JavaScript
Object Notation),也就是**JSON,作為文檔序列化格式。JSON現在已經被大多語言所支持,而且已經成為NoSQL領域的標準格式。它簡潔、簡單且容易閱讀。
以下使用JSON文檔來表示一個用戶對象:
{"email": "john@smith.com","first_name": "John","last_name": "Smith","info": {"bio": "Eco-warrior and defender of the weak","age": 25,"interests": [ "dolphins", "whales" ]},"join_date": "2014/05/01" }盡管原始的user對象很復雜,但它的結構和對象的含義已經被完整的體現在JSON中了,在Elasticsearch中將對象轉化為JSON并做索引要比在表結構中做相同的事情簡單的多。
NOTE
盡管幾乎所有的語言都有相應的模塊用于將任意數據結構轉換為JSON,但每種語言處理細節不同。具體請查看“serialization” or “marshalling”兩個用于處理JSON的模塊。Elasticsearch官方客戶端會自動為你序列化和反序列化JSON。
開始第一步
我們現在開始進行一個簡單教程,它涵蓋了一些基本的概念介紹,比如索引(indexing)、搜索(search)以及聚合(aggregations)。通過這個教程,我們可以讓你對Elasticsearch能做的事以及其易用程度有一個大致的感覺。
我們接下來將陸續介紹一些術語和基本的概念,但就算你沒有馬上完全理解也沒有關系。我們將在本書的各個章節中更加深入的探討這些內容。
所以,坐下來,開始以旋風般的速度來感受Elasticsearch的能力吧!
讓我們建立一個員工目錄
假設我們剛好在Megacorp工作,這時人力資源部門出于某種目的需要讓我們創建一個員工目錄,這個目錄用于促進人文關懷和用于實時協同工作,所以它有以下不同的需求:
- 數據能夠包含多個值的標簽、數字和純文本。
- 檢索任何員工的所有信息。
- 支持結構化搜索,例如查找30歲以上的員工。
- 支持簡單的全文搜索和更復雜的短語(phrase)搜索
- 高亮搜索結果中的關鍵字
- 能夠利用圖表管理分析這些數據
索引員工文檔
我們首先要做的是存儲員工數據,每個文檔代表一個員工。在Elasticsearch中存儲數據的行為就叫做索引(indexing),不過在索引之前,我們需要明確數據應該存儲在哪里。
在Elasticsearch中,文檔歸屬于一種類型(type),而這些類型存在于索引(index)中,我們可以畫一些簡單的對比圖來類比傳統關系型數據庫:
Relational DB -> Databases -> Tables -> Rows -> Columns Elasticsearch -> Indices -> Types -> Documents -> FieldsElasticsearch集群可以包含多個索引(indices)(數據庫),每一個索引可以包含多個類型(types)(表),每一個類型包含多個文檔(documents)(行),然后每個文檔包含多個字段(Fields)(列)。
「索引」含義的區分
你可能已經注意到索引(index)這個詞在Elasticsearch中有著不同的含義,所以有必要在此做一下區分:
- 索引(名詞)
如上文所述,一個索引(index)就像是傳統關系數據庫中的數據庫,它是相關文檔存儲的地方,index的復數是indices 或indexes。
- 索引(動詞)
「索引一個文檔」表示把一個文檔存儲到索引(名詞)里,以便它可以被檢索或者查詢。這很像SQL中的INSERT關鍵字,差別是,如果文檔已經存在,新的文檔將覆蓋舊的文檔。
- 倒排索引
傳統數據庫為特定列增加一個索引,例如B-Tree索引來加速檢索。Elasticsearch和Lucene使用一種叫做倒排索引(inverted index)的數據結構來達到相同目的。
默認情況下,文檔中的所有字段都會被索引(擁有一個倒排索引),只有這樣他們才是可被搜索的。
我們將會在倒排索引章節中更詳細的討論。
所以為了創建員工目錄,我們將進行如下操作:
- 為每個員工的文檔(document)建立索引,每個文檔包含了相應員工的所有信息。
- 每個文檔的類型為employee。
- employee類型歸屬于索引megacorp。
- megacorp索引存儲在Elasticsearch集群中。
實際上這些都是很容易的(盡管看起來有許多步驟)。我們能通過一個命令執行完成的操作:
PUT /megacorp/employee/1 {"first_name" : "John","last_name" : "Smith","age" : 25,"about" : "I love to go rock climbing","interests": [ "sports", "music" ] }我們看到path:/megacorp/employee/1包含三部分信息:
| megacorp | 索引名 |
| employee | 類型名 |
| 1 | 這個員工的ID |
請求實體(JSON文檔),包含了這個員工的所有信息。他的名字叫“John Smith”,25歲,喜歡攀巖。
很簡單吧!它不需要你做額外的管理操作,比如創建索引或者定義每個字段的數據類型。我們能夠直接索引文檔,Elasticsearch已經內置所有的缺省設置,所有管理操作都是透明的。
接下來,讓我們在目錄中加入更多員工信息:
PUT /megacorp/employee/2 {"first_name" : "Jane","last_name" : "Smith","age" : 32,"about" : "I like to collect rock albums","interests": [ "music" ] }PUT /megacorp/employee/3 {"first_name" : "Douglas","last_name" : "Fir","age" : 35,"about": "I like to build cabinets","interests": [ "forestry" ] }檢索文檔
現在Elasticsearch中已經存儲了一些數據,我們可以根據業務需求開始工作了。第一個需求是能夠檢索單個員工的信息。
這對于Elasticsearch來說非常簡單。我們只要執行HTTP GET請求并指出文檔的“地址”——索引、類型和ID既可。根據這三部分信息,我們就可以返回原始JSON文檔:
GET /megacorp/employee/1響應的內容中包含一些文檔的元信息,John Smith的原始JSON文檔包含在_source字段中。
{"_index" : "megacorp","_type" : "employee","_id" : "1","_version" : 1,"found" : true,"_source" : {"first_name" : "John","last_name" : "Smith","age" : 25,"about" : "I love to go rock climbing","interests": [ "sports", "music" ]} }我們通過HTTP方法GET來檢索文檔,同樣的,我們可以使用DELETE方法刪除文檔,使用HEAD方法檢查某文檔是否存在。如果想更新已存在的文檔,我們只需再PUT一次。
簡單搜索
GET請求非常簡單——你能輕松獲取你想要的文檔。讓我們來進一步嘗試一些東西,比如簡單的搜索!
我們嘗試一個最簡單的搜索全部員工的請求:
GET /megacorp/employee/_search你可以看到我們依然使用megacorp索引和employee類型,但是我們在結尾使用關鍵字_search來取代原來的文檔ID。響應內容的hits數組中包含了我們所有的三個文檔。默認情況下搜索會返回前10個結果。
{"took": 6,"timed_out": false,"_shards": { ... },"hits": {"total": 3,"max_score": 1,"hits": [{"_index": "megacorp","_type": "employee","_id": "3","_score": 1,"_source": {"first_name": "Douglas","last_name": "Fir","age": 35,"about": "I like to build cabinets","interests": [ "forestry" ]}},{"_index": "megacorp","_type": "employee","_id": "1","_score": 1,"_source": {"first_name": "John","last_name": "Smith","age": 25,"about": "I love to go rock climbing","interests": [ "sports", "music" ]}},{"_index": "megacorp","_type": "employee","_id": "2","_score": 1,"_source": {"first_name": "Jane","last_name": "Smith","age": 32,"about": "I like to collect rock albums","interests": [ "music" ]}}]} }注意:
響應內容不僅會告訴我們哪些文檔被匹配到,而且這些文檔內容完整的被包含在其中—我們在給用戶展示搜索結果時需要用到的所有信息都有了。
接下來,讓我們搜索姓氏中包含“Smith”的員工。要做到這一點,我們將在命令行中使用輕量級的搜索方法。這種方法常被稱作查詢字符串(query string)搜索,因為我們像傳遞URL參數一樣去傳遞查詢語句:
GET /megacorp/employee/_search?q=last_name:Smith我們在請求中依舊使用_search關鍵字,然后將查詢語句傳遞給參數q=。這樣就可以得到所有姓氏為Smith的結果:
{..."hits": {"total": 2,"max_score": 0.30685282,"hits": [{..."_source": {"first_name": "John","last_name": "Smith","age": 25,"about": "I love to go rock climbing","interests": [ "sports", "music" ]}},{..."_source": {"first_name": "Jane","last_name": "Smith","age": 32,"about": "I like to collect rock albums","interests": [ "music" ]}}]} }使用DSL語句查詢
查詢字符串搜索便于通過命令行完成特定(ad hoc)的搜索,但是它也有局限性(參閱簡單搜索章節)。Elasticsearch提供豐富且靈活的查詢語言叫做DSL查詢(Query DSL),它允許你構建更加復雜、強大的查詢。
DSL(Domain Specific Language特定領域語言)以JSON請求體的形式出現。我們可以這樣表示之前關于“Smith”的查詢:
GET /megacorp/employee/_search {"query" : {"match" : {"last_name" : "Smith"}} }這會返回與之前查詢相同的結果。你可以看到有些東西改變了,我們不再使用查詢字符串(query string)做為參數,而是使用請求體代替。這個請求體使用JSON表示,其中使用了match語句(查詢類型之一,具體我們以后會學到)。
更復雜的搜索
我們讓搜索稍微再變的復雜一些。我們依舊想要找到姓氏為“Smith”的員工,但是我們只想得到年齡大于30歲的員工。我們的語句將添加過濾器(filter),它使得我們高效率的執行一個結構化搜索:
GET /megacorp/employee/_search {"query" : {"filtered" : {"filter" : {"range" : {"age" : { "gt" : 30 } <1>}},"query" : {"match" : {"last_name" : "smith" <2>}}}} }- <1> 這部分查詢屬于區間過濾器(range filter),它用于查找所有年齡大于30歲的數據——gt為”greater than”的縮寫。
- <2> 這部分查詢與之前的match語句(query)一致。
現在不要擔心語法太多,我們將會在以后詳細的討論。你只要知道我們添加了一個過濾器(filter)用于執行區間搜索,然后重復利用了之前的match語句。現在我們的搜索結果只顯示了一個32歲且名字是“Jane Smith”的員工:
{..."hits": {"total": 1,"max_score": 0.30685282,"hits": [{..."_source": {"first_name": "Jane","last_name": "Smith","age": 32,"about": "I like to collect rock albums","interests": [ "music" ]}}]} }全文搜索
到目前為止搜索都很簡單:搜索特定的名字,通過年齡篩選。讓我們嘗試一種更高級的搜索,全文搜索——一種傳統數據庫很難實現的功能。
我們將會搜索所有喜歡“rock climbing”的員工:
GET /megacorp/employee/_search {"query" : {"match" : {"about" : "rock climbing"}} }你可以看到我們使用了之前的match查詢,從about字段中搜索“rock climbing”,我們得到了兩個匹配文檔:
{..."hits": {"total": 2,"max_score": 0.16273327,"hits": [{..."_score": 0.16273327, <1>"_source": {"first_name": "John","last_name": "Smith","age": 25,"about": "I love to go rock climbing","interests": [ "sports", "music" ]}},{..."_score": 0.016878016, <2>"_source": {"first_name": "Jane","last_name": "Smith","age": 32,"about": "I like to collect rock albums","interests": [ "music" ]}}]} }- <1><2> 結果相關性評分。
默認情況下,Elasticsearch根據結果相關性評分來對結果集進行排序,所謂的「結果相關性評分」就是文檔與查詢條件的匹配程度。很顯然,排名第一的John Smith的about字段明確的寫到**“rock
climbing”**。
但是為什么Jane Smith也會出現在結果里呢?原因是“rock”在她的abuot字段中被提及了。因為只有“rock”被提及而“climbing”沒有,所以她的_score要低于John。
這個例子很好的解釋了Elasticsearch如何在各種文本字段中進行全文搜索,并且返回相關性最大的結果集。相關性(relevance)的概念在Elasticsearch中非常重要,而這個概念在傳統關系型數據庫中是不可想象的,因為傳統數據庫對記錄的查詢只有匹配或者不匹配。
短語搜索
目前我們可以在字段中搜索單獨的一個詞,這挺好的,但是有時候你想要確切的匹配若干個單詞或者短語(phrases)。例如我們想要查詢同時包含”rock”和”climbing”(并且是相鄰的)的員工記錄。
要做到這個,我們只要將match查詢變更為match_phrase查詢即可:
GET /megacorp/employee/_search {"query" : {"match_phrase" : {"about" : "rock climbing"}} }毫無疑問,該查詢返回John Smith的文檔:
{..."hits": {"total": 1,"max_score": 0.23013961,"hits": [{..."_score": 0.23013961,"_source": {"first_name": "John","last_name": "Smith","age": 25,"about": "I love to go rock climbing","interests": [ "sports", "music" ]}}]} }高亮我們的搜索
很多應用喜歡從每個搜索結果中高亮(highlight)匹配到的關鍵字,這樣用戶可以知道為什么這些文檔和查詢相匹配。在Elasticsearch中高亮片段是非常容易的。
讓我們在之前的語句上增加highlight參數:
GET /megacorp/employee/_search {"query" : {"match_phrase" : {"about" : "rock climbing"}},"highlight": {"fields" : {"about" : {}}} }當我們運行這個語句時,會命中與之前相同的結果,但是在返回結果中會有一個新的部分叫做highlight,這里包含了來自about字段中的文本,并且用<em></em>來標識匹配到的單詞。
{..."hits": {"total": 1,"max_score": 0.23013961,"hits": [{..."_score": 0.23013961,"_source": {"first_name": "John","last_name": "Smith","age": 25,"about": "I love to go rock climbing","interests": [ "sports", "music" ]},"highlight": {"about": ["I love to go <em>rock</em> <em>climbing</em>" <1>]}}]} }- <1> 原有文本中高亮的片段
你可以在高亮章節關于搜索高亮的部分。
分析
最后,我們還有一個需求需要完成:允許管理者在職員目錄中進行一些分析。
Elasticsearch有一個功能叫做聚合(aggregations),它允許你在數據上生成復雜的分析統計。它很像SQL中的GROUP BY但是功能更強大。
舉個例子,讓我們找到所有職員中最大的共同點(興趣愛好)是什么:
GET /megacorp/employee/_search {"aggs": {"all_interests": {"terms": { "field": "interests" }}} }暫時先忽略語法只看查詢結果:
{..."hits": { ... },"aggregations": {"all_interests": {"buckets": [{"key": "music","doc_count": 2},{"key": "forestry","doc_count": 1},{"key": "sports","doc_count": 1}]}} }我們可以看到兩個職員對音樂有興趣,一個喜歡林學,一個喜歡運動。這些數據并沒有被預先計算好,它們是實時的從匹配查詢語句的文檔中動態計算生成的。如果我們想知道所有姓”Smith”的人最大的共同點(興趣愛好),我們只需要增加合適的語句既可:
GET /megacorp/employee/_search {"query": {"match": {"last_name": "smith"}},"aggs": {"all_interests": {"terms": {"field": "interests"}}} }all_interests聚合已經變成只包含和查詢語句相匹配的文檔了:
..."all_interests": {"buckets": [{"key": "music","doc_count": 2},{"key": "sports","doc_count": 1}]}聚合也允許分級匯總。例如,讓我們統計每種興趣下職員的平均年齡:
GET /megacorp/employee/_search {"aggs" : {"all_interests" : {"terms" : { "field" : "interests" },"aggs" : {"avg_age" : {"avg" : { "field" : "age" }}}}} }雖然這次返回的聚合結果有些復雜,但任然很容易理解:
..."all_interests": {"buckets": [{"key": "music","doc_count": 2,"avg_age": {"value": 28.5}},{"key": "forestry","doc_count": 1,"avg_age": {"value": 35}},{"key": "sports","doc_count": 1,"avg_age": {"value": 25}}]}該聚合結果比之前的聚合結果要更加豐富。我們依然得到了興趣以及數量(指具有該興趣的員工人數)的列表,但是現在每個興趣額外擁有avg_age字段來顯示具有該興趣員工的平均年齡。
即使你還不理解語法,但你也可以大概感覺到通過這個特性可以完成相當復雜的聚合工作,你可以處理任何類型的數據。
教程小結
希望這個簡短的教程能夠很好的描述Elasticsearch的功能。當然這只是一些皮毛,為了保持簡短,還有很多的特性未提及——像推薦、定位、滲透、模糊以及部分匹配等。但這也突出了構建高級搜索功能是多么的容易。無需配置,只需要添加數據然后開始搜索!
可能有些語法讓你覺得有些困惑,或者在微調方面有些疑問。那么,本書的其余部分將深入這些問題的細節,讓你全面了解Elasticsearch的工作過程。
分布式的特性
在章節的開始我們提到Elasticsearch可以擴展到上百(甚至上千)的服務器來處理PB級的數據。然而我們的教程只是給出了一些使用Elasticsearch的例子,并未涉及相關機制。Elasticsearch為分布式而生,而且它的設計隱藏了分布式本身的復雜性。
Elasticsearch在分布式概念上做了很大程度上的透明化,在教程中你不需要知道任何關于分布式系統、分片、集群發現或者其他大量的分布式概念。所有的教程你既可以運行在你的筆記本上,也可以運行在擁有100個節點的集群上,其工作方式是一樣的。
Elasticsearch致力于隱藏分布式系統的復雜性。以下這些操作都是在底層自動完成的:
- 將你的文檔分區到不同的容器或者分片(shards)中,它們可以存在于一個或多個節點中。
- 將分片均勻的分配到各個節點,對索引和搜索做負載均衡。
- 冗余每一個分片,防止硬件故障造成的數據丟失。
- 將集群中任意一個節點上的請求路由到相應數據所在的節點。
- 無論是增加節點,還是移除節點,分片都可以做到無縫的擴展和遷移。
當你閱讀本書時,你可以遇到關于Elasticsearch分布式特性的補充章節。這些章節將教給你如何擴展集群和故障轉移,如何處理文檔存儲,如何執行分布式搜索,分片是什么以及如何工作。
這些章節不是必讀的——不懂這些內部機制也可以使用Elasticsearch的。但是這些能夠幫助你更深入和完整的了解Elasticsearch。你可以略讀它們,然后在你需要更深入的理解時再回頭翻閱。
下一步
現在你對Elasticsearch可以做些什么以及其易用程度有了大概的了解。Elasticsearch致力于降低學習成本和輕松配置。學習Elasticsearch最好的方式就是開始使用它:開始索引和檢索吧!
當然,你越是了解Elasticsearch,你的生產力就越高。你越是詳細告訴Elasticsearch你的應用的數據特點,你就越能得到準確的輸出。
本書其余部分將幫助你從新手晉級到專家。每一個章節都會闡述一個要點,并且會包含專家級別的技巧。如果你只是剛起步,那么這些技巧可能暫時和你無關。Elasticsearch有合理的默認配置而且可以在沒有用戶干預的情況下做正確的事情。當需要提升性能時你可以隨時回顧這些章節。
原文:https://github.com/looly/elasticsearch-definitive-guide-cn
總結
以上是生活随笔為你收集整理的Elasticsearch 权威教程 - 入门的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 计算机二级access知识点6,知识点:
- 下一篇: 阿里云物联网平台架构