Elasticsearch 5.0.1 java API操作

來源:互聯網
上載者:User

標籤:大量新增   來講   gre   get   生效   區別   request   bsp   ping   

 

今天來說下使用ES 5.0.1的API來進行編碼。

開始之前,簡單說下5.0.1跟之前的幾個變化。之前的ES自身是不支援delete-by-query的,也就是通過查詢來刪除,可以達到批量的效果,是因為重新整理的原因,應該夠近即時的特性相關。一直是以一個外掛程式的形式存在,到5.0.1時,倒騰了半天,還是官方文檔說,已經廢掉了這個外掛程式,放到ES Core中來了。這是一個變化,另外,初始化ES client的方式也變化了,這個要吐槽一下,從1.7到2.X,初始化方式改了一遍,從2.X到5.X又變了,讓人有點受不了啊!

 

閑話不提,開始。

 

本篇談到初始化,增,刪,改。對於查詢,我們用單獨一節來說。

 

ES的初始化:

Settings esSettings = Settings.builder()

    .put("cluster.name", clusterName) //設定ES執行個體的名稱

    .put("client.transport.sniff", true) //自動嗅探整個叢集的狀態,把叢集中其他ES節點的ip添加到本地的用戶端列表中

    .build();

   

    client = new PreBuiltTransportClient(esSettings);//初始化client較老版本發生了變化,此方法有幾個重載方法,初始化外掛程式等。

   

    //此步驟添加IP,至少一個,其實一個就夠了,因為添加了自動嗅探配置

    client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(ip), esPort));

   

對於ES Client,有兩種形式,一個是TransportClient,一個是NodeClient。兩個的區別為:

TransportClient作為一個外部存取者,通過HTTP去請求ES的叢集,對於叢集而言,它是一個外部因素。

NodeClient顧名思義,是作為ES叢集的一個節點,它是ES中的一環,其他的節點對它是感知的,不像TransportClient那樣,ES叢集對它一無所知。NodeClient通訊的效能會更好,但是因為是ES的一環,所以它出問題,也會給ES叢集帶來問題。NodeClient可以設定不作為資料節點,在elasticsearch.yml中設定,這樣就不會在此節點上分配資料。

如果用ES的節點,大家仁者見仁智者見智,各按所需。

 

現在已經通過TransportClient串連到了叢集。下一步就是建立索引,有一個常用的關係型資料庫與ES的映射關係:

關係型資料庫 -> 索引

關係型資料表 -> 類型

關係型資料項目 -> 文檔

欄位 -> 欄位

 

說到索引,簡單說下分區(shard)。ES本身是分布式的,所以分區自然而然,它的分區並非將所有的資料都放在一起,以預設的5個主分區為例,ES會將資料均衡的儲存到5個分區上,也就是這5個分區的資料並集才是整個資料集,這5個分區會按照一定規則分配到不同的ES Node上。這樣的5個分區叫主分區。然後就是從分區,預設設定是一個主分區會有一個從分區,那麼就有5個從分區,那麼預設配置會產生10個分區(5主5從)就散布在所有的Node上。主分區的個數是索引建立的時候設定的,一經設定,不可改變,因為ES判斷一條文檔存放到哪個分區就是通過這個主分區數量來控制的。簡單來講,插入的文檔號與5取餘(實際不是這樣實現的,但是也很簡單)。檢索結果的時候,也是通過這個來確認結果分布的,所以不能改。從分區的數量可以隨便改,因為塔是跟主分區關聯的。另外,Node節點也可以隨時加,而且ES還會在新節點加入之後,重新調整資料分區的分布。

 

建立索引:

client.admin().indices().prepareCreate(indexName).get();

或者

client.admin().indices().prepareCreate(indexName).setSettings(settings).get();

ES是區分大小寫,索引所有資料在進到ES之前,最好都規格化。

setSettings挺有用,比如上面說的設定分區數就是通過這裡設定的,參數可以是JSON,也有其他的重載;

這裡說下在建立索引的時候配置預設的分詞器IK

{"analysis":{"analyzer":{"ik":{"tokenizer":"ik_smart"}}}}

