- Elastic Stack應用寶典
- 田雪松編著
- 3552字
- 2020-07-22 17:21:24
2.5 客戶端API概覽
Elasticsearch提供了豐富的客戶端API操作和訪問文檔,支持Java、JavaScript、Groovy、.NET、PHP、Perl、Python、Ruby等多種語言。但Elasticsearch最基本的訪問方式還是通過REST接口,以HTTP協議的形式操作文檔數據。除此之外,Elasticsearch還內置一種稱為Painless的腳本語言,可以在API中使用。本節將從總體上介紹REST接口和Painless腳本語言,同時也會簡要介紹一下基于Java語言的API。
2.5.1 REST接口
在前述章節的講解中,大部分示例代碼中使用的就是Elasticsearch提供的REST接口。REST有自己獨特的規范和約定,Elasticsearch的REST接口基本遵從了這些規范和約定,所以了解REST的一些基礎知識,對于理解Elasticsearch客戶端接口是有一定幫助的。
REST可以理解為一種架構風格,它核心的思想是認為一切都是資源,而應用程序則是通過更改資源的狀態實現具體功能。REST中的資源可以理解為數據,并且以URI為惟一標識。所以構建REST風格的URI,一個重要原則就是它們應該都是名詞。Elasticsearch的主要資源就是索引、映射類型和文檔,它們在Elasticsearch定義的URI中是有次序的。例如在“/users/_doc/1”這個URI中,users為索引名,_doc為類型名,而1則是文檔的ID。在版本7中,映射類型已經被提升為一種內置資源,用戶不能再自定義映射類型名稱。內置資源要么以下劃線“_”開頭,要么以“.”開頭,一般都是一些具有特別用途的資源。除了映射類型_doc以外,Elasticsearch提供的所有接口也都是以下劃線“_”開頭的,例如_search、_cat、_cluster等。
REST這種將URI定義為名詞的作法,與早期軟件系統定義的URI有很大區別。例如,對于查看用戶來說,以往定義的URI一般是“listUsers.do”。因為它即包含了資源users,又包含了對資源的操作list,所以不是REST風格的URI。在REST中對資源的操作是通過HTTP的七種請求方法完成的,即POST、PUT、GET、DELETE、HEAD、OPTIONS、TRACE。但常用的請求方法一般只有4種,即POST、PUT、GET、DELETE。簡單來說,POST可以理解為新增資源,PUT為新增或修改資源,GET為查詢資源,DELETE為刪除資源。具體到Elasticsearch中,創建一個索引可以使用PUT請求,如PUT test代表創建一個名為test的索引,“PUT test/_doc/1”則代表在test索引的_doc類型下增加ID為1的文檔。除此之外,Elasticsearch還支持HEAD請求,用于做存在性查詢,即查看一個資源是否存在。
這里要特別說明一下POST和PUT的區別。PUT新增資源是直接通過URI標明資源是哪一個,所以對同一個URI多次PUT請求時,只有第一次請求是執行新增操作;之后所有的PUT請求都可以理解為對資源的更新。所以一般說PUT請求是冪等的,即對同一資源請求多次的結果是一樣的。而POST請求則不同,它的URI一般是要操作資源的父資源,所以對同一URI請求多次會一直新增資源。舉例來說,多次請求“PUT test/_doc/1”相當于一直在更新ID為1的文檔,文檔的_id字段值為1。而使用POST請求時應該為“POST test/_doc/”,多次請求時會不斷向test索引中添加新文檔,而每次文檔的_id字段都由Elasticsearch自動產生。在Elasticsearch中可以同時使用POST和PUT請求更新一份文檔,但通過映射類型添加文檔則只能使用POST請求。
本書后續章節在講解Elasticsearch具體操作、檢索接口時都會使用REST接口,讀者在調用時可以使用Kibana控制臺,也可以使用curl命令。在調用這些REST接口時有一些比較通用的規則,下面將分別介紹。
1.多索引
REST接口的URI一般都對應一個資源,但Elasticsearch在操作索引時可以在URI中指定多個,也可以使用通配符匹配多個索引。具體來說,多個索引使用逗號分隔開出現在URI中,可以在索引名稱中使用星號匹配任意字符,還可以在URI中使用_all代表所有索引,如示例2-19所示:

