使用Java Rest Client操作Elasticsearch
Elasticsearch作為一個成熟的開源框架,對主流的多種客戶端語言都支援,比如Java,JavaScript ,PHP,.Net,Python,Ruby,CURL當然還有一些小眾的語言,雖然es官網沒支援,但是個人開發者也有一些開源的,具體的可在es官網clients地址檢視:
開發過程中,基本最常用的就是Java和curl的方式了,因為es本身就是使用java語言開發的,所以對Java的支援應該是最到位了,此外es也支援rest ful的DSL的訪問方式,我們可以在linux上輕鬆的使用curl命令來對es進行增刪改查,curl的操作方式大多數都是臨時的,實際開發的我們還是用程式語言來訪問的:
es支援Java API的訪問方式,支援非常全面,唯一的缺點就是依賴有點多,程式碼稍臃腫,有時候我們想簡單的開發一個非常小的功能,又不想使用java笨重的客戶端方式,應該怎麼辦?
上文說到es支援rest的訪問方式,那麼我們完全可以使用httpclient或者jsoup來直接傳送http請求不就行了嗎?其實是可以的,使用httpclient和jsoup來發送curl的命令也能操作es,獲取結果。這裡面有一個需要注意的地方。
httpclient和jsoup都不直接支援傳送DELETE方法帶引數的請求,這一點是個小缺陷,如果這個不支援,意味著一些刪除操作比如delete by query可能支援不太好。jsoup是完全不支援,而在httpclient裡面我們可以通過繼承重寫HttpEntityEnclosingRequestBase來滿足,刪除請求帶引數體,下面來看下如何使用:
繼承重寫的程式碼:
package tools;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import java.net.URI;
public class MyHttpDelete extends HttpEntityEnclosingRequestBase {
//
public static final String METHOD_NAME = "DELETE";
//
public String getMethod() {
return METHOD_NAME;
}
//
public MyHttpDelete(final String uri) {
super();
setURI(URI.create(uri));
}
//
public MyHttpDelete(final URI uri) {
super();
setURI(uri);
}
//
public MyHttpDelete() {
super();
}
}
然後使用httpclient傳送一個刪除請求:
//例項化http,刪除id=1001的一條資料
val client = HttpClients.createDefault()
val httpdelete = new MyHttpDelete("http://localhost:9200/test_index/logs/_query")
val s = new StringEntity("{ \"query\": { \"query_string\": { \"query\": id:1001 " } }} ",ContentType.APPLICATION_JSON)
httpdelete.setEntity(s)
val rs=client.execute(httpdelete)//執行刪除
//解析響應結果
val json = EntityUtils.toString(rs.getEntity(), "UTF-8")
//釋放資源
client.close()
httpclient還是比較強大的,但是上面的程式碼還是有點複雜,而且涉及連線的地方是有問題的,我們都知道es一般都是多臺機器組成叢集,而使用原生的httpclient請求建立的連結只能是某一臺機器的ip這樣一來,如果這臺機器掛掉這個客戶端程式就完全不能使用了,所以風險還是比較大的,不過也不用擔心,es官網也提供了ES Java RestClient的方式來訪問es,這個庫底層用的也是httpclient的元件,只不過es官網做了封裝,支援多機器ip,以及對請求方法做了簡化,所以想減少專案的依賴,又對支援功能要求比較健壯,我們就可以使用這個庫來開發我們的業務。
官網文件地址:
maven依賴:
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>rest</artifactId>
<version>5.5.1</version>
</dependency>
下面來看下,如何使用ES的RestClient來操作ES:
//初始化RestClient例項
static RestClient restClient = RestClient.builder(
new HttpHost("192.168.10.5", 9200, "http"),
new HttpHost("192.168.10.6", 9200, "http"),
new HttpHost("192.168.10.7", 9200, "http")).build()
// (1) 執行一個基本的方法,驗證es叢集是否搭建成功
Response response = restClient.performRequest("GET", "/", Collections.singletonMap("pretty", "true"));
System.out.println(EntityUtils.toString(response.getEntity()));
//輸出結果:
{
"name" : "nd2",
"cluster_name" : "search",
"version" : {
"number" : "2.3.4",
"build_hash" : "e455fd0c13dceca8dbbdbb1665d068ae55dabe3f",
"build_timestamp" : "2016-06-30T11:24:31Z",
"build_snapshot" : false,
"lucene_version" : "5.5.0"
},
"tagline" : "You Know, for Search"
}
// (2)驗證es的某個索引是否存在
Response response = restClient.performRequest("HEAD","/product/pdt",Collections.<String, String>emptyMap());
System.out.println(response.getStatusLine().getReasonPhrase().equals("OK"));
//輸出結果:
true
// (3) 刪除某個索引的指定條件的資料
Map<String, String> paramMap = new HashMap<String, String>();
paramMap.put("q", "id:"+id);
paramMap.put("pretty", "true");
Response response = restClient.performRequest("DELETE", + "product/pdt/_query", paramMap);
System.out.println(EntityUtils.toString(response.getEntity()));
//輸出結果:
{
"took" : 0,
"timed_out" : false,
"_indices" : {
"_all" : {
"found" : 1,
"deleted" : 0,
"missing" : 0,
"failed" : 0
}
},
"failures" : [ ]
}
總結:
ES官網提供的RestClient還支援nio實現的非同步非阻塞的方式多執行緒多送請求,通過回撥函式來處理響應的結果,當然了許可權認證,超時中斷,失敗重試,執行緒數都有對應的設定選項,感興趣的朋友可自行查閱嘗試。
通過對比我們發現官網封裝的RestClient使用起來更加簡單和健壯,比起來沒有包裝的httpclient原生的方式更加符合生產環境的標準,對於不想熟悉標準的java api的es操作方法,又想通過java來訪問es的朋友們,RestClient是一個不錯的選擇。