這是我用JSON序列化出來的,紅底的ik是我為analyzer設定的名字,通過這個名字在索引和檢索的時候,來調用ik分詞器。當然,我們打算把IK設定為預設的分詞器,可以將ik改為default,這樣就不需要在索引和檢索的時候指定了,預設的分詞器為standardAnalyzer。

 

設定好之後,建立一個Index,可以用Kibana瞧瞧結果:

 

注意,Kibana有個坑,就是用它來分詞中文,會有亂碼,這個跟ES沒關係,用Kibana的結果

 

用FireFox的外掛程式Request的結果,話說Request還是極好用的:

 

有遇到並知道為啥的給指點一下。

 

建立好了索引,接下來就是類型了,建立類型很簡單,直接插入一個文檔,如果文檔所屬的類型不存在,則會建立,如果存在,就直接插入。但是在插入文檔之前,我們可以對一些預料到的欄位或者其他屬性進行一個預定義的設定,比如,我在插入文檔之前,想讓所有的id都是long類型,並且id是要儲存並且不需要分析的。(關於欄位儲存和分析,下回再說)。可以用MappingRequest這個類幫我們達到目的。直接上代碼

XContentBuilder builder = XContentFactory.jsonBuilder()

.startObject()

.startObject(type)

.startObject("properties");

JSONObject object = mapping.getJSONObject(i);

builder.startObject(object.getString("fieldName"));

builder.field("type", object.getString("fieldType"));

builder.field("index", "not_analyzed");

builder.field("store", "yes");

builder.endObject();

builder.endObject().endObject().endObject();

PutMappingRequest mappingRequest = Requests.putMappingRequest(index).type(type).source(builder);

client.admin().indices().putMapping(mappingRequest).actionGet();

 

這樣就指定好了mapping。

 

那接下來我們添加文檔,添加文檔可以單條添加,也可以大量新增:

單條添加:

client.prepareIndex(indexName, type)

.setSource(jsonData)

.setId(jsonData.getString(KEY))//自己設定了id,也可以使用ES內建的,但是看文檔說,ES的會因為刪除id發生變動。

.execute()

.actionGet();

 

大量新增:

BulkRequestBuilder bulkRequestBuilder = client.prepareBulk();

for (int i = 0; i < docData.size(); i++){

bulkRequestBuilder.add(client.prepareIndex(indexName, type).setId(docData.getJSONObject(i).getString("id")).setSource(docData.getJSONObject(i)));

}

BulkResponse bulkResponse = bulkRequestBuilder.execute().actionGet();

bulkRequestBuilder.request().requests().clear();

if (bulkResponse.hasFailures()){

    //TODO:

}

 

刪除:

client.prepareDelete(indexName, type, docId).execute().actionGet();

 

更新

UpdateRequest updateRequest = new UpdateRequest();

updateRequest.index(indexName).type(type).id(jsonData.getString("id")).doc(jsonData);

client.update(updateRequest);

 

以上代碼都很簡單,但都有不少重載,可以先通過一個方法進去,然後研究各個重載是應對什麼情況的。

通過上面的編碼,就可以在我們的程式中實現ES的初始化,添加文檔,刪除文檔,和更新文檔。最後,再說下delete-by-query。

ES提供介面,可以直接刪除整個索引

client.admin().indices().delete(new DeleteIndexRequest(indexName)).actionGet();

上面也提到了刪除一個文檔,但是如果刪除整個type呢?es是沒有提供整個東西的。因為ES是基於Lucene的,Lucene的核心是文檔,一個索引就是一個檔案夾,裡面儲存都是文檔,所以沒有type的物理概念。ES裡面提供了這樣一個概念。是一組Field定義相同的文檔的集合。那麼我們要刪除特定的集合的文檔,比如一個type下的,怎麼做的?Lucene提供了delete by query的能力,那麼,我們就按照這個去做就是了:

 

QueryBuilder builder = QueryBuilders.typeQuery(type);//查詢整個type

DeleteByQueryAction.INSTANCE.newRequestBuilder(client).source(indexName).filter(builder).execute().actionGet();

 

好了,最後再提一點,所有的操作之後,都至少要等待1s,因為ES/Lucene是近即時,而不是准即時,索引才做之後,會有預設的重新整理時間,之後才可以將更新真正生效。一定要注意這點。

Elasticsearch 5.0.1 java API操作

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.