Elastic search 入门
- 摘要:Elasticsearch是一個(gè)實(shí)時(shí)分布式搜索和分析引擎。它讓你以前所未有的速度處理大數(shù)據(jù)成為可能。它用于全文搜索、結(jié)構(gòu)化搜索、分析以及將這三者混合使用:維基百科使用Elasticsearch提供全文搜索并高亮關(guān)鍵字,以及輸入實(shí)時(shí)搜索(search-as-you-type)和搜索糾錯(cuò)(did-you-mean)等搜索建議功能。英國(guó)衛(wèi)報(bào)使用Elasticsearch結(jié)合用戶日志和社交網(wǎng)絡(luò)數(shù)據(jù)提供給他們的編輯以實(shí)時(shí)的反饋,以便及時(shí)了解公眾對(duì)新發(fā)表的文章的回應(yīng)。StackOverf
-
Elasticsearch是一個(gè)實(shí)時(shí)分布式搜索和分析引擎。它讓你以前所未有的速度處理大數(shù)據(jù)成為可能。
它用于全文搜索、結(jié)構(gòu)化搜索、分析以及將這三者混合使用:
維基百科使用Elasticsearch提供全文搜索并高亮關(guān)鍵字,以及輸入實(shí)時(shí)搜索(search-as-you-type)和搜索糾錯(cuò)(did-you-mean)等搜索建議功能。
英國(guó)衛(wèi)報(bào)使用Elasticsearch結(jié)合用戶日志和社交網(wǎng)絡(luò)數(shù)據(jù)提供給他們的編輯以實(shí)時(shí)的反饋,以便及時(shí)了解公眾對(duì)新發(fā)表的文章的回應(yīng)。
StackOverflow結(jié)合全文搜索與地理位置查詢,以及more-like-this功能來找到相關(guān)的問題和答案。
Github使用Elasticsearch檢索1300億行的代碼。
但是Elasticsearch不僅用于大型企業(yè),它還讓像DataDog以及Klout這樣的創(chuàng)業(yè)公司將最初的想法變成可擴(kuò)展的解決方案。Elasticsearch可以在你的筆記本上運(yùn)行,也可以在數(shù)以百計(jì)的服務(wù)器上處理PB級(jí)別的數(shù)據(jù)。
Elasticsearch所涉及到的每一項(xiàng)技術(shù)都不是創(chuàng)新或者革命性的,全文搜索,分析系統(tǒng)以及分布式數(shù)據(jù)庫(kù)這些早就已經(jīng)存在了。它的革命性在于將這些獨(dú)立且有用的技術(shù)整合成一個(gè)一體化的、實(shí)時(shí)的應(yīng)用。它對(duì)新用戶的門檻很低,當(dāng)然它也會(huì)跟上你技能和需求增長(zhǎng)的步伐。
如果你打算看這本書,說明你已經(jīng)有數(shù)據(jù)了,但光有數(shù)據(jù)是不夠的,除非你能對(duì)這些數(shù)據(jù)做些什么事情。
很不幸,現(xiàn)在大部分?jǐn)?shù)據(jù)庫(kù)在提取可用知識(shí)方面顯得異常無能。的確,它們能夠通過時(shí)間戳或者精確匹配做過濾,但是它們能夠進(jìn)行全文搜索,處理同義詞和根據(jù)相關(guān)性給文檔打分嗎?它們能根據(jù)同一份數(shù)據(jù)生成分析和聚合的結(jié)果嗎?最重要的是,它們?cè)跊]有大量工作進(jìn)程(線程)的情況下能做到對(duì)數(shù)據(jù)的實(shí)時(shí)處理嗎?
這就是Elasticsearch存在的理由:Elasticsearch鼓勵(lì)你瀏覽并利用你的數(shù)據(jù),而不是讓它爛在數(shù)據(jù)庫(kù)里,因?yàn)樵跀?shù)據(jù)庫(kù)里實(shí)在太難查詢了。
Elasticsearch是你新認(rèn)識(shí)的最好的朋友。
1.1是什么?為了搜索,你懂得!
Elasticsearch是一個(gè)基于Apache Lucene(TM)的開源搜索引擎。無論在開源還是專有領(lǐng)域,Lucene可以被認(rèn)為是迄今為止最先進(jìn)、性能最好的、功能最全的搜索引擎庫(kù)。
但是,Lucene只是一個(gè)庫(kù)。想要使用它,你必須使用Java來作為開發(fā)語(yǔ)言并將其直接集成到你的應(yīng)用中,更糟糕的是,Lucene非常復(fù)雜,你需要深入了解檢索的相關(guān)知識(shí)來理解它是如何工作的。
Elasticsearch也使用Java開發(fā)并使用Lucene作為其核心來實(shí)現(xiàn)所有索引和搜索的功能,但是它的目的是通過簡(jiǎn)單的RESTful API來隱藏Lucene的復(fù)雜性,從而讓全文搜索變得簡(jiǎn)單。
不過,Elasticsearch不僅僅是Lucene和全文搜索,我們還能這樣去描述它:
分布式的實(shí)時(shí)文件存儲(chǔ),每個(gè)字段都被索引并可被搜索?
分布式的實(shí)時(shí)分析搜索引擎?
可以擴(kuò)展到上百臺(tái)服務(wù)器,處理PB級(jí)結(jié)構(gòu)化或非結(jié)構(gòu)化數(shù)據(jù)而且,所有的這些功能被集成到一個(gè)服務(wù)里面,你的應(yīng)用可以通過簡(jiǎn)單的RESTful API、各種語(yǔ)言的客戶端甚至命令行與之交互。
上手Elasticsearch非常容易。它提供了許多合理的缺省值,并對(duì)初學(xué)者隱藏了復(fù)雜的搜索引擎理論。它開箱即用(安裝即可使用),只需很少的學(xué)習(xí)既可在生產(chǎn)環(huán)境中使用。
Elasticsearch在Apache 2 license下許可使用,可以免費(fèi)下載、使用和修改。
隨著你對(duì)Elasticsearch的理解加深,你可以根據(jù)不同的問題領(lǐng)域定制Elasticsearch的高級(jí)特性,這一切都是可配置的,并且配置非常靈活。
1.2安裝Elasticsearch?理解Elasticsearch最好的方式是去運(yùn)行它,讓我們開始吧!
安裝Elasticsearch唯一的要求是安裝官方新版的JAVA.
你可以從 elasticsearch.org/download下載最新版本.
curl -L -O http://download.elasticsearch.org/PATH/TO/VERSION.zip?
unzip elasticsearch-$VERSION.zip?
cdelasticsearch-$VERSION?1.從elasticsearch.org/download獲得最新可用的版本號(hào)并填入U(xiǎn)RL中
提示:
在生產(chǎn)環(huán)境安裝時(shí),除了以上方法,你還可以使用Debian或者RPM安裝包,地址在這里:downloads page,或者也可以使用官方提供的Puppet module或者Chef cookbook。
安裝Marvel?Marvel是Elasticsearch的管理和監(jiān)控工具,在開發(fā)環(huán)境下免費(fèi)使用。它包含了一個(gè)叫做Sense的交互式控制臺(tái),使用戶方便的通過瀏覽器直接與Elasticsearch進(jìn)行交互。
Elasticsearch線上文檔中的很多示例代碼都附帶一個(gè)View in Sense的鏈接。點(diǎn)擊進(jìn)去,就會(huì)在Sense控制臺(tái)打開相應(yīng)的實(shí)例。安裝Marvel不是必須的,但是它可以通過在你本地Elasticsearch集群中運(yùn)行示例代碼而增加與此書的互動(dòng)性。
Marvel是一個(gè)插件,可在Elasticsearch目錄中運(yùn)行以下命令來下載和安裝:
./bin/plugin -i elasticsearch/marvel/latest你可能想要禁用監(jiān)控,你可以通過以下命令關(guān)閉Marvel:
echo 'marvel.agent.enabled: false' >> ./config/elasticsearch.yml?
運(yùn)行Elasticsearch?Elasticsearch已經(jīng)準(zhǔn)備就緒,執(zhí)行以下命令可在前臺(tái)啟動(dòng):
./bin/elasticsearch如果想在后臺(tái)以守護(hù)進(jìn)程模式運(yùn)行,添加-d參數(shù)。
打開另一個(gè)終端進(jìn)行測(cè)試:
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集群已經(jīng)啟動(dòng)并且正常運(yùn)行,接下來我們可以開始各種實(shí)驗(yàn)了。
集群和節(jié)點(diǎn)?節(jié)點(diǎn)(node)是一個(gè)運(yùn)行著的Elasticsearch實(shí)例。集群(cluster)是一組具有相同cluster.name的節(jié)點(diǎn)集合,他們協(xié)同工作,共享數(shù)據(jù)并提供故障轉(zhuǎn)移和擴(kuò)展功能,當(dāng)然一個(gè)節(jié)點(diǎn)也可以組成一個(gè)集群。
你最好找一個(gè)合適的名字來替代cluster.name的默認(rèn)值,比如你自己的名字,這樣可以防止一個(gè)新啟動(dòng)的節(jié)點(diǎn)加入到相同網(wǎng)絡(luò)中的另一個(gè)同名的集群中。
你可以通過修改config/目錄下的elasticsearch.yml文件,然后重啟ELasticsearch來做到這一點(diǎn)。當(dāng)Elasticsearch在前臺(tái)運(yùn)行,可以使用Ctrl-C快捷鍵終止,或者你可以調(diào)用shutdownAPI來關(guān)閉:
curl -XPOST 'http://localhost:9200/_shutdown'查看Marvel和Sense?如果你安裝了Marvel(作為管理和監(jiān)控的工具),就可以在瀏覽器里通過以下地址訪問它:
http://localhost:9200/_plugin/marvel/
你可以在Marvel中通過點(diǎn)擊dashboards,在下拉菜單中訪問Sense開發(fā)者控制臺(tái),或者直接訪問以下地址:
http://localhost:9200/_plugin/marvel/sense/
1.3 API?與 Elasticsearch 交互
如何與 Elasticsearch 交互取決于你是否使用JAVA.
Java API?Elasticsearch為Java用戶提供了兩種內(nèi)置客戶端:
節(jié)點(diǎn)客戶端(node client):?節(jié)點(diǎn)客戶端以無數(shù)據(jù)節(jié)點(diǎn)(none data node)身份加入集群,換言之,它自己不存儲(chǔ)任何數(shù)據(jù),但是它知道數(shù)據(jù)在集群中的具體位置,并且能夠直接轉(zhuǎn)發(fā)請(qǐng)求到對(duì)應(yīng)的節(jié)點(diǎn)上。
傳輸客戶端(Transport client):?這個(gè)更輕量的傳輸客戶端能夠發(fā)送請(qǐng)求到遠(yuǎn)程集群。它自己不加入集群,只是簡(jiǎn)單轉(zhuǎn)發(fā)請(qǐng)求給集群中的節(jié)點(diǎn)。
兩個(gè)Java客戶端都通過9300端口與集群交互,使用Elasticsearch傳輸協(xié)議(Elasticsearch Transport Protocol)。集群中的節(jié)點(diǎn)之間也通過9300端口進(jìn)行通信。如果此端口未開放,你的節(jié)點(diǎn)將不能組成集群。
TIP
Java客戶端所在的Elasticsearch版本必須與集群中其他節(jié)點(diǎn)一致,否則,它們可能互相無法識(shí)別。
關(guān)于Java API的更多信息請(qǐng)查看相關(guān)章節(jié):Java API
基于HTTP協(xié)議,以JSON為數(shù)據(jù)交互格式的RESTful API?其他所有程序語(yǔ)言都可以使用RESTful API,通過9200端口的與Elasticsearch進(jìn)行通信,你可以使用你喜歡的WEB客戶端,事實(shí)上,如你所見,你甚至可以通過curl命令與Elasticsearch通信。
NOTE
Elasticsearch官方提供了多種程序語(yǔ)言的客戶端——Groovy,Javascript, .NET,PHP,Perl,Python,以及 Ruby——還有很多由社區(qū)提供的客戶端和插件,所有這些可以在文檔中找到。
向Elasticsearch發(fā)出的請(qǐng)求的組成部分與其它普通的HTTP請(qǐng)求是一樣的:
curl -X?'?://?:?/???<query_string>' -d ''?
VERB HTTP方法:GET,POST,PUT,HEAD,DELETE?
PROTOCOL http或者h(yuǎn)ttps協(xié)議(只有在Elasticsearch前面有https代理的時(shí)候可用)?
HOST Elasticsearch集群中的任何一個(gè)節(jié)點(diǎn)的主機(jī)名,如果是在本地的節(jié)點(diǎn),那么就叫l(wèi)ocalhost?
PORT Elasticsearch HTTP服務(wù)所在的端口,默認(rèn)為9200?
PATH API路徑(例如_count將返回集群中文檔的數(shù)量),PATH可以包含多個(gè)組件,例如_cluster/stats或者_(dá)nodes/stats/jvm?
QUERY_STRING 一些可選的查詢請(qǐng)求參數(shù),例如?pretty參數(shù)將使請(qǐng)求返回更加美觀易讀的JSON數(shù)據(jù)?
BODY 一個(gè)JSON格式的請(qǐng)求主體(如果請(qǐng)求需要的話)舉例說明,為了計(jì)算集群中的文檔數(shù)量,我們可以這樣做:
curl -XGET 'http://localhost:9200/_count?pretty' -d '?
{?
"query": {?
"match_all": {}?
}?
}?
'?Elasticsearch返回一個(gè)類似200 OK的HTTP狀態(tài)碼和JSON格式的響應(yīng)主體(除了HEAD請(qǐng)求)。上面的請(qǐng)求會(huì)得到如下的JSON格式的響應(yīng)主體:
{?
"count" : 0,?
"_shards" : {?
"total" : 5,?
"successful" : 5,?
"failed" : 0?
}?
}?我們看不到HTTP頭是因?yàn)槲覀儧]有讓curl顯示它們,如果要顯示,使用curl命令后跟-i參數(shù):
curl -i -XGET 'localhost:9200/'?對(duì)于本書的其余部分,我們將簡(jiǎn)寫curl請(qǐng)求中重復(fù)的部分,例如主機(jī)名和端口,還有curl命令本身。
一個(gè)完整的請(qǐng)求形如:
curl -XGET 'localhost:9200/_count?pretty' -d '?
{?
"query": {?
"match_all": {}?
}?
}'?我們將簡(jiǎn)寫成這樣:
GET /_count?
{?
"query": {?
"match_all": {}?
}?
}?事實(shí)上,在Sense控制臺(tái)中也使用了與上面相同的格式。
1.4 文檔?
面向文檔?應(yīng)用中的對(duì)象很少只是簡(jiǎn)單的鍵值列表,更多時(shí)候它擁有復(fù)雜的數(shù)據(jù)結(jié)構(gòu),比如包含日期、地理位置、另一個(gè)對(duì)象或者數(shù)組。
總有一天你會(huì)想到把這些對(duì)象存儲(chǔ)到數(shù)據(jù)庫(kù)中。將這些數(shù)據(jù)保存到由行和列組成的關(guān)系數(shù)據(jù)庫(kù)中,就好像是把一個(gè)豐富,信息表現(xiàn)力強(qiáng)的對(duì)象拆散了放入一個(gè)非常大的表格中:你不得不拆散對(duì)象以適應(yīng)表模式(通常一列表示一個(gè)字段),然后又不得不在查詢的時(shí)候重建它們。
Elasticsearch是面向文檔(document oriented)的,這意味著它可以存儲(chǔ)整個(gè)對(duì)象或文檔(document)。然而它不僅僅是存儲(chǔ),還會(huì)索引(index)每個(gè)文檔的內(nèi)容使之可以被搜索。在Elasticsearch中,你可以對(duì)文檔(而非成行成列的數(shù)據(jù))進(jìn)行索引、搜索、排序、過濾。這種理解數(shù)據(jù)的方式與以往完全不同,這也是Elasticsearch能夠執(zhí)行復(fù)雜的全文搜索的原因之一。
JSON?ELasticsearch使用Javascript對(duì)象符號(hào)(JavaScript Object Notation),也就是JSON,作為文檔序列化格式。JSON現(xiàn)在已經(jīng)被大多語(yǔ)言所支持,而且已經(jīng)成為NoSQL領(lǐng)域的標(biāo)準(zhǔn)格式。它簡(jiǎn)潔、簡(jiǎn)單且容易閱讀。
以下使用JSON文檔來表示一個(gè)用戶對(duì)象:
{?
"email":"?aliyunzixun@xxx.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對(duì)象很復(fù)雜,但它的結(jié)構(gòu)和對(duì)象的含義已經(jīng)被完整的體現(xiàn)在JSON中了,在Elasticsearch中將對(duì)象轉(zhuǎn)化為JSON并做索引要比在表結(jié)構(gòu)中做相同的事情簡(jiǎn)單的多。
NOTE
盡管幾乎所有的語(yǔ)言都有相應(yīng)的模塊用于將任意數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)換為JSON,但每種語(yǔ)言處理細(xì)節(jié)不同。具體請(qǐng)查看“serialization” or “marshalling”兩個(gè)用于處理JSON的模塊。Elasticsearch官方客戶端會(huì)自動(dòng)為你序列化和反序列化JSON。
1.5索引?
開始第一步?我們現(xiàn)在開始進(jìn)行一個(gè)簡(jiǎn)單教程,它涵蓋了一些基本的概念介紹,比如索引(indexing)、搜索(search)以及聚合(aggregations)。通過這個(gè)教程,我們可以讓你對(duì)Elasticsearch能做的事以及其易用程度有一個(gè)大致的感覺。
我們接下來將陸續(xù)介紹一些術(shù)語(yǔ)和基本的概念,但就算你沒有馬上完全理解也沒有關(guān)系。我們將在本書的各個(gè)章節(jié)中更加深入的探討這些內(nèi)容。
所以,坐下來,開始以旋風(fēng)般的速度來感受Elasticsearch的能力吧!
讓我們建立一個(gè)員工目錄?假設(shè)我們剛好在Megacorp工作,這時(shí)人力資源部門出于某種目的需要讓我們創(chuàng)建一個(gè)員工目錄,這個(gè)目錄用于促進(jìn)人文關(guān)懷和用于實(shí)時(shí)協(xié)同工作,所以它有以下不同的需求:
數(shù)據(jù)能夠包含多個(gè)值的標(biāo)簽、數(shù)字和純文本。?
檢索任何員工的所有信息。?
支持結(jié)構(gòu)化搜索,例如查找30歲以上的員工。?
支持簡(jiǎn)單的全文搜索和更復(fù)雜的短語(yǔ)(phrase)搜索?
高亮搜索結(jié)果中的關(guān)鍵字?
能夠利用圖表管理分析這些數(shù)據(jù) 索引員工文檔?我們首先要做的是存儲(chǔ)員工數(shù)據(jù),每個(gè)文檔代表一個(gè)員工。在Elasticsearch中存儲(chǔ)數(shù)據(jù)的行為就叫做索引(indexing),不過在索引之前,我們需要明確數(shù)據(jù)應(yīng)該存儲(chǔ)在哪里。
在Elasticsearch中,文檔歸屬于一種類型(type),而這些類型存在于索引(index)中,我們可以畫一些簡(jiǎn)單的對(duì)比圖來類比傳統(tǒng)關(guān)系型數(shù)據(jù)庫(kù):
Relational DB -> Databases -> Tables -> Rows -> Columns?
Elasticsearch -> Indices -> Types-> Documents -> FieldsElasticsearch集群可以包含多個(gè)索引(indices)(數(shù)據(jù)庫(kù)),每一個(gè)索引可以包含多個(gè)類型(types)(表),每一個(gè)類型包含多個(gè)文檔(documents)(行),然后每個(gè)文檔包含多個(gè)字段(Fields)(列)。
「索引」含義的區(qū)分?你可能已經(jīng)注意到索引(index)這個(gè)詞在Elasticsearch中有著不同的含義,所以有必要在此做一下區(qū)分:
索引(名詞) 如上文所述,一個(gè)索引(index)就像是傳統(tǒng)關(guān)系數(shù)據(jù)庫(kù)中的數(shù)據(jù)庫(kù),它是相關(guān)文檔存儲(chǔ)的地方,index的復(fù)數(shù)是indices或indexes。?
索引(動(dòng)詞)「索引一個(gè)文檔」表示把一個(gè)文檔存儲(chǔ)到索引(名詞)里,以便它可以被檢索或者查詢。這很像SQL中的INSERT關(guān)鍵字,差別是,如果文檔已經(jīng)存在,新的文檔將覆蓋舊的文檔。?
倒排索引 傳統(tǒng)數(shù)據(jù)庫(kù)為特定列增加一個(gè)索引,例如B-Tree索引來加速檢索。Elasticsearch和Lucene使用一種叫做倒排索引(inverted index)的數(shù)據(jù)結(jié)構(gòu)來達(dá)到相同目的。默認(rèn)情況下,文檔中的所有字段都會(huì)被索引(擁有一個(gè)倒排索引),只有這樣他們才是可被搜索的。
我們將會(huì)在倒排索引章節(jié)中更詳細(xì)的討論。
所以為了創(chuàng)建員工目錄,我們將進(jìn)行如下操作:
為每個(gè)員工的文檔(document)建立索引,每個(gè)文檔包含了相應(yīng)員工的所有信息。?
每個(gè)文檔的類型為employee。?
employee類型歸屬于索引megacorp。?
megacorp索引存儲(chǔ)在Elasticsearch集群中。實(shí)際上這些都是很容易的(盡管看起來有許多步驟)。我們能通過一個(gè)命令執(zhí)行完成的操作:
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?
這個(gè)員工的ID?請(qǐng)求實(shí)體(JSON文檔),包含了這個(gè)員工的所有信息。他的名字叫“John Smith”,25歲,喜歡攀巖。
很簡(jiǎn)單吧!它不需要你做額外的管理操作,比如創(chuàng)建索引或者定義每個(gè)字段的數(shù)據(jù)類型。我們能夠直接索引文檔,Elasticsearch已經(jīng)內(nèi)置所有的缺省設(shè)置,所有管理操作都是透明的。
接下來,讓我們?cè)谀夸浿屑尤敫鄦T工信息:
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" ]?
} 1.6搜索?
檢索文檔?現(xiàn)在Elasticsearch中已經(jīng)存儲(chǔ)了一些數(shù)據(jù),我們可以根據(jù)業(yè)務(wù)需求開始工作了。第一個(gè)需求是能夠檢索單個(gè)員工的信息。
這對(duì)于Elasticsearch來說非常簡(jiǎn)單。我們只要執(zhí)行HTTP GET請(qǐng)求并指出文檔的“地址”——索引、類型和ID既可。根據(jù)這三部分信息,我們就可以返回原始JSON文檔:
GET /megacorp/employee/1響應(yīng)的內(nèi)容中包含一些文檔的元信息,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一次。
簡(jiǎn)單搜索?GET請(qǐng)求非常簡(jiǎn)單——你能輕松獲取你想要的文檔。讓我們來進(jìn)一步嘗試一些東西,比如簡(jiǎn)單的搜索!
我們嘗試一個(gè)最簡(jiǎn)單的搜索全部員工的請(qǐng)求:
GET /megacorp/employee/_search你可以看到我們依然使用megacorp索引和employee類型,但是我們?cè)诮Y(jié)尾使用關(guān)鍵字_search來取代原來的文檔ID。響應(yīng)內(nèi)容的hits數(shù)組中包含了我們所有的三個(gè)文檔。默認(rèn)情況下搜索會(huì)返回前10個(gè)結(jié)果。
{?
"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" ]?
}?
}?
]?
}?
}注意:
響應(yīng)內(nèi)容不僅會(huì)告訴我們哪些文檔被匹配到,而且這些文檔內(nèi)容完整的被包含在其中—我們?cè)诮o用戶展示搜索結(jié)果時(shí)需要用到的所有信息都有了。
接下來,讓我們搜索姓氏中包含“Smith”的員工。要做到這一點(diǎn),我們將在命令行中使用輕量級(jí)的搜索方法。這種方法常被稱作查詢字符串(query string)搜索,因?yàn)槲覀兿駛鬟fURL參數(shù)一樣去傳遞查詢語(yǔ)句:
GET /megacorp/employee/_search?q=last_name:Smith我們?cè)谡?qǐng)求中依舊使用_search關(guān)鍵字,然后將查詢語(yǔ)句傳遞給參數(shù)q=。這樣就可以得到所有姓氏為Smith的結(jié)果:
{?
...?
"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語(yǔ)句查詢?查詢字符串搜索便于通過命令行完成特定(ad hoc)的搜索,但是它也有局限性(參閱簡(jiǎn)單搜索章節(jié))。Elasticsearch提供豐富且靈活的查詢語(yǔ)言叫做DSL查詢(Query DSL),它允許你構(gòu)建更加復(fù)雜、強(qiáng)大的查詢。
DSL(Domain Specific Language特定領(lǐng)域語(yǔ)言)以JSON請(qǐng)求體的形式出現(xiàn)。我們可以這樣表示之前關(guān)于“Smith”的查詢:
1
GET /megacorp/employee/_search?
{?
"query" : {?
"match" : {?
"last_name" : "Smith"?
}?
}?
}這會(huì)返回與之前查詢相同的結(jié)果。你可以看到有些東西改變了,我們不再使用查詢字符串(query string)做為參數(shù),而是使用請(qǐng)求體代替。這個(gè)請(qǐng)求體使用JSON表示,其中使用了match語(yǔ)句(查詢類型之一,具體我們以后會(huì)學(xué)到)。
更復(fù)雜的搜索?我們讓搜索稍微再變的復(fù)雜一些。我們依舊想要找到姓氏為“Smith”的員工,但是我們只想得到年齡大于30歲的員工。我們的語(yǔ)句將添加過濾器(filter),它使得我們高效率的執(zhí)行一個(gè)結(jié)構(gòu)化搜索:
GET /megacorp/employee/_search?
{?
"query" : {?
"filtered" : {?
"filter" : {?
"range" : {?
"age" : { "gt" : 30 } <1>?
}?
},?
"query" : {?
"match" : {?
"last_name" : "smith" <2>?
}?
}?
}?
}?
}?
<1> 這部分查詢屬于區(qū)間過濾器(range filter),它用于查找所有年齡大于30歲的數(shù)據(jù)——gt為"greater than"的縮寫。?
<2> 這部分查詢與之前的match語(yǔ)句(query)一致。現(xiàn)在不要擔(dān)心語(yǔ)法太多,我們將會(huì)在以后詳細(xì)的討論。你只要知道我們添加了一個(gè)過濾器(filter)用于執(zhí)行區(qū)間搜索,然后重復(fù)利用了之前的match語(yǔ)句。現(xiàn)在我們的搜索結(jié)果只顯示了一個(gè)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" ]?
}?
}?
]?
}?
}全文搜索?到目前為止搜索都很簡(jiǎn)單:搜索特定的名字,通過年齡篩選。讓我們嘗試一種更高級(jí)的搜索,全文搜索——一種傳統(tǒng)數(shù)據(jù)庫(kù)很難實(shí)現(xiàn)的功能。
我們將會(huì)搜索所有喜歡“rock climbing”的員工:
GET /megacorp/employee/_search?
{?
"query" : {?
"match" : {?
"about" : "rock climbing"?
}?
}?
}你可以看到我們使用了之前的match查詢,從about字段中搜索"rock climbing",我們得到了兩個(gè)匹配文檔:
{?
...?
"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> 結(jié)果相關(guān)性評(píng)分。默認(rèn)情況下,Elasticsearch根據(jù)結(jié)果相關(guān)性評(píng)分來對(duì)結(jié)果集進(jìn)行排序,所謂的「結(jié)果相關(guān)性評(píng)分」就是文檔與查詢條件的匹配程度。很顯然,排名第一的John Smith的about字段明確的寫到“rock climbing”。
但是為什么Jane Smith也會(huì)出現(xiàn)在結(jié)果里呢?原因是“rock”在她的abuot字段中被提及了。因?yàn)橹挥小皉ock”被提及而“climbing”沒有,所以她的_score要低于John。
3
這個(gè)例子很好的解釋了Elasticsearch如何在各種文本字段中進(jìn)行全文搜索,并且返回相關(guān)性最大的結(jié)果集。相關(guān)性(relevance)的概念在Elasticsearch中非常重要,而這個(gè)概念在傳統(tǒng)關(guān)系型數(shù)據(jù)庫(kù)中是不可想象的,因?yàn)閭鹘y(tǒng)數(shù)據(jù)庫(kù)對(duì)記錄的查詢只有匹配或者不匹配。
短語(yǔ)搜索?目前我們可以在字段中搜索單獨(dú)的一個(gè)詞,這挺好的,但是有時(shí)候你想要確切的匹配若干個(gè)單詞或者短語(yǔ)(phrases)。例如我們想要查詢同時(shí)包含"rock"和"climbing"(并且是相鄰的)的員工記錄。
要做到這個(gè),我們只要將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" ]?
}?
}?
]?
}?
}高亮我們的搜索?很多應(yīng)用喜歡從每個(gè)搜索結(jié)果中高亮(highlight)匹配到的關(guān)鍵字,這樣用戶可以知道為什么這些文檔和查詢相匹配。在Elasticsearch中高亮片段是非常容易的。
讓我們?cè)谥暗恼Z(yǔ)句上增加highlight參數(shù):
GET /megacorp/employee/_search?
{?
"query" : {?
"match_phrase" : {?
"about" : "rock climbing"?
}?
},?
"highlight": {?
"fields" : {?
"about" : {}?
}?
}?
}當(dāng)我們運(yùn)行這個(gè)語(yǔ)句時(shí),會(huì)命中與之前相同的結(jié)果,但是在返回結(jié)果中會(huì)有一個(gè)新的部分叫做highlight,這里包含了來自about字段中的文本,并且用來標(biāo)識(shí)匹配到的單詞。
{?
...?
"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?rock?climbing" <1>?
]?
}?
}?
]?
}?
}?
<1> 原有文本中高亮的片段你可以在高亮章節(jié)關(guān)于搜索高亮的部分。
1.7聚合?
分析?最后,我們還有一個(gè)需求需要完成:允許管理者在職員目錄中進(jìn)行一些分析。 Elasticsearch有一個(gè)功能叫做聚合(aggregations),它允許你在數(shù)據(jù)上生成復(fù)雜的分析統(tǒng)計(jì)。它很像SQL中的GROUP BY但是功能更強(qiáng)大。
舉個(gè)例子,讓我們找到所有職員中最大的共同點(diǎn)(興趣愛好)是什么:
GET /megacorp/employee/_search?
{?
"aggs": {?
"all_interests": {?
"terms": { "field": "interests" }?
}?
}?
}暫時(shí)先忽略語(yǔ)法只看查詢結(jié)果:
{?
...?
"hits": { ... },?
"aggregations": {?
"all_interests": {?
"buckets": [?
{?
"key":"music",?
"doc_count": 2?
},?
{?
"key":"forestry",?
"doc_count": 1?
},?
{?
"key":"sports",?
"doc_count": 1?
}?
]?
}?
}?
}我們可以看到兩個(gè)職員對(duì)音樂有興趣,一個(gè)喜歡林學(xué),一個(gè)喜歡運(yùn)動(dòng)。這些數(shù)據(jù)并沒有被預(yù)先計(jì)算好,它們是實(shí)時(shí)的從匹配查詢語(yǔ)句的文檔中動(dòng)態(tài)計(jì)算生成的。如果我們想知道所有姓"Smith"的人最大的共同點(diǎn)(興趣愛好),我們只需要增加合適的語(yǔ)句既可:
GET /megacorp/employee/_search?
{?
"query": {?
"match": {?
"last_name": "smith"?
}?
},?
"aggs": {?
"all_interests": {?
"terms": {?
"field": "interests"?
}?
}?
}?
}all_interests聚合已經(jīng)變成只包含和查詢語(yǔ)句相匹配的文檔了:
...?
"all_interests": {?
"buckets": [?
{?
"key": "music",?
"doc_count": 2?
},?
{?
"key": "sports",?
"doc_count": 1?
}?
]?
}聚合也允許分級(jí)匯總。例如,讓我們統(tǒng)計(jì)每種興趣下職員的平均年齡:
GET /megacorp/employee/_search?
{?
"aggs" : {?
"all_interests" : {?
"terms" : { "field" : "interests" },?
"aggs" : {?
"avg_age" : {?
"avg" : { "field" : "age" }?
}?
}?
}?
}?
}雖然這次返回的聚合結(jié)果有些復(fù)雜,但任然很容易理解:
3
...?
"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?
}?
}?
]?
}該聚合結(jié)果比之前的聚合結(jié)果要更加豐富。我們依然得到了興趣以及數(shù)量(指具有該興趣的員工人數(shù))的列表,但是現(xiàn)在每個(gè)興趣額外擁有avg_age字段來顯示具有該興趣員工的平均年齡。
即使你還不理解語(yǔ)法,但你也可以大概感覺到通過這個(gè)特性可以完成相當(dāng)復(fù)雜的聚合工作,你可以處理任何類型的數(shù)據(jù)。
1.8小結(jié)?
教程小結(jié)?希望這個(gè)簡(jiǎn)短的教程能夠很好的描述Elasticsearch的功能。當(dāng)然這只是一些皮毛,為了保持簡(jiǎn)短,還有很多的特性未提及——像推薦、定位、滲透、模糊以及部分匹配等。但這也突出了構(gòu)建高級(jí)搜索功能是多么的容易。無需配置,只需要添加數(shù)據(jù)然后開始搜索!
可能有些語(yǔ)法讓你覺得有些困惑,或者在微調(diào)方面有些疑問。那么,本書的其余部分將深入這些問題的細(xì)節(jié),讓你全面了解Elasticsearch的工作過程。
1.9分布式?
分布式的特性?在章節(jié)的開始我們提到Elasticsearch可以擴(kuò)展到上百(甚至上千)的服務(wù)器來處理PB級(jí)的數(shù)據(jù)。然而我們的教程只是給出了一些使用Elasticsearch的例子,并未涉及相關(guān)機(jī)制。Elasticsearch為分布式而生,而且它的設(shè)計(jì)隱藏了分布式本身的復(fù)雜性。
Elasticsearch在分布式概念上做了很大程度上的透明化,在教程中你不需要知道任何關(guān)于分布式系統(tǒng)、分片、集群發(fā)現(xiàn)或者其他大量的分布式概念。所有的教程你既可以運(yùn)行在你的筆記本上,也可以運(yùn)行在擁有100個(gè)節(jié)點(diǎn)的集群上,其工作方式是一樣的。
Elasticsearch致力于隱藏分布式系統(tǒng)的復(fù)雜性。以下這些操作都是在底層自動(dòng)完成的:
將你的文檔分區(qū)到不同的容器或者分片(shards)中,它們可以存在于一個(gè)或多個(gè)節(jié)點(diǎn)中。?
將分片均勻的分配到各個(gè)節(jié)點(diǎn),對(duì)索引和搜索做負(fù)載均衡。?
冗余每一個(gè)分片,防止硬件故障造成的數(shù)據(jù)丟失。?
將集群中任意一個(gè)節(jié)點(diǎn)上的請(qǐng)求路由到相應(yīng)數(shù)據(jù)所在的節(jié)點(diǎn)。?
無論是增加節(jié)點(diǎn),還是移除節(jié)點(diǎn),分片都可以做到無縫的擴(kuò)展和遷移。當(dāng)你閱讀本書時(shí),你可以遇到關(guān)于Elasticsearch分布式特性的補(bǔ)充章節(jié)。這些章節(jié)將教給你如何擴(kuò)展集群和故障轉(zhuǎn)移,如何處理文檔存儲(chǔ),如何執(zhí)行分布式搜索,分片是什么以及如何工作。
這些章節(jié)不是必讀的——不懂這些內(nèi)部機(jī)制也可以使用Elasticsearch的。但是這些能夠幫助你更深入和完整的了解Elasticsearch。你可以略讀它們,然后在你需要更深入的理解時(shí)再回頭翻閱。
1.10 結(jié)語(yǔ)?
下一步?現(xiàn)在你對(duì)Elasticsearch可以做些什么以及其易用程度有了大概的了解。Elasticsearch致力于降低學(xué)習(xí)成本和輕松配置。學(xué)習(xí)Elasticsearch最好的方式就是開始使用它:開始索引和檢索吧!
當(dāng)然,你越是了解Elasticsearch,你的生產(chǎn)力就越高。你越是詳細(xì)告訴Elasticsearch你的應(yīng)用的數(shù)據(jù)特點(diǎn),你就越能得到準(zhǔn)確的輸出。
本書其余部分將幫助你從新手晉級(jí)到專家。每一個(gè)章節(jié)都會(huì)闡述一個(gè)要點(diǎn),并且會(huì)包含專家級(jí)別的技巧。如果你只是剛起步,那么這些技巧可能暫時(shí)和你無關(guān)。Elasticsearch有合理的默認(rèn)配置而且可以在沒有用戶干預(yù)的情況下做正確的事情。當(dāng)需要提升性能時(shí)你可以隨時(shí)回顧這些章節(jié)。
- 轉(zhuǎn)載自https://www.aliyun.com/jiaocheng/1184374.html
轉(zhuǎn)載于:https://www.cnblogs.com/double-orange/p/10049381.html
總結(jié)
以上是生活随笔為你收集整理的Elastic search 入门的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: sap制造业成本核算流程(转自互联网)
- 下一篇: php根据背景图片深浅加水印