標籤:option 忽略 port 類方法 listener 連接埠 sync import 擷取
本章內容
使用用戶端對象(client object)串連到本地或遠程Elasticsearch叢集。
逐條或批量索引文檔。
更新文檔內容。
使用各種Elasticsearch支援的查詢方式。
處理Elasticsearch返回的錯誤資訊。
通過發送各種管理指令來收集叢集狀態資訊或執行管理工作。
8.3 串連到叢集8.3.1 成為Elasticsearch節點
第一種串連到Elasticsearch節點的方式是把應用程式當成Elasticsearch叢集中的一個節點。
Node node=nodeBuilder().clusterName("escluster2").client (true).node();Client client=node.client();
8.3.2 使用傳輸機串連方式
Settings settings = ImmutableSettings.settingsBuilder().put("cluster.name","escluster2").build();TransportClient client=new TransportClient(settings);client.addTransportAddress(new InetSocketTransportAddress("127.0.0.1",9300));
注意這裡的連接埠號碼不是9200,而是9300。 9200連接埠用來讓HTTP REST API訪問Elasticsearch,而9300連接埠是傳輸層監聽的預設連接埠。
我們再回過頭來看TransportClient類的可用配置:
- client.transport.sniff(預設值:false):如果設為true , Elasticsearch會讀取叢集中的 節點資訊。因此你不需要在建立TransportClient對象時提供所有節點的網路地址。 Elasticsearch很智能,它會自動檢測到活躍節點並把它們加人到列表中。
- client.transport.ignore_cluster_name(預設值:false ):如果設為true,則Elasticsearch會忽視配置中的叢集名稱並嘗試串連到某個可串連叢集上,而不管叢集名稱是否匹配。這一點很危險,你可能會首先串連到你不想要的叢集上。
- client.transport.ping_timeout(預設值:5s):該參數指定了ping命令響應的逾時時間。 如果用戶端和叢集間的網路延遲較大或串連不穩定,可能需要調大這個取值。
- client.transport.nodes_sampler_interval預設值:5s):該參數指定了檢查節點可用 性的時間間隔。與前一個參數類似,如果網路延遲較大或者網路不穩定,可能需要調大這個值。
8.3.3 選擇合適的串連方式
第一種方式讓 啟動順序複雜化了,即用戶端節點必須加人叢集並建立與其他節點的串連,而這需要時間和資源。然而,操作卻可以更快地執行,因為所有關於叢集、索引、分區的資訊都對用戶端節點可見。
另一方面,使用TransportClient對象啟動速度更快,需要的資源更少,如更少的socket串連。然而,發送查詢和資料卻需要消耗更多的資源,TransportClient對象對 叢集和索引拓撲結構的資訊一無所知,所以它無法把資料直接發送到正確的節點,而是先把資料發給某個初始傳輸節點,然後再由Elasticsearch來完成剩下的轉寄工作。此外,TransportClient對象還需要你提供一份待串連節點的網路地址清單。
在選擇合適的串連方式時請記住,第一種方式並不總是可行的。例如,當要串連的Elasticsearch叢集處於另一個區域網路中,唯一可選的方式就是使用TransportClient對象。
8.4 API部析
GetResponse response=client.prepareGet(”library","book",”1").setFields("title",”_source").execute().actionGet();
在完成準備工作之後,我們用構造器對象建立一個請求 (利用request()方法)以備隨後使用,或者直接通過execute()調用送出查詢請求,這裡我們選擇後者。
ELasticSearch的API是天生非同步。這意味著execute()調用 不會等待Elasticsearch的響應結果,而是直接把控制權交回給調用它的程式碼片段,而查詢請求在後台執行。本例中我們使用actionGet()方法,這個方法會等待查詢執行完畢並返回資料。這樣做比較簡單,但在更複雜的系統中這顯然不夠。接下來是一個使用非同步API的例子。首先引人相關聲明:
ListenableActionFuture<GetResponse> future=client.prepareGet("library","book","1").setFields("title",”_source").execute();future.addListener( new ActionListener<GetResponse>(){ @Override public void onResponse(GetResponse response){ System.out.println("Document:"+response.getIndex() +”/“ +response .getType() +”/" +response.getId()); } @Override public void onFailure(Throwable e){ throw new RuntimeException(e); }});
8.5 CRUD操作8.5.1 讀取文檔
GetResponse response=client.prepareGet("library","book","1").setFields("title","_source").execute().actionGet();
setFields(String):setIndex(String) , setType(String) , setId(String):setRouting(String):setParent(String):setPreference(String): 【_local, _primary】setRefresh(Boolean): 【false】setRealtime(Boolean):【true】
isExists():getindex():getType():getId():getVersion():isSourceEmpty():getSourceXXX():【getSourceAsString(),getSourceAsMap(),getSourceAsBytes()】getField(String):
8.5.2 索引文檔
IndexResponae response=client.prepareIndex("library","book","2") .setSource("{\"title\":\"Mastering Elasticsearch\"}") .execute().actionGet();
setSource():setlndex(String), setType(String), setId(String):setRouting(String) , setParent(String):setOpType():【index,create】setRefresh(Boolean):【false】setReplicationType():【sync,async,default】setConsistencyLevel():【DEFAULT,ONE,QUORUM,ALL】多少副本活躍才進行該操作setVersion(long):多虧了這個方法。程式可以確保在讀取和更新文檔期間沒有別人更改這個文檔。setVersionType(VersionType):setPercolate(String):setTimestamp(String):setTTL(long):超過這個時間長度後文檔會被自動刪除getlndex():返回請求的索引名稱getType():返迴文檔類型名稱getId():返回被索引文檔的IDgetVersion():返回被索引文檔的版本號碼getMatches():返回匹配被索引文檔的過濾器查詢列表,如果沒有匹配的查詢,則返回null
8.5.3 更新文檔
Map<String, Object>params=Maps.newHashMap();params.put("ntitle","Elasticsearch Server Book");UpdateResponse response = client.prepareUpdate("library","book","2") .setScript("ctx._source.title=ntitle") .setScriptParams(params) .execute().actionGet();
setIndex(String) , setType(String) , setId(String):setRouting(String), setParent(String):setScript(String):setScriptLang(String):setScriptParams(Map<String, Object>):addScriptParam(String, Object):setFields(String...):setRetryOnConflict(int):預設值為0。在Elasticsearch中,更新一個文檔意味著先檢索出文檔的舊版本,修改它的結構,從索引中刪除舊版本然後重新索引新版本。這意味著,在檢索出舊版本和寫人新版本之間,目的文件可能被其他程式修改。Elasticsearch通過比較文檔版本號碼來檢測修改,如果發現修改則返回錯誤。除了直接返回錯誤,還可以選擇重試本操作。而這個重試次數就可以由本方法指定。setRefresh(Boolean):【false】setRepliactionType():【sync, async, default】。本方法用於控制在更新過程中的複製類型。預設情況下,只有所有副本執行更新後才認為更新操作是成功的,對應這裡的取值為sync或等價枚舉值。另一種選擇是不等待副本上的操作完成就直接返回,對應取值為async或等價枚舉值。還有一種選擇是讓Elasticsearch根據節點配置來決定如何操作,對應取值為default或等價枚舉值。setConsistencyLevel():【DEFAULT,ONE,QUORUM,ALL】本方法設定有多少個活躍副本時才能夠執行更新操作。setPercolate(String):這個方法將導致索引文檔要經過percolator的檢查,其參數是 一個用來限制percolator查詢的查詢串。取值為`*`表示所有查詢都要檢查。setDoc():這類方法用來設定文檔片段,而這些文檔片段將合并到索引中相同ID的 文檔上。如果通過setScript()方法設定了script,則文檔將被忽略。Elasticsearch提供了本方法的多種版本,分別需要輸入字串、位元組數組、XContentBuilder, Map 等多種類型表示的文檔。setSource():setDocsAsUpsert(Boolean):預設值為false。設定為true後,如果指定文檔在索引中不存在,則setDoc()方法使用的文檔將作為新文檔加人到索引中。
- 更新要求返回的響應為一個UpdateResponse對象方法:
getIndex():getType():getld():getVersion():getMatches():getGetResult():
8.5.4 刪除文檔
DeleteResponse response=client.prepareDelete("library","book","2") .execute().actionGet();
setIndex(String), setType(String), setId(String):setRouting(String), setParent(String):setRefresh(Boolean):setVersion(long):本方法指定索引時被刪除文檔的版本號碼。如果指定ID的文檔不 存在,或者版本號碼不匹配,則刪除操作會失敗。這個方法確保了程式中沒有別人更改這個文檔。 setVersionType(VersionType):本方法告知Elasticsearch使用哪個版本類型。setRepliactionType():【sync, async和default】setConsistencyLevel():本方法設定有多少個活躍副本時才能夠執行更新操作。【DEFAULT,ONE,QUORUM,ALL】
- 刪除操作的響應DeleteResponse類提供了如下方法:
getIndex():返回請求的索引名稱。getType():返迴文檔類別名稱。getId():返回被索引文檔的ID。getVersion():返回被索引文檔的版本號碼。isNotFound():如果請求未找到待刪除文檔,則返回true
8.6 Elasticsearch查詢8.6.1 準備查詢請求
SearchResponse response=client.prepareSearch("library" .addFields(‘title","_source") .execute().actionGet();for(SearchHit hit:response.getHits().getHits()){ System.out.println(hit.getId()); if (hit.getFields().containsKey("title"}){ System.out.println("field.title: " +hit.getFields().get("title").getValue()) } System.out.println("source.title: " +hit.getSource().get("title")); }
8.6.2 構造查詢
QueryBuilder queryBuilder=QueryBuilders .disMaxQuery() .add(QueryBuilders.termQuery("title","Elastic")) .add(QueryBuilders.prefixQuery("title","el"));System.out.println(queryBuilder.toString());SearchResponse response=client.prepareSearch("library") .setQuery(queryBuilder) .execute().actionGet();
匹配查詢
queryBuilder=QueryBuilders .matchQuery("message","a quick brown fox") .operator(Operator.AND) .zeroTermsQuery(ZeroTermsQuery.ALL);
使用地理位置查詢
queryBuilder = QueryBuilders.geoShapeQuery("location", ShapeBuilder.newRectangle() .topLeft(13, 53) .bottomRight(14, 52) .build());
8.6.3 分頁
SearchResponse response=client.prepareSearch("library") .setQuery(QueryBuilders.matchAllQuery()) .setFrom(10) .setSize(20) .execute().actionGet();
8.6.4 排序
SearchResponse response=client.prepareSearch("library") .setQuery(QueryBuilders.matchAllQuery()) .addSort(SortBuilders.fieldSort("title")) .addsort("_score",SortOrder .DESC) .execute().actionGet();
除了上述排序方法外,ElasticSearcb還提供了一種基於指令碼的排序方法:scriptSort(String, String)
,以及一種基於空間距離排序的方法:geoDistanceSort(String).
8.6.5 過濾
FilterBuilder filterBuilder=FilterBuilders .andFilter( FilterBuilders .existsFilter("title").filterName("exist”), FilterBuilders.termFilter("title","elastic") );SearchResponse response=client.prepareSearch("library") .setFilter(filterBuilder) .execute().actionGet();
8.6.6 切面計算
FacetSBuilder facetBuilder=FacetBuilders .filterFacet("test") .filter(FilterBuilders .termFilter("title","elastic"));SearchResponse response=client.prepareSearch("library") .addFacet(facetBuilder) .execute()actionGet();
8.6.7 高亮
SearchResponse response=client.preparesearch("wikipedia") .addHighlightedField("title") .setQuery(QueryBuilders.termQuery("title","actress")) .setHighlighterPreTags("<1>", "<2>") .setHighlighterPostTags("</1>"," </2>").execute().actionGet();
for(SearchHit hit:response.getHits().getHits()){ HighlightField hField = hit.getHighlightFields()get("title"); for (Text t:hField.fragments()){ System.out.println(t.string()); }}
8.6.8 查詢建議
SearchResponse response=client.prepareSearch("wikipedia") .setQuery(QueryBuilders.matchAllQuery()) .addSuggestion(new TermSuggestionBuilder("first_suggestion") .text("graphics designer") .field("_all") ) .execute().actionGet()
for(Entry<? extends Option> entry: response.getSuggest() .getSuggestion("first_suggestion").getEntries()){ System.out.println("Check for: " +entry.getText() +". Options:"); for(Option option: entry.getOptions()){ System.out.println("\t"+option.getText()); }
8.6.9 計數
有時 候,我們不在乎具體會返回哪些文檔,而只想知道匹配的結果數量。在這種情況下,我們需要使用計數請求,因為它的效能更好:不需要做排序,也不需要從索引中取出文檔。
CountResponse response=client.prepareCount("library") .setQuery(QueryBuilders.termQuery("title","elastic")) .execute().actionGet();
8.6.10 滾動
要使用Elasticsearch Java API的滾動功能擷取大量文檔集合:
SearchResponse responseSearch=client.prepareSearch("library" ) .setScroll("1m") .setSearchType(SearchType.SCAN) .execute().actionGet();String scrolled=responseSearch.getScrollId();SearchResponse response = client.prepareSearchScroll(scrollld) .execute().actionGet(),
其中有兩個請求:第一個請求指定了查詢條件以及滾動屬性,如滾動的有效時間長度(使用 setScroll()方法);第二個請求指定了查詢類型,如這裡我們切換到掃描模式(scan mode)。掃描模式下會忽略排序而僅執行取出文檔操作。
8.7 批量執行多個操作8.7.1 大量操作
BulkResponse response=client.prepareBulk() .add(client.prepareIndex("library", "book","5") .setSource("{\"title\":\"Solr Cookbook\"}" .request() .add(client.prepareDelete("library", "book", "2").request()).execute().actionGet();
該請求向Iibrary索引的boo(類型中添加了一個文檔(ID為5),又從這個索引中刪除了一 個文檔(ID為2)。得到響應後,通過getItems()方法可得到一個由org.elasticsearch.action.bulk.BulkItemResponse對象組成的數組。
8.7.2 根據查詢刪除文檔
DeleteByQueryResponse response=client.prepareDeleteByQuery("library") .setQuery(QueryBuilders.termQuery("title","Elasticsearch")) .execute().actionGet();
8.7.3 Multi GET
MultiGetResponse response = client.prepareMultiGet() .add("library", "book", "1","2") .execute().actionGet();
這個請求的響應對象包含一個getResponses()方法,而該方法返回了一個由org. elasticsearch.action.get.MultiGetItemResponse對象構成的數組。
8.7.4 Multi Search
MultiSearchResponse response=client.prepareMultiSearch() .add(client.prepareSearch("library","book").request()) .add(client.prepareSearch("news"). .setFilter(FilterBuilders.termFilter("tags", "important"))) .execute().actionGet();
本操作包含一個getResponses()方法。該方法返回了一個由 elasticsearch.action.search.MultiSearchResponse.Item對象組成的數組。
8.8 Percolator
percolator是查詢的逆過程。我們可以根據某個文檔來找出與之匹配的所有查詢。假 定有一個prc ltr的索引,我們可以使用如下代碼向_percolator索引的prcltr類型索引一個查詢:
client.prepareIndex(”_percolator","prcltr","query:1") .setSource(XContentFactory.jsonBuilder() .startObject() .field("query", QueryBuilders .termQuery("test","abc")) .endObject()) .execute().actionGet();
本例中我們定義了一個ID為“query: 1”的查詢,用來檢查test欄位中是否包含abc這個 值。既然percolator已經準備好了,那麼可以使用如下程式碼片段來向它發送一個文檔:
PercolateResponse response =client.preparePercolate("prcltr","type") .setSource(XContentFactory.jsonBuilder() .startObject() .startObject("doc") .field("test").value("abc") .endObject() .endObject()) .execute().actionGet();
我們發送的這個文檔應該是與percolator中儲存的那個查詢匹配,這一點可以通過 getMatches()方法來檢驗。具體可以使用如下代碼:
for (String match:response.getMatches()){ System.out.println("Match:"+match);}
8.9 explain API
最後一個關於查詢Elasticsearch的API是explain API。explain API可以協助檢查關於 相關度的問題,並指出文檔匹配與否的依據。請看下面的代碼:
ExplainResponse response=client .prepareExplain(“library","book","1") .setQuery(QueryBuilders.termQuery("title","elastic")) .execute().actionGet();
8.11 管理API
Elasticsearch把管理操作劃分為 兩類:叢集管理和索引管理。我們先看第一類。
8.11.1 叢集管理API
ClusterAdminClient cluster=client.admin().cluster()
叢集和索引健康狀態API
ClusterHealthResponse response=client.admin().cluster() .prepareHealth("library") .execute().actionGet();
在響應中,可以讀取到叢集狀態、已指派分區數、總分區數、特定 索引的副本數等資訊。
叢集狀態API
叢集狀態API可以讓我們擷取叢集相關資訊,如路由、分區分配情況以及映射等。
ClusterStateResponse response=client.admin().cluster() .prepareState() .execute().actionGet();
設定更新API
設定更新API可以設定叢集範圍的配置參數。
Map<String, Object> map=Maps.newHashMap()map.put("indices.ttl.interval","10m");ClusterUpdateSettingsResponse response=client.admin().cluster() .prepareUpdateSettings() .setTransientSettings(map) .execute().actionGet();
重新路由API
重新路由API可以在節點間移動分區,以及取消或強制進行分區分配行為。
ClusterRerouteResponse response=client .admin().cluster() .prepareReroute() .setDryRun(true) .add( new MoveAllocationCommand(new ShardId("library",3), "G3czOt4HQbKZT1RhpPCULw", PvHtEMuRSJ6rLJ27AW3U6w"), new CancelAllocationCommand(new ShardId("‘library", 2), "G3czOt4HQbKZT1RhpPCULw", true)) .execute().actionGet();
節點資訊API
節點資訊(nodes information) API提供了一個或多個特定節點的資訊。該API輸出的資訊涵蓋Java虛擬機器、
作業系統以及網路(如IP地址或區域網路地址以及外掛程式資訊等)。
NodesInfoResponse response = client.admin().cluster() .prepareNodesInfo() .setNetwork(true) .setPlugin(true) .execute().actionGet();
節點統計API
節點統計(node statistics ) API和節點資訊API很相似,只是它輸出的是有關 Elasticsearch使用方式的資訊,如索引統計、檔案系統、HTTP模組、Java虛擬機器等。
NodesStatsResponse response=client.admin().cluster() .prepareNodesStats() .all() .execute().actionGet();
節點熱點線程API
節點熱點線程API用於在Elasticsearch出故障或CPU使用率超過正常值時檢查節點狀 態。
NodesHotThreadsResponse response=client.admin().cluster() .prepareNodesHotThreads() .execute().actionGet();
節點關閉API
節點關閉(node shutdown ) APl比較簡單,它允許我們關閉指定節點(或所有節點)。 如果需要,還可以設定關閉延遲時間。例如,下面代碼將立即關閉整個叢集:
NodeaShutdownResponse response=client.admin().cluster() .prepareNodesShutdown() .execute().actionGet();
查詢分區API
查詢分區(searchshard ) API也比較簡單,它允許我們檢查哪些節點將用於處理查詢。 它還可以設定路由參數,因此在使用自訂路由時特別方便。
ClusterSearchShardsResponse response=client.admin().cluster() .prepareSearchShards() .setIndices("library") .setRouting("12") .execute().actionGet();
8.11.2 索引管理API
IndicesAdminClient cluster = client.admin().indices();
索引存在API
類型存在API
索引統計API
索引統計(indicesstats ) API可以提供關於索引、文檔、儲存以及操作的資訊,如擷取、 查詢、索引、預熱器、合并過程、清空緩衝區、重新整理等。
索引狀態
索引段資訊API
建立索引API
刪除索引API
關閉索引API
開啟索引API
重新整理API
清空緩衝區API
索引最佳化API
設定映射API
刪除映射API
別名API
擷取別名API
別名存在API
清空緩衝API
更新設定API
分析API
設定模板API
刪除模板API
查詢驗證API
設定預熱器API
刪除預熱器API
第08章 Elasticsearch Java API