示例2-19 多索引
需要注意的是,并不是所有Elaticsearch接口都支持多索引,在不支持多索引的接口中使用上述格式的URI將會報錯。
2.通用參數
有一些參數對于所有Elasticsearch接口都是有效的,它們一般用于定義接口返回結果的內容和格式定義。比如在接口請求中添加“?pretty=true”,可以讓返回的JSON結果以更易讀的格式展示出來;添加“?format=yaml”則可以讓返回結果以YAML格式展示出來;而添加“?human=true”則會讓返回結果字段以更易于人類理解的方式展示。
除了以上參數,還有一個比較有用的參數filter_path。這個參數用于過濾返回結果中的字段,參數值是希望在返回結果中展示的字段路徑。例如,如果只想查看返回結果中的_source字段值,那么就可以使用“hits.hits._source”。這是因為在使用_search接口檢索文檔時,_source字段是在返回結果的hits.hits字段。本書第6章在講解聚集查詢時,在所有示例中都會使用filter_path參數以過濾聚集結果。
2.5.2 Painless腳本
在Elasticsearch的許多接口中都可以使用腳本做動態運算,支持包括Painless、expression、mustache和Java在內的4種腳本語言。在這些語言中,Java語言雖然通用,但沒有提供內置支持,需要用戶自行開發插件;而Painless則是Elasticsearch支持最好的一種腳本語言,所以本小節將簡單介紹一下這種語言。
Painless是Elasticsearch在5.0版本之后提供的一種簡單安全且高性能的腳本語言,它的名稱也反映出它在使用上讓人更愉悅。Painless以Java語言為基礎,最終會被編譯為字節碼并運行在JVM上。所以Painless在語法上與Java語言基本相同,并添加了動態類型、Map和List快捷訪問等新功能。
為了便于學習和測試Painless腳本,Elasticsearch還專門提供了一個腳本執行接口。接口地址為_scripts/painless/_execute,支持使用GET或POST方法調用。腳本執行接口的script參數接收Painless腳本,其中它的子參數source用于編寫腳本本身,而params則用于給腳本傳遞參數。例如示例2-20中的腳本片段會將列表list中的元素累加起來并返回:

示例2-20 Painless腳本執行接口
通過示例2-20代碼可以看出,Painless語言與Java語言非常相似。但為了講解Painless語言特性,代碼中特意添加了三處Painless特有語法,否則它會與Java代碼完全相同。在這三處特有語法中,一個是在第5行中List初始化使用的“[...]”的格式,另一個是在第7行for循環中使用了def動態類型聲明變量,還有一個就是第10行腳本最后一句沒有用return。在Painless中,“[...]”格式不僅可以初始化List,還可以初始化Map,只是在括號中的元素需要用冒號分隔為鍵和值兩部分。例如:

示例2-21 初始化Map
這種初始化方式只是一種語法糖,在編寫時完全可以按Java語法的形式初始化它們,只不過要麻煩一些。實際上def也是一種語法糖,其實在示例2-20中的list、result都可以使用def來聲明。所以,如果不想在Painless語法上花費太多精力,可以完全按Java語法編寫腳本。
如果希望Painless腳本返回一個具體數值,則需要在最后一句使用return語句返回值,或者像示例2-20中那樣只寫一個變量或表達式。在實際應用中,Painless腳本往往就是一句簡單的表達式,用于從Elasticsearch的對象中求解某個值。這就牽出另外一個問題,即Painless腳本如何訪問Elasticsearch中的對象,比如如何從文檔中讀取某一字段值。
Painless為每段腳本的執行定義了一個上下文,而在這個上下文中則保存了腳本需要的大部分環境數據。但由于Painless執行的上下文有多種情況,所以它們包含的數據也不相同。本節就不在此一一列舉,而會在后續章節中具體用到Painless腳本的接口中介紹它們。
Painless可以使用Java風格的注釋語句,支持分支、循環等控制結構,所以Painless有一些關鍵字不能用于聲明標識符。Painless關鍵字比Java少很多,一共只有15個。表2-5列出了所有可用關鍵字,從中可以看出Painless都支持哪些語句類型。
表2-5 Painless關鍵字

