Elasticsearch簡(jiǎn)介
Elasticsearch(簡(jiǎn)稱ES)是一個(gè)基于Apache Lucene(TM)的開源搜索引擎,無(wú)論在開源還是專有領(lǐng)域,Lucene可以被認(rèn)為是迄今為止最先進(jìn)、性能最好的、功能最全的搜索引擎庫(kù)。
但是,Lucene只是一個(gè)庫(kù)。想要發(fā)揮其強(qiáng)大的作用,你需使用Java并要將其集成到你的應(yīng)用中。Lucene非常復(fù)雜,你需要深入的了解檢索相關(guān)知識(shí)來(lái)理解它是如何工作的。
Elasticsearch也是使用Java編寫并使用Lucene來(lái)建立索引并實(shí)現(xiàn)搜索功能,但是它的目的是通過(guò)簡(jiǎn)單連貫的RESTful API讓全文搜索變得簡(jiǎn)單并隱藏Lucene的復(fù)雜性。
不過(guò),Elasticsearch不僅僅是Lucene和全文搜索引擎,它還提供:
分布式的實(shí)時(shí)文件存儲(chǔ),每個(gè)字段都被索引并可被搜索
實(shí)時(shí)分析的分布式搜索引擎
可以擴(kuò)展到上百臺(tái)服務(wù)器,處理PB級(jí)結(jié)構(gòu)化或非結(jié)構(gòu)化數(shù)據(jù)
而且,所有的這些功能被集成到一臺(tái)服務(wù)器,你的應(yīng)用可以通過(guò)簡(jiǎn)單的RESTful API、各種語(yǔ)言的客戶端甚至命令行與之交互。上手Elasticsearch非常簡(jiǎn)單,它提供了許多合理的缺省值,并對(duì)初學(xué)者隱藏了復(fù)雜的搜索引擎理論。它開箱即用(安裝即可使用),只需很少的學(xué)習(xí)既可在生產(chǎn)環(huán)境中使用。Elasticsearch在Apache 2 license下許可使用,可以免費(fèi)下載、使用和修改。
隨著知識(shí)的積累,你可以根據(jù)不同的問(wèn)題領(lǐng)域定制Elasticsearch的高級(jí)特性,這一切都是可配置的,并且配置非常靈活。
Elasticsearch中涉及到的重要概念
Elasticsearch有幾個(gè)核心概念。從一開始理解這些概念會(huì)對(duì)整個(gè)學(xué)習(xí)過(guò)程有莫大的幫助。
(1) 接近實(shí)時(shí)(NRT)
Elasticsearch是一個(gè)接近實(shí)時(shí)的搜索平臺(tái)。這意味著,從索引一個(gè)文檔直到這個(gè)文檔能夠被搜索到有一個(gè)輕微的延遲(通常是1秒)。
(2) 集群(cluster)
一個(gè)集群就是由一個(gè)或多個(gè)節(jié)點(diǎn)組織在一起,它們共同持有你整個(gè)的數(shù)據(jù),并一起提供索引和搜索功能。一個(gè)集群由一個(gè)唯一的名字標(biāo)識(shí),這個(gè)名字默認(rèn)就是“elasticsearch”。這個(gè)名字是重要的,因?yàn)橐粋€(gè)節(jié)點(diǎn)只能通過(guò)指定某個(gè)集群的名字,來(lái)加入這個(gè)集群。在產(chǎn)品環(huán)境中顯式地設(shè)定這個(gè)名字是一個(gè)好習(xí)慣,但是使用默認(rèn)值來(lái)進(jìn)行測(cè)試/開發(fā)也是不錯(cuò)的。
(3) 節(jié)點(diǎn)(node)
一個(gè)節(jié)點(diǎn)是你集群中的一個(gè)服務(wù)器,作為集群的一部分,它存儲(chǔ)你的數(shù)據(jù),參與集群的索引和搜索功能。和集群類似,一個(gè)節(jié)點(diǎn)也是由一個(gè)名字來(lái)標(biāo)識(shí)的,默認(rèn)情況下,這個(gè)名字是一個(gè)隨機(jī)的漫威漫畫角色的名字,這個(gè)名字會(huì)在啟動(dòng)的時(shí)候賦予節(jié)點(diǎn)。這個(gè)名字對(duì)于管理工作來(lái)說(shuō)挺重要的,因?yàn)樵谶@個(gè)管理過(guò)程中,你會(huì)去確定網(wǎng)絡(luò)中的哪些服務(wù)器對(duì)應(yīng)于Elasticsearch集群中的哪些節(jié)點(diǎn)。
一個(gè)節(jié)點(diǎn)可以通過(guò)配置集群名稱的方式來(lái)加入一個(gè)指定的集群。默認(rèn)情況下,每個(gè)節(jié)點(diǎn)都會(huì)被安排加入到一個(gè)叫做“elasticsearch”的集群中,這意味著,如果你在你的網(wǎng)絡(luò)中啟動(dòng)了若干個(gè)節(jié)點(diǎn),并假定它們能夠相互發(fā)現(xiàn)彼此,它們將會(huì)自動(dòng)地形成并加入到一個(gè)叫做“elasticsearch”的集群中。
在一個(gè)集群里,只要你想,可以擁有任意多個(gè)節(jié)點(diǎn)。而且,如果當(dāng)前你的網(wǎng)絡(luò)中沒有運(yùn)行任何Elasticsearch節(jié)點(diǎn),這時(shí)啟動(dòng)一個(gè)節(jié)點(diǎn),會(huì)默認(rèn)創(chuàng)建并加入一個(gè)叫做“elasticsearch”的集群。
(4) 索引(index)
一個(gè)索引就是一個(gè)擁有幾分相似特征的文檔的集合。比如說(shuō),你可以有一個(gè)客戶數(shù)據(jù)的索引,另一個(gè)產(chǎn)品目錄的索引,還有一個(gè)訂單數(shù)據(jù)的索引。一個(gè)索引由一個(gè)名字來(lái)標(biāo)識(shí)(必須全部是小寫字母的),并且當(dāng)我們要對(duì)對(duì)應(yīng)于這個(gè)索引中的文檔進(jìn)行索引、搜索、更新和刪除的時(shí)候,都要使用到這個(gè)名字。索引類似于關(guān)系型數(shù)據(jù)庫(kù)中Database的概念。在一個(gè)集群中,如果你想,可以定義任意多的索引。
(5) 類型(type)
在一個(gè)索引中,你可以定義一種或多種類型。一個(gè)類型是你的索引的一個(gè)邏輯上的分類/分區(qū),其語(yǔ)義完全由你來(lái)定。通常,會(huì)為具有一組共同字段的文檔定義一個(gè)類型。比如說(shuō),我們假設(shè)你運(yùn)營(yíng)一個(gè)博客平臺(tái)并且將你所有的數(shù)據(jù)存儲(chǔ)到一個(gè)索引中。在這個(gè)索引中,你可以為用戶數(shù)據(jù)定義一個(gè)類型,為博客數(shù)據(jù)定義另一個(gè)類型,當(dāng)然,也可以為評(píng)論數(shù)據(jù)定義另一個(gè)類型。類型類似于關(guān)系型數(shù)據(jù)庫(kù)中Table的概念。
(6)文檔(document)
一個(gè)文檔是一個(gè)可被索引的基礎(chǔ)信息單元。比如,你可以擁有某一個(gè)客戶的文檔,某一個(gè)產(chǎn)品的一個(gè)文檔,當(dāng)然,也可以擁有某個(gè)訂單的一個(gè)文檔。文檔以JSON(Javascript Object Notation)格式來(lái)表示,而JSON是一個(gè)到處存在的互聯(lián)網(wǎng)數(shù)據(jù)交互格式。
在一個(gè)index/type里面,只要你想,你可以存儲(chǔ)任意多的文檔。注意,盡管一個(gè)文檔,物理上存在于一個(gè)索引之中,文檔必須被索引/賦予一個(gè)索引的type。文檔類似于關(guān)系型數(shù)據(jù)庫(kù)中Record的概念。實(shí)際上一個(gè)文檔除了用戶定義的數(shù)據(jù)外,還包括_index、_type和_id字段。
(7) 分片和復(fù)制(shards & replicas)
一個(gè)索引可以存儲(chǔ)超出單個(gè)結(jié)點(diǎn)硬件限制的大量數(shù)據(jù)。比如,一個(gè)具有10億文檔的索引占據(jù)1TB的磁盤空間,而任一節(jié)點(diǎn)都沒有這樣大的磁盤空間;或者單個(gè)節(jié)點(diǎn)處理搜索請(qǐng)求,響應(yīng)太慢。
為了解決這個(gè)問(wèn)題,Elasticsearch提供了將索引劃分成多份的能力,這些份就叫做分片。當(dāng)你創(chuàng)建一個(gè)索引的時(shí)候,你可以指定你想要的分片的數(shù)量。每個(gè)分片本身也是一個(gè)功能完善并且獨(dú)立的“索引”,這個(gè)“索引”可以被放置到集群中的任何節(jié)點(diǎn)上。
分片之所以重要,主要有兩方面的原因:
允許你水平分割/擴(kuò)展你的內(nèi)容容量
允許你在分片(潛在地,位于多個(gè)節(jié)點(diǎn)上)之上進(jìn)行分布式的、并行的操作,進(jìn)而提高性能/吞吐量
至于一個(gè)分片怎樣分布,它的文檔怎樣聚合回搜索請(qǐng)求,是完全由Elasticsearch管理的,對(duì)于作為用戶的你來(lái)說(shuō),這些都是透明的。
在一個(gè)網(wǎng)絡(luò)/云的環(huán)境里,失敗隨時(shí)都可能發(fā)生,在某個(gè)分片/節(jié)點(diǎn)不知怎么的就處于離線狀態(tài),或者由于任何原因消失了。這種情況下,有一個(gè)故障轉(zhuǎn)移機(jī)制是非常有用并且是強(qiáng)烈推薦的。為此目的,Elasticsearch允許你創(chuàng)建分片的一份或多份拷貝,這些拷貝叫做復(fù)制分片,或者直接叫復(fù)制。復(fù)制之所以重要,主要有兩方面的原因:
在分片/節(jié)點(diǎn)失敗的情況下,提供了高可用性。因?yàn)檫@個(gè)原因,注意到復(fù)制分片從不與原/主要(original/primary)分片置于同一節(jié)點(diǎn)上是非常重要的。
擴(kuò)展你的搜索量/吞吐量,因?yàn)樗阉骺梢栽谒械膹?fù)制上并行運(yùn)行
總之,每個(gè)索引可以被分成多個(gè)分片。一個(gè)索引也可以被復(fù)制0次(意思是沒有復(fù)制)或多次。一旦復(fù)制了,每個(gè)索引就有了主分片(作為復(fù)制源的原來(lái)的分片)和復(fù)制分片(主分片的拷貝)之別。分片和復(fù)制的數(shù)量可以在索引創(chuàng)建的時(shí)候指定。在索引創(chuàng)建之后,你可以在任何時(shí)候動(dòng)態(tài)地改變復(fù)制數(shù)量,但是不能改變分片的數(shù)量。
默認(rèn)情況下,Elasticsearch中的每個(gè)索引被分片5個(gè)主分片和1個(gè)復(fù)制,這意味著,如果你的集群中至少有兩個(gè)節(jié)點(diǎn),你的索引將會(huì)有5個(gè)主分片和另外5個(gè)復(fù)制分片(1個(gè)完全拷貝),這樣的話每個(gè)索引總共就有10個(gè)分片。一個(gè)索引的多個(gè)分片可以存放在集群中的一臺(tái)主機(jī)上,也可以存放在多臺(tái)主機(jī)上,這取決于你的集群機(jī)器數(shù)量。主分片和復(fù)制分片的具體位置是由ES內(nèi)在的策略所決定的。
Elasticsearch安裝與配置
安裝與運(yùn)行
(1) 從這里下載Elasticsearch安裝包。一共提供4種格式的安裝包(ZIP、TAR.GZ、DEB和RPM),可以根據(jù)自己所使用的系統(tǒng)平臺(tái)選擇相應(yīng)格式的安裝包進(jìn)行下載。(建議使用Linux系統(tǒng),本人在2臺(tái)windows機(jī)器上嘗試啟動(dòng)過(guò),一臺(tái)機(jī)器上無(wú)法正常啟動(dòng),另外一臺(tái)可以)
(2) 對(duì)下載的安裝包進(jìn)行解壓縮即可完成安裝操作。下面以在Ubuntu操作系統(tǒng)下使用TAR.GZ格式的1.5.0版本的安裝包為例進(jìn)行安裝。在Linux shell中輸入下面的命令解壓縮。
tar –vxf elasticsearch-1.5.0.tar.gz
安裝成功,下面運(yùn)行ES。
注意:Elasticsearch需要Java虛擬機(jī)的支持,在運(yùn)行之前保證機(jī)器上安裝了JDK,并且JDK版本不能低于1.7_55。
(3) 現(xiàn)在可以直接使用默認(rèn)配置啟動(dòng)Elasticsearch了。
假設(shè)安裝包解壓后的目錄路徑為【/home/elasticsearch/elasticsearch-1.5.0】,下面軍用$ES_HOME來(lái)表示這個(gè)路徑。執(zhí)行下面的命令:
cd /home/elasticsearch/elasticsearch-1.5.0/bin/
chmod +x *
./elasticsearch
如果出現(xiàn)如圖所示的界面(最后打印出started),則說(shuō)明Elasticsearch啟動(dòng)成功。
下面來(lái)驗(yàn)證一下是否真的啟動(dòng)成功。打開瀏覽器,訪問(wèn)網(wǎng)址 http://host:9200(這里的host是ES的安裝主機(jī)地址,如果安裝在本機(jī),就是http://127.0.0.1:9200)。如果顯示下面的信息,則表示ES安裝成功。
{
"status" : 200,
"name" : "Captain Zero",
"cluster_name" : "elasticsearch",
"version" : {
"number" : "1.5.0",
"build_hash" : "544816042d40151d3ce4ba4f95399d7860dc2e92",
"build_timestamp" : "2015-03-23T14:30:58Z",
"build_snapshot" : false,
"lucene_version" : "4.10.4"
},
"tagline" : "You Know, for Search"
}
上面是前臺(tái)啟動(dòng)方式,一旦關(guān)閉Linux shell,ES服務(wù)就會(huì)停止。所以是實(shí)際使用過(guò)程中,絕對(duì)不會(huì)使用這種方式去啟動(dòng)ES。除了上面的啟動(dòng)方式外,還可以加上一定的啟動(dòng)參數(shù)。例如:
./elasticsearch –d #在后臺(tái)運(yùn)行Elasticsearch
./elasticsearch -d -Xmx2g -Xms2g #后臺(tái)啟動(dòng),啟動(dòng)時(shí)指定內(nèi)存大?。?G)
./elasticsearch -d -Des.logger.level=DEBUG #可以在日志中打印出更加詳細(xì)的信息。
ES的配置
配置文件所在的目錄路徑如下:$ES_HOME/config/elasticsearch.yml。
下面介紹一些重要的配置項(xiàng)及其含義。
(1)cluster.name: elasticsearch
配置elasticsearch的集群名稱,默認(rèn)是elasticsearch。elasticsearch會(huì)自動(dòng)發(fā)現(xiàn)在同一網(wǎng)段下的集群名為elasticsearch的主機(jī),如果在同一網(wǎng)段下有多個(gè)集群,就可以用這個(gè)屬性來(lái)區(qū)分不同的集群。生成環(huán)境時(shí)建議更改。
(2)node.name: “Franz Kafka”
節(jié)點(diǎn)名,默認(rèn)隨機(jī)指定一個(gè)name列表中名字,該列表在elasticsearch的jar包中config文件夾里name.txt文件中,其中有很多作者添加的有趣名字,大部分是漫威動(dòng)漫里面的人物名字。生成環(huán)境中建議更改以能方便的指定集群中的節(jié)點(diǎn)對(duì)應(yīng)的機(jī)器
(3)node.master: true
指定該節(jié)點(diǎn)是否有資格被選舉成為node,默認(rèn)是true,elasticsearch默認(rèn)集群中的第一臺(tái)啟動(dòng)的機(jī)器為master,如果這臺(tái)機(jī)掛了就會(huì)重新選舉master。
(4)node.data: true
指定該節(jié)點(diǎn)是否存儲(chǔ)索引數(shù)據(jù),默認(rèn)為true。如果節(jié)點(diǎn)配置node.master:false并且node.data: false,則該節(jié)點(diǎn)將起到負(fù)載均衡的作用
(5)index.number_of_shards: 5
設(shè)置默認(rèn)索引分片個(gè)數(shù),默認(rèn)為5片。經(jīng)本人測(cè)試,索引分片對(duì)ES的查詢性能有很大的影響,在應(yīng)用環(huán)境,應(yīng)該選擇適合的分片大小。
(6)index.number_of_replicas:
設(shè)置默認(rèn)索引副本個(gè)數(shù),默認(rèn)為1個(gè)副本。此處的1個(gè)副本是指index.number_of_shards的一個(gè)完全拷貝;默認(rèn)5個(gè)分片1個(gè)拷貝;即總分片數(shù)為10。
(7)path.conf: /path/to/conf
設(shè)置配置文件的存儲(chǔ)路徑,默認(rèn)是es根目錄下的config文件夾。
(8)path.data:/path/to/data1,/path/to/data2
設(shè)置索引數(shù)據(jù)的存儲(chǔ)路徑,默認(rèn)是es根目錄下的data文件夾,可以設(shè)置多個(gè)存儲(chǔ)路徑,用逗號(hào)隔開。
(9)path.work:/path/to/work
設(shè)置臨時(shí)文件的存儲(chǔ)路徑,默認(rèn)是es根目錄下的work文件夾。
(10)path.logs: /path/to/logs
設(shè)置日志文件的存儲(chǔ)路徑,默認(rèn)是es根目錄下的logs文件夾
(11)path.plugins: /path/to/plugins
設(shè)置插件的存放路徑,默認(rèn)是es根目錄下的plugins文件夾
(12)bootstrap.mlockall: true
設(shè)置為true來(lái)鎖住內(nèi)存。因?yàn)楫?dāng)jvm開始swapping時(shí)es的效率會(huì)降低,所以要保證它不swap,可以把ES_MIN_MEM和ES_MAX_MEM兩個(gè)環(huán)境變量設(shè)置成同一個(gè)值,并且保證機(jī)器有足夠的內(nèi)存分配給es。同時(shí)也要允許elasticsearch的進(jìn)程可以鎖住內(nèi)存,linux下可以通過(guò)
ulimit -l unlimited命令。
(13)network.bind_host: 192.168.0.1
設(shè)置綁定的ip地址,可以是ipv4或ipv6的,默認(rèn)為0.0.0.0。
(14)network.publish_host: 192.168.0.1
設(shè)置其它節(jié)點(diǎn)和該節(jié)點(diǎn)交互的ip地址,如果不設(shè)置它會(huì)自動(dòng)判斷,值必須是個(gè)真實(shí)的ip地址。
(15)network.host: 192.168.0.1
這個(gè)參數(shù)是用來(lái)同時(shí)設(shè)置bind_host和publish_host上面兩個(gè)參數(shù)。
(16)transport.tcp.port: 9300
設(shè)置節(jié)點(diǎn)間交互的tcp端口,默認(rèn)是9300。
(17)transport.tcp.compress: true
設(shè)置是否壓縮tcp傳輸時(shí)的數(shù)據(jù),默認(rèn)為false,不壓縮。
(18)http.port: 9200
設(shè)置對(duì)外服務(wù)的http端口,默認(rèn)為9200。
(19)http.max_content_length: 100mb
設(shè)置內(nèi)容的最大容量,默認(rèn)100mb
(20)http.enabled: false
是否使用http協(xié)議對(duì)外提供服務(wù),默認(rèn)為true,開啟。
(21)gateway.type: local
gateway的類型,默認(rèn)為local即為本地文件系統(tǒng),可以設(shè)置為本地文件系統(tǒng),分布式文件系統(tǒng),hadoop的HDFS,和amazon的s3服務(wù)器,其它文件系統(tǒng)的設(shè)置。
(22)gateway.recover_after_nodes: 1
設(shè)置集群中N個(gè)節(jié)點(diǎn)啟動(dòng)時(shí)進(jìn)行數(shù)據(jù)恢復(fù),默認(rèn)為1。
(23)gateway.recover_after_time: 5m
設(shè)置初始化數(shù)據(jù)恢復(fù)進(jìn)程的超時(shí)時(shí)間,默認(rèn)是5分鐘。
(24)gateway.expected_nodes: 2
設(shè)置這個(gè)集群中節(jié)點(diǎn)的數(shù)量,默認(rèn)為2,一旦這N個(gè)節(jié)點(diǎn)啟動(dòng),就會(huì)立即進(jìn)行數(shù)據(jù)恢復(fù)。
(25)cluster.routing.allocation.node_initial_primaries_recoveries: 4
初始化數(shù)據(jù)恢復(fù)時(shí),并發(fā)恢復(fù)線程的個(gè)數(shù),默認(rèn)為4。
(26)cluster.routing.allocation.node_concurrent_recoveries: 2
添加刪除節(jié)點(diǎn)或負(fù)載均衡時(shí)并發(fā)恢復(fù)線程的個(gè)數(shù),默認(rèn)為4。
(27)indices.recovery.max_size_per_sec: 0
設(shè)置數(shù)據(jù)恢復(fù)時(shí)限制的帶寬,如入100mb,默認(rèn)為0,即無(wú)限制。
(28)indices.recovery.concurrent_streams: 5
設(shè)置這個(gè)參數(shù)來(lái)限制從其它分片恢復(fù)數(shù)據(jù)時(shí)最大同時(shí)打開并發(fā)流的個(gè)數(shù),默認(rèn)為5。
(29)discovery.zen.minimum_master_nodes: 1
設(shè)置這個(gè)參數(shù)來(lái)保證集群中的節(jié)點(diǎn)可以知道其它N個(gè)有master資格的節(jié)點(diǎn)。默認(rèn)為1,對(duì)于大的集群來(lái)說(shuō),可以設(shè)置大一點(diǎn)的值(2-4)
(30)discovery.zen.ping.timeout: 3s
設(shè)置集群中自動(dòng)發(fā)現(xiàn)其它節(jié)點(diǎn)時(shí)ping連接超時(shí)時(shí)間,默認(rèn)為3秒,對(duì)于比較差的網(wǎng)絡(luò)環(huán)境可以高點(diǎn)的值來(lái)防止自動(dòng)發(fā)現(xiàn)時(shí)出錯(cuò)。
(31)discovery.zen.ping.multicast.enabled: false
設(shè)置是否打開多播發(fā)現(xiàn)節(jié)點(diǎn),默認(rèn)是true。
(32)discovery.zen.ping.unicast.hosts: [“host1”, “host2:port”, “host3 [portX-portY] “]
設(shè)置集群中master節(jié)點(diǎn)的初始列表,可以通過(guò)這些節(jié)點(diǎn)來(lái)自動(dòng)發(fā)現(xiàn)新加入集群的節(jié)點(diǎn)。
除了上面的在安裝時(shí)配置文件中就自帶的配置項(xiàng)外,本人在實(shí)際使用過(guò)程還使用到了下面的配置:
threadpool:
search:
type: fixed
min: 60
max: 80
queue_size: 1000
// 配置es服務(wù)器的執(zhí)行查詢操作時(shí)所用線程池,fix固定線程數(shù)的線程池。
index :
store:
type: memory
// 表示索引存儲(chǔ)在內(nèi)存中,當(dāng)然es不太建議這么做。經(jīng)本人測(cè)試,做查詢時(shí),使用內(nèi)存索引并不會(huì)比正常的索引快。
index.mapper.dynamic: false
// 禁止自動(dòng)創(chuàng)建mapping。默認(rèn)情況下,es可以根據(jù)數(shù)據(jù)類型自動(dòng)創(chuàng)建mapping。配置成這樣,可以禁止自動(dòng)創(chuàng)建mapping的行為。至于什么是mapping,在之后的博文中再介紹。
index.query.parse.allow_unmapped_fields: false
// 不能查找沒有在mapping中定義的屬性
以上總結(jié)介紹了Elasticsearch中的一些基礎(chǔ)知識(shí),包括其中的一些核心概念。只有理解了ES中的這些核心概念,才能對(duì)更加得心應(yīng)手地使用ES,發(fā)揮其強(qiáng)大的搜索能力。同時(shí),也介紹了ES的安裝和運(yùn)行,ES的安裝和運(yùn)行是很簡(jiǎn)單的,只需要極少的簡(jiǎn)單步驟,就可以開始體驗(yàn)ES。ES的配置非常豐富,安裝時(shí)自帶的配置文件只包含一部分比較核心的配置項(xiàng),更多的配置內(nèi)容需要自己去閱讀ES的源碼時(shí)才能被發(fā)現(xiàn)。
ES Restful API基本使用:
ES為開發(fā)者提供了非常豐富的基于HTTP協(xié)議的Rest API,只需要向ES服務(wù)端發(fā)送簡(jiǎn)單的Rest請(qǐng)求,就可以實(shí)現(xiàn)非常強(qiáng)大的功能。本篇文章主要介紹ES中常用操作的Rest API的使用,同時(shí)會(huì)講解ES的源代碼工程中的API接口文檔,通過(guò)了解這個(gè)API文檔的接口描述結(jié)構(gòu),就基本上可以實(shí)現(xiàn)ES中的絕大部分功能。
注意:查詢是ES的核心。作為一個(gè)先進(jìn)的搜索引擎,ES中提供了多種查詢接口。本篇僅僅會(huì)涉及查詢API的結(jié)構(gòu),而具體如何使用ES所提供的各種查詢API,會(huì)在接下來(lái)的博文中做詳細(xì)介紹。
基礎(chǔ)知識(shí)
如果之前沒有用過(guò)類似于ES這樣的索引數(shù)據(jù)庫(kù)(暫且將ES歸為數(shù)據(jù)庫(kù)類,與傳統(tǒng)的數(shù)據(jù)庫(kù)有較大的區(qū)別),要理解本篇博文介紹的API是有些難度的。本節(jié)先介紹一些基礎(chǔ)知識(shí),對(duì)理解全文有很幫助。
Rest介紹
筆者在學(xué)習(xí)軟件開發(fā)過(guò)程中,多次聽到過(guò)Rest Http這個(gè)概念,但在很長(zhǎng)的一段時(shí)間里,死活搞不懂這玩意到底是個(gè)什么東西。剛開始看相關(guān)資料時(shí),看得云里霧里,完全不知所云 _。這玩意太過(guò)于抽象和理論,心里覺得有必要搞這么復(fù)雜么。隨著自己動(dòng)手開發(fā)的東西越來(lái)越多,才開始對(duì)它有了一丟丟感覺。
Rest完全不是三言兩語(yǔ)就能將清楚的,它有自己的一套體系,所以筆者打算以后單獨(dú)寫一些有關(guān)Rest的博文。在這里推薦一篇優(yōu)秀的文章,它對(duì)Rest講的相當(dāng)清楚,本人看完之后真有醍醐灌頂?shù)母杏X!
Mapping詳解
Mapping是ES中的一個(gè)很重要的內(nèi)容,它類似于傳統(tǒng)關(guān)系型數(shù)據(jù)中table的schema,用于定義一個(gè)索引(index)的某個(gè)類型(type)的數(shù)據(jù)的結(jié)構(gòu)。
在傳統(tǒng)關(guān)系型數(shù)據(jù)庫(kù),我們必須首先創(chuàng)建table并同時(shí)定義其schema,如下面的SQL語(yǔ)句。下面代碼中小括號(hào)內(nèi)的代碼的作用就是定義person_info的schema(模式)。
create table person_info
(
name varchar(20),
age tinyint
)
在ES中,我們無(wú)需手動(dòng)創(chuàng)建type(相當(dāng)于table)和mapping(相關(guān)與schema)。在默認(rèn)配置下,ES可以根據(jù)插入的數(shù)據(jù)自動(dòng)地創(chuàng)建type及其mapping。在下面的API介紹部分中,會(huì)做相關(guān)的試驗(yàn)。當(dāng)然,在實(shí)際使用過(guò)程中我們可能就想硬性規(guī)定mapping,可以通過(guò)配置文件關(guān)閉ES的自動(dòng)創(chuàng)建mapping功能。
mapping中主要包括字段名、字段數(shù)據(jù)類型和字段索引類型這3個(gè)方面的定義。
字段名:這就不用說(shuō)了,與傳統(tǒng)數(shù)據(jù)庫(kù)字段名作用一樣,就是給字段起個(gè)唯一的名字,好讓系統(tǒng)和用戶能識(shí)別。
字段數(shù)據(jù)類型:定義該字段保存的數(shù)據(jù)的類型,不符合數(shù)據(jù)類型定義的數(shù)據(jù)不能保存到ES中。下表列出的是ES中所支持的數(shù)據(jù)類型。(大類是對(duì)所有類型的一種歸類,小類是實(shí)際使用的類型。)
| 大類 | 包含的小類 |
|---|---|
| String | string |
| Whole number | byte, short, integer, long |
| Floating point | float, double |
| Boolean | boolean |
| Date | date |
字段索引類型:索引是ES中的核心,ES之所以能夠?qū)崿F(xiàn)實(shí)時(shí)搜索,完全歸功于Lucene這個(gè)優(yōu)秀的Java開源索引。在傳統(tǒng)數(shù)據(jù)庫(kù)中,如果字段上建立索引,我們?nèi)匀荒軌蛞运鳛椴樵儣l件進(jìn)行查詢,只不過(guò)查詢速度慢點(diǎn)。而在ES中,字段如果不建立索引,則就不能以這個(gè)字段作為查詢條件來(lái)搜索。也就是說(shuō),不建立索引的字段僅僅能起到數(shù)據(jù)載體的作用。string類型的數(shù)據(jù)肯定是日常使用得最多的數(shù)據(jù)類型,下面介紹mapping中string類型字段可以配置的索引類型。
| 索引類型 | 解釋 |
|---|---|
| analyzed | 首先分析這個(gè)字符串,然后再建立索引。換言之,以全文形式索引此字段。 |
| not_analyzed | 索引這個(gè)字段,使之可以被搜索,但是索引內(nèi)容和指定值一樣。不分析此字段。 |
| no | 不索引這個(gè)字段。這個(gè)字段不能被搜索到。 |
如果索引類型設(shè)置為analyzed,在表示ES會(huì)先對(duì)這個(gè)字段進(jìn)行分析(一般來(lái)說(shuō),就是自然語(yǔ)言中的分詞),ES內(nèi)置了不少分析器(analyser),如果覺得它們對(duì)中文的支持不好,也可以使用第三方分析器。由于筆者在實(shí)際項(xiàng)目中僅僅將ES用作普通的數(shù)據(jù)查詢引擎,所以并沒有研究過(guò)這些分析器。如果將ES當(dāng)做真正的搜索引擎,那么挑選正確的分析器是至關(guān)重要的。
mapping中除了上面介紹的3個(gè)主要的內(nèi)容外,還有其他的定義內(nèi)容,詳見官網(wǎng)文檔。
常用的Rest API介紹
下面介紹一下ES中的一些常用的Rest API。掌握了這些API的用法,基本上就可以簡(jiǎn)單地使用ES了。
我們需要借助能夠發(fā)送HTTP請(qǐng)求的工具調(diào)用這些API,工具是可以任意的,包括網(wǎng)頁(yè)瀏覽器。這里利用Linux上的curl命令來(lái)發(fā)送HTTP請(qǐng)求。基本的命令結(jié)構(gòu)為:
curl <-Xaction> url -d 'body'
# 這里的action表示HTTP協(xié)議中的各種動(dòng)作,包括GET、POST、PUT、DELETE等。
注意。文中的示例代碼里面包含了用戶注釋的文字,就是 # 號(hào)后面的文字。運(yùn)行代碼時(shí),請(qǐng)注意刪除這些注釋。
查看集群(Cluster)信息相關(guān)API
(1)查看集群健康信息。
curl -XGET "localhost:9200/_cat/heath?v"
返回結(jié)果為:
epoch timestamp cluster status node.total node.data shards pri relo init unassign pending_tasks
1440206633 18:23:53 elasticsearch green 1 1 0 0 0 0 0 0
返回結(jié)果的主要字段意義:
- cluster:集群名,是在ES的配置文件中配置的cluster.name的值。
- status:集群狀態(tài)。集群共有g(shù)reen、yellow或red中的三種狀態(tài)。green代表一切正常(集群功能齊全),yellow意味著所有的數(shù)據(jù)都是可用的,但是某些復(fù)制沒有被分配(集群功能齊全),red則代表因?yàn)槟承┰?,某些?shù)據(jù)不可用。如果是red狀態(tài),則要引起高度注意,數(shù)據(jù)很有可能已經(jīng)丟失。
- node.total:集群中的節(jié)點(diǎn)數(shù)。
- node.data:集群中的數(shù)據(jù)節(jié)點(diǎn)數(shù)。
- shards:集群中總的分片數(shù)量。
- pri:主分片數(shù)量,英文全稱為private。
- relo:復(fù)制分片總數(shù)。
- unassign:未指定的分片數(shù)量,是應(yīng)有分片數(shù)和現(xiàn)有的分片數(shù)的差值(包括主分片和復(fù)制分片)。
我們也可以在請(qǐng)求中添加help參數(shù)來(lái)查看每個(gè)操作返回結(jié)果字段的意義。
curl -XGET "localhost:9200/_cat/heath?help"
返回結(jié)果如下:
epoch | t,time | seconds since 1970-01-01 00:00:00
timestamp | ts,hms,hhmmss | time in HH:MM:SS
cluster | cl | cluster name
status | st | health status
node.total | nt,nodeTotal | total number of nodes
node.data | nd,nodeData | number of nodes that can store data
shards | t,sh,shards.total,shardsTotal | total number of shards
pri | p,shards.primary,shardsPrimary | number of primary shards
relo | r,shards.relocating,shardsRelocating | number of relocating nodes
init | i,shards.initializing,shardsInitializing | number of initializing nodes
unassign | u,shards.unassigned,shardsUnassigned | number of unassigned shards
pending_tasks | pt,pendingTasks | number of pending tasks
確實(shí)是很好很強(qiáng)大。有了這個(gè)東東,就可以減少看文檔的時(shí)間。ES中許多API都可以添加help參數(shù)來(lái)顯示字段含義,哪些可以這么做呢?每個(gè)API都試試就知道了。
當(dāng)然,如果你覺得返回的東西太多,看著眼煩,我們也可以人為地指定返回的字段。
curl -XGET "localhost:9200/_cat/health?h=cluster,pri,relo&v"
這次的返回結(jié)果就簡(jiǎn)單很多羅。對(duì)于患有嚴(yán)重強(qiáng)迫癥的患者來(lái)說(shuō),這是福音??!
cluster pri relo
elasticsearch 0 0
(2)查看集群中的節(jié)點(diǎn)信息。
curl -XGET "localhost:9200/_cat/nodes?v"
返回節(jié)點(diǎn)的詳細(xì)信息如下:
host ip heap.percent ram.percent load node.role master name
master.hadoop localhost 3 35 0.00 d * Ezekiel
(3)查看集群中的索引信息。
curl -XGET "localhost:9200/_cat/indices?v"
返回集群中的索引信息如下:
health status index pri rep docs.count docs.deleted store.size pri.store.size
yellow open index_test 5 1 0 0 575b 575b
更多的查看和監(jiān)視ES的API參見官網(wǎng)文檔。
索引(Index)相關(guān)API
(1)創(chuàng)建一個(gè)新的索引。
curl -XPUT "localhost:9200/index_test"
如果返回下面的信息,則說(shuō)明索引創(chuàng)建成功。如果不是,則ES會(huì)返回相應(yīng)的異常信息。通??梢酝ㄟ^(guò)異常信息的最后一項(xiàng)推斷出失敗的原因。
{
"acknowledged": true
}
上面的操作使用默認(rèn)的配置信息創(chuàng)建一個(gè)索引。大多數(shù)情況下,我們想在索引創(chuàng)建的時(shí)候就將我們所需的mapping和其他配置確定好。下面的操作就可以在創(chuàng)建索引的同時(shí),創(chuàng)建settings和mapping。
curl -XPUT "localhost:9200/index_test" -d ' # 注意這里的'號(hào)
{
"settings": {
"index": {
"number_of_replicas": "1", # 設(shè)置復(fù)制數(shù)
"number_of_shards": "5" # 設(shè)置主分片數(shù)
}
},
"mappings": { # 創(chuàng)建mapping
"test_type": { # 在index中創(chuàng)建一個(gè)新的type(相當(dāng)于table)
"properties": {
"name": { # 創(chuàng)建一個(gè)字段(string類型數(shù)據(jù),使用普通索引)
"type": "string",
"index": "not_analyzed"
},
"age": {
"type": "integer"
}
}
}
}
}'
(2)刪除一個(gè)索引。
curl -XDELETE "localhost:9200/index_test"
如果返回與創(chuàng)建索引同樣的信息,則說(shuō)明刪除成功。反之,則返回相應(yīng)的異常信息。更多的索引操作參見ES官網(wǎng)文檔。
映射(Mapping)相關(guān)API
(1)創(chuàng)建索引的mapping。
curl -XPUT 'localhost:9200/index_test/_mapping/test_type' -d '
{
"test_type": { # 注意,這里的test_type與url上的test_type名保存一致
"properties": {
"name": {
"type": "string",
"index": "not_analyzed"
},
"age": {
"type": "integer"
}
}
}
}'
如果不想單獨(dú)創(chuàng)建mapping,可以使用上一節(jié)的方法(創(chuàng)建索引時(shí)創(chuàng)建mappings)。
假設(shè)我們的項(xiàng)目中有多個(gè)環(huán)境(開發(fā)環(huán)境、測(cè)試環(huán)境等),那每一個(gè)環(huán)境的mapping總要一致的吧,那每次創(chuàng)建一次mappings就比較麻煩了,而且還容易導(dǎo)致數(shù)據(jù)不一致。莫急,ES還給我們準(zhǔn)備另外一種創(chuàng)建mapping的方式??梢园凑障旅娴牟襟E來(lái)做。
步驟1 創(chuàng)建一個(gè)擴(kuò)展名為test_type.json的文件名,其中type_test就是mapping所對(duì)應(yīng)的type名。
步驟2 在test_type.json中輸入mapping信息。假設(shè)你的mapping如下:
{
"test_type": { # 注意,這里的test_type與json文件名必須一致
"properties": {
"name": {
"type": "string",
"index": "not_analyzed"
},
"age": {
"type": "integer"
}
}
}
}
步驟3 在$ES_HOME/config/路徑下創(chuàng)建mappings/index_test子目錄,這里的index_test目錄名必須與我們要建立的索引名一致。將test_type.json文件拷貝到index_tes目錄下。
步驟4 創(chuàng)建index_test索引。操作如下:
curl -XPUT "localhost:9200/index_test" # 注意,這里的索引名必須與mappings下新建的index_test目錄名一致
這樣我們就創(chuàng)建了一個(gè)新的索引,并且使用了test_type.json所定義的mapping作為索引的mapping。就是這么簡(jiǎn)單方便!
(2)刪除mapping。
curl -XDELETE 'localhost:9200/index_test/_mapping/test_type'
(3)查看索引的mapping。
curl -XGET 'localhost:9200/index_test/_mapping/test_type'
更多的mapping相關(guān)操作參加官網(wǎng)文檔。
文檔(document)相關(guān)API
(1)新增一個(gè)文檔。
curl -XPUT 'localhost:9200/index_test/test_type/1?pretty' -d ' # 這里的pretty參數(shù)的作用是使得返回的json顯示地更加好看。1是文檔的id值(唯一鍵)。
{
"name": "zhangsan",
"age" : "12"
}'
(2)更新一個(gè)文檔
curl -XPOST 'localhost:9200/index_test/test_type/1?pretty' -d ' # 這里的1必須是索引中已經(jīng)存在id,否則就會(huì)變成新增文檔操作
{
"name": "lisi",
"age" : "12"
}'
(3)刪除一個(gè)文檔
curl -XDELETE 'localhost:9200/index_test/test_type/1?pretty' # 這里的1必須是索引中已經(jīng)存在id
(4)查詢單個(gè)文檔
curl -XGET 'localhost:9200/index_test/test_type/1?pretty'
上面的操作僅僅查詢id為1的一條文檔,這樣看似乎ES的查詢也太弱了。前面已經(jīng)說(shuō)過(guò)了,查詢操作是ES中的核心,是其立身的根本。但是本文的重點(diǎn)并不在這里,為了防止文章的篇幅過(guò)長(zhǎng),之后將專本介紹ES中的查詢操作。
源代碼中提供的Rest API文檔結(jié)構(gòu)
ES的源代碼托管在Github上。將源代碼下載下來(lái)之后,里面有一個(gè)文件夾專門存放ES中絕大部分的Rest API。有了這些文檔,就不必每次都要到官網(wǎng)上查詢接口文檔了(PS:ES的官網(wǎng)真的很慢)。
下面以cat.health.json文件為例簡(jiǎn)單地介紹這些Rest API文檔的結(jié)構(gòu)。一旦結(jié)構(gòu)搞清楚了,文檔看起來(lái)就比較順心,ES用起來(lái)就更加得心應(yīng)手了!
{
"cat.health": {
"documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-health.html", # 該文檔對(duì)應(yīng)的官方站點(diǎn)
"methods": ["GET"],
"url": { # url部分可選
"path": "/_cat/health",
"paths": ["/_cat/health"],
"parts": {
},
"params": {
"local": {
"type" : "boolean",
"description" : "Return local information, do not retrieve the state from master node (default: false)"
},
"master_timeout": {
"type" : "time",
"description" : "Explicit operation timeout for connection to master node"
},
"h": {
"type": "list",
"description" : "Comma-separated list of column names to display"
},
"help": {
"type": "boolean",
"description": "Return help information",
"default": false
},
"ts": {
"type": "boolean",
"description": "Set to false to disable timestamping",
"default": true
},
"v": {
"type": "boolean",
"description": "Verbose mode. Display column headers",
"default": true
}
}
},
"body": null
}
}
上面文檔接口所對(duì)應(yīng)的Reqeust操作如下:
curl -XGET "localhost:9200/_cat/health?v" -d 'body'
該操作命令可劃分為5個(gè)部分,下面把這5個(gè)部分與文檔對(duì)應(yīng)起來(lái)。通過(guò)這個(gè)例子,就可以在閱讀其他文檔后,使用正確的操作了。
- 第1部分(-XGET):對(duì)應(yīng)文檔中methods所包含的GET操作。
- 第2部分(localhost:9200):是ES服務(wù)端所在主機(jī)的hostname和port。
- 第3部分(/_cat/health):對(duì)應(yīng)文檔中的url。其中path是最簡(jiǎn)單的url;paths是除了path之外的其他url;parts描述和解釋paths里面的url的可變部分(通常用{}包裹,如{index})。
- 第4部分v:表示參數(shù),對(duì)應(yīng)文檔中的params。像“v”這種boolean類型的參數(shù),不需要特意指定其布爾值(true或者false),出現(xiàn)即表示true,否則為false。
- 第5部分body:表示要傳遞的數(shù)據(jù)主體,對(duì)應(yīng)文檔中的body。如果body里面指明“required=true”,則表示必須傳入body數(shù)據(jù)。具體body里面需要傳怎樣的數(shù)據(jù),則可以訪問(wèn)文檔中的documentation字段所指明的官方站點(diǎn)進(jìn)行查詢。
總結(jié)
本文重點(diǎn)介紹了ES中的一些常用Rest API的用法,并在開始部分簡(jiǎn)單地介紹了一些基礎(chǔ)知識(shí)(Rest和mapping)。掌握了這些API的調(diào)用,就可以利用ES完成簡(jiǎn)單的應(yīng)用程序了。當(dāng)然,ES的API遠(yuǎn)不止這些,如果想要更加深入地了解ES的使用及其內(nèi)部原理,建議先仔細(xì)地閱讀ES的官網(wǎng)文檔。然后下載其源代碼進(jìn)行研究。