通過表2-5可以看出,Painless支持除switch語句以外的所有控制語句。有關Painless語言就暫時介紹這么多,對于有Java語言基礎的用戶來說,完全可以按Java語法來編寫腳本。本書后續章節在具體應用到Painless腳本時還會再詳細介紹,這里就不再贅述。
2.5.3 Java API
由于REST接口基于HTTP協議而與客戶端語言無關,所以使用Java調用Elasticsearch完全可以使用Apache HttpClient這樣的開源框架實現。例如示例2-22中的代碼就是直接使用HttpClient調用Elasticsearch:


示例2-22 使用HttpClient調用Elasticsearch
Elasticsearch官方提供的Java客戶端API底層其實也是基于HttpClient框架,它在此基礎上做封裝并提供了兩種解決方案。第一種解決方案封裝的比較簡單,開放出來的接口還是REST調用形式,但使用的客戶端、請求、響應等對象已經被封裝為Elasticsearch相關的類型,所以被稱為低級REST客戶端(Low Level REST Client)。使用Java低級REST客戶端訪問Elasticsearch需要在pom文件中添加如下依賴:

示例2-23 低級REST客戶端Maven依賴
Java低級REST客戶端使用RestClient對象連接Elasticsearch,在創建RestClient對象時可以指定多個節點地址以實現負載均衡。RestClient的performRequest可以執行REST請求,在使用結束后需要調用close方法釋放RestClient占用的資源。Request對象代表需要執行的REST請求,在創建時接收兩個參數:一個是請求方法;另一個是請求的地址。如果有請求體需要傳遞可使用setEntity或setJsonEntity設置,前者可使用HttpClient中的HttpEntity設置,而后者則可以直接使用字符串設置。Response對象代表REST請求執行的結果,通過調用getEntity方法可以得到響應體,類型也是HttpEntity。示例2-24展示了使用這幾個對象訪問Elasticsearch中test索引的方法:

示例2-24 低級REST客戶端調用
Elasticsearch提供的第二種解決方案建立在低級REST客戶端基礎之上,它將幾乎所有Elasticsearch訪問接口都封裝為對象和方法,在調用過程中已經沒有明顯的REST語法形式了。由于這種解決方案面向對象級別更高,所以被稱為高級REST客戶端(High Level REST Client)。高級REST客戶端連接Elasticsearch的對象是RestHighLevelClient,它基于RestClient在使用結束后也需要調用close方法釋放資源。由于高級REST客戶端中將接口請求和響應都做了封裝,所以請求和響應的種類非常多。比如,同樣是獲取索引信息接口,在高級REST客戶端中對應的請求和響應分別為GetIndexRequest和GetIndexResponse。示例2-25展示了使用高級REST客戶端訪問test索引的代碼片段:

示例2-25 高級REST客戶端調用
無論是使用哪一種方式,REST接口都是調用Elasticsearch的基礎。所以本書后續章節在介紹Elasticsearch接口時將全部以REST接口的形式講解,而有關它們在各種編程語言中的接口請讀者根據REST接口自行查找。
- 案例式C語言程序設計
- Learning Real-time Processing with Spark Streaming
- Flink SQL與DataStream入門、進階與實戰
- jQuery EasyUI網站開發實戰
- aelf區塊鏈應用架構指南
- 手把手教你學C語言
- 低代碼平臺開發實踐:基于React
- Integrating Facebook iOS SDK with Your Application
- Kubernetes源碼剖析
- Spring技術內幕:深入解析Spring架構與設計原理(第2版)
- Access 2010數據庫應用技術實驗指導與習題選解(第2版)
- Xamarin Blueprints
- 創意UI Photoshop玩轉移動UI設計
- Building Slack Bots
- Java從入門到精通(視頻實戰版)