1. 程式人生 > >Elasticsearch 6.4基本操作 - Java版

Elasticsearch 6.4基本操作 - Java版

all efi _array 寫法 creat guide 復雜 dds ddt

1. Elasticsearch Java API有四類client連接方式

  • TransportClient
  • RestClient
  • Jest
  • Spring Data Elasticsearch

其中TransportClient和RestClient是Elasticsearch原生的api。TransportClient可以支持2.x,5.x版本,TransportClient將會在Elasticsearch 7.0棄用並在8.0中完成刪除,替而代之,我們使用Java High Level REST Client,它使用HTTP請求而不是Java序列化請求。

Jest是Java社區開發的,是Elasticsearch的Java Http Rest客戶端;Spring Data Elasticsearch是spring集成的Elasticsearch開發包。

建議:TransportClient將會在後面的版本中棄用,因此不推薦後續使用;而Jest由於是社區維護,所以更新有一定延遲,目前最新版對接ES6.3.1,近一個月只有四個issue,說明整體活躍度較低,因此也不推薦使用;Spring Data Elasticsearch主要是與Spring生態對接,可以在web系統中整合到Spring中使用。目前比較推薦使用官方的高階、低階Rest Client,官方維護,比較值得信賴。本文主要介紹RestClient,其他的只做簡單概述。

1.1 TransportClient

這裏考慮到後面版本將棄用TransportClinet,主要簡單介紹TransportClient的創建、以及一些基本增刪改查操作。

<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>transport</artifactId>
    <version>6.4.3</version>
</dependency>
<dependency>
     <groupId>org.elasticsearch</groupId>
     <artifactId>elasticsearch</artifactId>
     <version>6.4.3</version>
</dependency>
/**
 * @Author: Yang JianQiu
 * @Date: 2018/11/12 16:40
 *
 * transportClient將會在7.0版本上過時,並在8.0版本上移除掉,建議使用Java High Level REST Client
 */
public class TransportClientUtils {

    private TransportClient client = null;

    /**
     * 這裏使用餓漢單例模式創建TransportClient
     */
    public TransportClientUtils() {
        if (client == null){
            synchronized (TransportClientUtils.class){
                if (client == null){
                    client = getClient();
                }
            }
        }
    }

    public TransportClient getClient(){
        TransportClient client = null;
        try {
            Settings settings = Settings.builder()
                    .put("client.transport.sniff", true)
                    .put("cluster.name", "bigdata").build();
            client = new PreBuiltTransportClient(settings)
                    .addTransportAddress(new TransportAddress(new InetSocketAddress("192.168.187.201", 9300)));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return client;
    }

    public viod test(){
        //增,插入記錄
        IndexResponse response = client.prepareIndex("twitter", "_doc")
                .setSource(json, XContentType.JSON)
                .get();
   
        //根據Id查詢
        GetResponse response = client.prepareGet("twitter", "_doc", 1).get();

        //根據Id刪除
        DeleteResponse response = client.prepareDelete("twitter", "_doc", 1).get();

        //根據Id更新對應的字段
        UpdateRequest updateRequest1 = new UpdateRequest("twitter", "_doc", "NpEWCGcBi36MQkKOSdf3")
                .doc(jsonBuilder()
                .startObject()
                .field("user", "tom")
                .endObject()
        );
        client.update(updateRequest1).get();
 
        //另外還有批處理API、search負責查詢API、Aggregate聚合API...
    }
    
}    

具體的TransportClient的其他API應用可以參考Elasticsearch的TransportClient API doc:

https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/index.html

1.2 Rest Client

Rest Client分為Java Low REST Client和Java High Level REST Client。

maven的依賴包:

<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <version>6.4.3</version>
</dependency>
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-client</artifactId>
    <version>6.4.3</version>
</dependency>
<dependency>
    <groupId>org.elasticsearch</groupId>
    <artifactId>elasticsearch</artifactId>
    <version>6.4.3</version>
</dependency>

RestHighLevelClient與RestClient的創建:

/**
 * @author: Swordfall Yeung
 * @date:
 * @desc:
 */
public class RestClientUtils {

    /**
     * 高階Rest Client
     */
    private RestHighLevelClient client = null;
    /**
     * 低階Rest Client
     */
    private RestClient restClient = null;

    /**
     * 這裏使用餓漢單例模式創建RestHighLevelClient
     */
    public RestClientUtils() {
        if (client == null) {
            synchronized (RestHighLevelClient.class) {
                if (client == null) {
                    client = getClient();
                }
            }
        }
    }

    private RestHighLevelClient getClient() {
        RestHighLevelClient client = null;

        try {
            client = new RestHighLevelClient(
                    RestClient.builder(
                            new HttpHost("192.168.187.201", 9300, "http")
                    )
            );
        } catch (Exception e) {
            e.printStackTrace();
        }
        return client;
    }

    private RestClient getRestClient() {
        RestClient client = null;

        try {
            client = RestClient.builder(
                    new HttpHost("192.168.187.201", 9300, "http")
            ).build();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return client;
    }

    public void closeClient() {
        try {
            if (client != null) {
                client.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

   /**
    * document API 主要是些簡單的增刪改查操作
    */
    public void documentAPI() {
       //...
    }
     
   /**
    * Search API 主要是些復雜查詢操作
    */
    public void searchAPI() {
       //...
    }
}

RestHighLevelAPI分為Document APIs、Search APIs、Miscellaneous APIs、Indices APIs、Cluster APIs...等等,這裏主要介紹常用的Document APIs和Search APIs,其余的APIs可以參考:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high.html

1.2.1 Document APIs

Document APIs主要涉及些增刪改查等操作,包括Single document APIs單條操作和Multi-document APIs批量操作。Document APIs均可以設置可選參數,實現同步、異步,也均可拋出異常,這裏以Index API為例,後面的不再簡述。

技術分享圖片

Index API介紹:

    /**
     * 增,插入記錄
     * 插入操作有四種方式,分同步異步操作,可選參數設置,結果返回IndexResponse,拋出異常
     * @throws Exception
     */
    public void index() throws Exception{
        
        //第一種方式: String
        IndexRequest request = new IndexRequest("posts", "doc", "1");
        String jsonString = "{" +
                "\"user\":\"kimchy\"," +
                "\"postDate\":\"2013-01-30\"," +
                "\"message\":\"trying out Elasticsearch\"" +
                "}";
        request.source(jsonString, XContentType.JSON);

        //第二種方式: Map
        Map<String, Object> jsonMap = new HashMap<>();
        jsonMap.put("user", "kimchy");
        jsonMap.put("postDate", new Date());
        jsonMap.put("message", "trying out Elasticsearch");
        IndexRequest indexRequest = new IndexRequest("posts", "doc", "1").source(jsonMap);

        //第三種方式: XContentBuilder automatically converted to JSON
        XContentBuilder builder = XContentFactory.jsonBuilder();
        builder.startObject();
        {
            builder.field("user", "kimchy");
            builder.timeField("postDate" , new Date());
            builder.field("message", "trying out Elasticsearch");
        }
        builder.endObject();
        IndexRequest indexRequest1 = new IndexRequest("posts", "doc", "1")
                .source(builder);

        //第四種方式: source -> key-pairs
        IndexRequest indexRequest2 = new IndexRequest("posts", "doc", "1")
                .source("user", "kimchy",
                        "postDate", new Date(),
                        "message", "trying out Elasticsearch"
                );

        //可選的參數設置
        request.routing("routing");
        request.parent("parent");
        request.timeout(TimeValue.timeValueSeconds(1));
        request.timeout("1s");
        request.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL);
        request.setRefreshPolicy("wait_for");
        request.version(2);
        request.versionType(VersionType.EXTERNAL);
        request.opType(DocWriteRequest.OpType.CREATE);
        request.opType("create");
        request.setPipeline("pipeline");

        //同步執行
        IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);

        //異步執行
        ActionListener<IndexResponse> listener = new ActionListener<IndexResponse>() {
            @Override
            public void onResponse(IndexResponse indexResponse) {

            }

            @Override
            public void onFailure(Exception e) {

            }
        };
        client.indexAsync(request, RequestOptions.DEFAULT, listener);

        //Index Response
        String index = indexResponse.getIndex();
        String type = indexResponse.getType();
        String id = indexResponse.getId();
        long version = indexResponse.getVersion();

        //拋出異常
        IndexRequest request1 = new IndexRequest("posts", "doc", "1")
                .source("field", "value")
                .version(1);
        try {
            IndexResponse response = client.index(request, RequestOptions.DEFAULT);
        } catch (ElasticsearchException e) {
            if (e.status() == RestStatus.CONFLICT){

            }
        }
    }

Get API介紹

    /**
     * 根據 id 獲取數據
     * @throws Exception
     */
    public void get() throws Exception{
        GetRequest request = new GetRequest("posts", "doc", "1");

        //可選參數設置
        request.fetchSourceContext(FetchSourceContext.DO_NOT_FETCH_SOURCE);
        String[] includes = new String[]{"message", "*Date"};
        String[] excludes = Strings.EMPTY_ARRAY;
        FetchSourceContext fetchSourceContext = new FetchSourceContext(true, includes, excludes);
        request.fetchSourceContext(fetchSourceContext);

        //同步執行
        GetResponse getResponse = client.get(request, RequestOptions.DEFAULT);

        //異步執行 listener的寫法參照Index的異步執行的listener
        client.getAsync(request, RequestOptions.DEFAULT, listener);

        //Get Response 獲取信息

        //拋出異常
    }

Exists API介紹

    /**
     * 是否存在
     * @throws Exception
     */
    public void exists() throws Exception{
        GetRequest getRequest = new GetRequest("posts", "doc", "1");
        getRequest.fetchSourceContext(new FetchSourceContext(false));
        getRequest.storedFields("_none_");

        //同步執行
        boolean exists = client.exists(getRequest, RequestOptions.DEFAULT);

        //異步執行 listener的寫法參照Index的
        client.existsAsync(getRequest, RequestOptions.DEFAULT, listener);
        
        if (exists){
            System.out.println("存在");
        }else {
            System.out.println("不存在");
        }
    }

Delete API介紹

    /**
     * 根據id刪除
     * @throws Exception
     */
    public void delete() throws Exception{
        DeleteRequest request = new DeleteRequest("posts", "doc", "1");

        //同步執行
        DeleteResponse deleteResponse = client.delete(request, RequestOptions.DEFAULT);

        //異步執行 listener參照index的
        client.deleteAsync(request, RequestOptions.DEFAULT, listener);

        //Delete Response
        String index = deleteResponse.getIndex();

        // document was not found
        if (deleteResponse.getResult() == DocWriteResponse.Result.NOT_FOUND) {

        }

        //拋出異常
      
    }

Update API介紹

/**
     * 根據id更新
     * @throws Exception
     */
    public void update() throws Exception{
        UpdateRequest request = new UpdateRequest("posts", "doc", "1");
        Map<String, Object> parameters = Collections.singletonMap("count", 4);

        //第一種方式:inline script
        Script inline = new Script(ScriptType.INLINE, "painless", "ctx._source.field += params.count", parameters);
        request.script(inline);

        //第二種方式:stored script
        Script stored = new Script(ScriptType.STORED, null, "increment-field", parameters);
        request.script(stored);

        //第三種方式:partial document String
        String jsonString = "{" +
                "\"updated\":\"2017-01-01\"," +
                "\"reason\":\"daily update\"" +
                "}";
        request.doc(jsonString, XContentType.JSON);

        //第四種方式:partial document Map
        Map<String, Object> jsonMap = new HashMap<>();
        jsonMap.put("updated", new Date());
        jsonMap.put("reason", "daily update");
        request.doc(jsonMap);

        //第五種方式:partial document XContentBuilder
        XContentBuilder builder = XContentFactory.jsonBuilder();
        builder.startObject();
        {
            builder.timeField("updated", new Date());
            builder.field("reason", "daily update");
        }
        builder.endObject();
        request.doc(builder);

        //第六種方式:partial document Object key-pairs
        request.doc("updated", new Date(),
                   "reason", "daily update");

        //upserts
        String jsonString1 = "{\"created\":\"2017-01-01\"}";
        request.upsert(jsonString1, XContentType.JSON);

        //同步執行
        UpdateResponse updateResponse = client.update(request, RequestOptions.DEFAULT);

        //異步執行, listener創建參考index的
        client.updateAsync(request, RequestOptions.DEFAULT, listener);

        //update Response
        GetResult result = updateResponse.getGetResult();
        if (result.isExists()) {
            String sourceAsString = result.sourceAsString();
            Map<String, Object> sourceAsMap = result.sourceAsMap();
            byte[] sourceAsBytes = result.source();
        } else {

        }

        //拋出異常
        
    }

Bulk API介紹

    /**
     * 批量處理
     * @throws Exception
     */
    public void bulk() throws Exception{
        BulkRequest request = new BulkRequest();

        //Other
        request.add(new DeleteRequest("posts", "doc", "3"));
        request.add(new UpdateRequest("posts", "doc", "2")
                .doc(XContentType.JSON, "other", "test"));
        request.add(new IndexRequest("posts", "doc", "4")
                .source(XContentType.JSON, "field", "baz"));

        //同步執行
        BulkResponse bulkResponses = client.bulk(request, RequestOptions.DEFAULT);

        //異步執行
        ActionListener<BulkResponse> listener = new ActionListener<BulkResponse>() {
            @Override
            public void onResponse(BulkResponse bulkResponse) {

            }

            @Override
            public void onFailure(Exception e) {

            }
        };
        client.bulkAsync(request, RequestOptions.DEFAULT, listener);

        //Bulk Response 批處理結果
        for (BulkItemResponse bulkItemResponse: bulkResponses){
            DocWriteResponse itemResponse = bulkItemResponse.getResponse();

            if (bulkItemResponse.getOpType() == DocWriteRequest.OpType.INDEX
                    || bulkItemResponse.getOpType() == DocWriteRequest.OpType.CREATE) {
                IndexResponse indexResponse = (IndexResponse) itemResponse;

            } else if (bulkItemResponse.getOpType() == DocWriteRequest.OpType.UPDATE) {
                UpdateResponse updateResponse = (UpdateResponse) itemResponse;

            } else if (bulkItemResponse.getOpType() == DocWriteRequest.OpType.DELETE) {
                DeleteResponse deleteResponse = (DeleteResponse) itemResponse;
            }
        }

        for (BulkItemResponse bulkItemResponse : bulkResponses) {
            if (bulkItemResponse.isFailed()) {
                BulkItemResponse.Failure failure = bulkItemResponse.getFailure();

            }
        }

        //Bulk Processor 自定義批處理器
        BulkProcessor.Listener listener1 = new BulkProcessor.Listener() {
            @Override
            public void beforeBulk(long l, BulkRequest bulkRequest) {

            }

            @Override
            public void afterBulk(long l, BulkRequest bulkRequest, BulkResponse bulkResponse) {

            }

            @Override
            public void afterBulk(long l, BulkRequest bulkRequest, Throwable throwable) {

            }
        };

        BiConsumer<BulkRequest, ActionListener<BulkResponse>> bulkConsumer =
                (request1, bulkListener) -> client.bulkAsync(request1, RequestOptions.DEFAULT, bulkListener);
        BulkProcessor bulkProcessor = BulkProcessor.builder(bulkConsumer, listener1).build();

        BiConsumer<BulkRequest, ActionListener<BulkResponse>> bulkConsumer1 =
                (request2, bulkListener) -> client.bulkAsync(request2, RequestOptions.DEFAULT, bulkListener);
        BulkProcessor.Builder builder = BulkProcessor.builder(bulkConsumer1, listener1);
        builder.setBulkActions(500);
        builder.setBulkSize(new ByteSizeValue(1L, ByteSizeUnit.MB));
        builder.setConcurrentRequests(0);
        builder.setFlushInterval(TimeValue.timeValueSeconds(10L));
        builder.setBackoffPolicy(BackoffPolicy
                .constantBackoff(TimeValue.timeValueSeconds(1L), 3));

        //Once the BulkProcessor is created requests can be added to it:
        IndexRequest one = new IndexRequest("posts", "doc", "1").
                source(XContentType.JSON, "title",
                        "In which order are my Elasticsearch queries executed?");
        IndexRequest two = new IndexRequest("posts", "doc", "2")
                .source(XContentType.JSON, "title",
                        "Current status and upcoming changes in Elasticsearch");
        IndexRequest three = new IndexRequest("posts", "doc", "3")
                .source(XContentType.JSON, "title",
                        "The Future of Federated Search in Elasticsearch");
        bulkProcessor.add(one);
        bulkProcessor.add(two);
        bulkProcessor.add(three);

        boolean terminated = bulkProcessor.awaitClose(30L, TimeUnit.SECONDS);
    }

Multi-Get API介紹

/**
     * 根據id批量獲取數據
     * @throws Exception
     */
    public void multiGet() throws Exception{
        MultiGetRequest request = new MultiGetRequest();
        request.add(new MultiGetRequest.Item("index","type","example_id"));
        request.add(new MultiGetRequest.Item("index", "type", "another_id"));

        //optional arguments
        request.add(new MultiGetRequest.Item("index", "type", "example_id") .fetchSourceContext(FetchSourceContext.DO_NOT_FETCH_SOURCE));

        //同步執行
        MultiGetResponse responses = client.mget(request, RequestOptions.DEFAULT);

        //異步執行 listener參考Index的
        client.mgetAsync(request, RequestOptions.DEFAULT, listener);

        //Multi Get Response
        MultiGetItemResponse firstItem = response.getResponses()[0];
        GetResponse firstGet = firstItem.getResponse();
        if (firstGet.isExists()) {

        }
    }

1.2.2 Search APIs

 public void search() throws Exception{
        //match all query 查詢所有數據
        SearchRequest searchRequest = new SearchRequest();
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        searchRequest.source(searchSourceBuilder);

        //使用SearchSourceBuilder查詢指定字段 
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.termQuery("user", "kimchy"));
        sourceBuilder.from(0);
        sourceBuilder.size(5);
        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        SearchRequest searchRequest2 = new SearchRequest();
        //index 數據庫
        searchRequest2.indices("posts");
        searchRequest2.source(sourceBuilder);

        //Building queries
        //One way, QueryBuilder can be created using its constructor 使用QueryBuilder的構造函數
        MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("user", "kimchy");
        matchQueryBuilder.fuzziness(Fuzziness.AUTO);
        matchQueryBuilder.prefixLength(3);
        matchQueryBuilder.maxExpansions(10);
        //Two way, QueryBuilder objects can also be created using the QueryBuilders utility class. 直接使用matchQuery
        QueryBuilder matchQueryBuilder1 = matchQuery("user", "kimchy")
                                                       .fuzziness(Fuzziness.AUTO)
                                                       .prefixLength(3)
                                                       .maxExpansions(10);

        searchSourceBuilder.query(matchQueryBuilder1);

        //Specifying Sorting 指定排序
        sourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC));
        sourceBuilder.sort(new FieldSortBuilder("_uid").order(SortOrder.ASC));

        //Source filtering, turn off _source retrieval completely
        sourceBuilder.fetchSource(false);
        //an array of one or more wildcard patterns to control which fields get included or excluded in a more fine grained way
        String[] includeFields = new String[] {"title", "user", "innerObject.*"};
        String[] excludeFields = new String[] {"_type"};
        sourceBuilder.fetchSource(includeFields, excludeFields);

        //Requesting Aggregations
        SearchSourceBuilder searchSourceBuilder2 = new SearchSourceBuilder();
        TermsAggregationBuilder aggregation = AggregationBuilders.terms("by_company")
                .field("company.keyword");
        aggregation.subAggregation(AggregationBuilders.avg("average_age")
                .field("age"));
        searchSourceBuilder2.aggregation(aggregation);

        //Requesting Suggestions
        SearchSourceBuilder searchSourceBuilder3 = new SearchSourceBuilder();
        SuggestionBuilder termSuggestionBuilder = SuggestBuilders.termSuggestion("user").text("kmichy");
        SuggestBuilder suggestBuilder = new SuggestBuilder();
        suggestBuilder.addSuggestion("suggest_user", termSuggestionBuilder);
        searchSourceBuilder3.suggest(suggestBuilder);

        //同步執行
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

        //異步執行 listener參考index的
        client.searchAsync(searchRequest, RequestOptions.DEFAULT, listener);

        //SearchResponse
        RestStatus status = searchResponse.status();
        for (ShardSearchFailure failure : searchResponse.getShardFailures()) {
            // failures should be handled here
        }

        //Retrieving SearchHits 獲取結果數據
        SearchHits hits = searchResponse.getHits();
        long totalHits = hits.getTotalHits();
        float maxScore = hits.getMaxScore();
        SearchHit[] searchHits = hits.getHits();
        for (SearchHit hit : searchHits) {
            // do something with the SearchHit
            String index = hit.getIndex();
            String type = hit.getType();
            String id = hit.getId();
            float score = hit.getScore();

            String sourceAsString = hit.getSourceAsString();
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            String documentTitle = (String) sourceAsMap.get("title");
            List<Object> users = (List<Object>) sourceAsMap.get("user");
            Map<String, Object> innerObject =
                    (Map<String, Object>) sourceAsMap.get("innerObject");
        }

        //Retrieving Aggregations
        Aggregations aggregations = searchResponse.getAggregations();
        Terms byCompanyAggregation = aggregations.get("by_company");
        Terms.Bucket elasticBucket = byCompanyAggregation.getBucketByKey("Elastic");
        Avg averageAge = elasticBucket.getAggregations().get("average_age");
        double avg = averageAge.getValue();

        Range range = aggregations.get("by_company");
        Map<String, Aggregation> aggregationMap = aggregations.getAsMap();
        Terms companyAggregation = (Terms) aggregationMap.get("by_company");

        List<Aggregation> aggregationList = aggregations.asList();
        for (Aggregation agg : aggregations) {
            String type = agg.getType();
            if (type.equals(TermsAggregationBuilder.NAME)) {
                Terms.Bucket elasticBucket1 = ((Terms) agg).getBucketByKey("Elastic");
                long numberOfDocs = elasticBucket1.getDocCount();
            }
        }

        //Retrieving Suggestions
        Suggest suggest = searchResponse.getSuggest();
        TermSuggestion termSuggestion = suggest.getSuggestion("suggest_user");
        for (TermSuggestion.Entry entry : termSuggestion.getEntries()) {
            for (TermSuggestion.Entry.Option option : entry) {
                String suggestText = option.getText().string();
            }
        }
    }

Multi-search APIs介紹:

public void multiSearch() throws Exception{
        MultiSearchRequest request = new MultiSearchRequest();
        SearchRequest firstSearchRequest = new SearchRequest();
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchQuery("user", "kimchy"));
        firstSearchRequest.source(searchSourceBuilder);
        request.add(firstSearchRequest);

        SearchRequest secondSearchRequest = new SearchRequest();
        searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchQuery("user", "luca"));
        secondSearchRequest.source(searchSourceBuilder);
        request.add(secondSearchRequest);

        //同步執行
        MultiSearchResponse response = client.msearch(request, RequestOptions.DEFAULT);

        //同步執行 listener參考index的
        client.msearchAsync(request, RequestOptions.DEFAULT, listener);

        //MultiSearchResponse
        MultiSearchResponse.Item firstResponse = response.getResponses()[0];
        SearchResponse searchResponse = firstResponse.getResponse();
        MultiSearchResponse.Item secondResponse = response.getResponses()[1];
        searchResponse = secondResponse.getResponse();
    }

SearchTemplate APIs介紹:

/**
     * 查詢模板
     * @throws Exception
     */
    public void searchTemplate() throws Exception{
        
        SearchTemplateRequest request = new SearchTemplateRequest();
        request.setRequest(new SearchRequest("posts"));
        //Inline Templates
        request.setScriptType(ScriptType.INLINE);
        //instead of providing an inline script
        request.setScriptType(ScriptType.STORED);
        request.setScript(
                "{" +
                 "  \"query\": { \"match\": { \"{{ field }}\": \"{{ value }}\" } }," +
                 "  \"size\": \"{{ size }}\"" +
                 "}");
        Map<String, Object> scriptParams = new HashMap<>();
        scriptParams.put("field", "title");
        scriptParams.put("value", "elasticsearch");
        scriptParams.put("size", 5);
        request.setScriptParams(scriptParams);

        //同步執行
        SearchTemplateResponse response = client.searchTemplate(request, RequestOptions.DEFAULT);

        //異步執行 listener參考Index的
        client.searchTemplateAsync(request, RequestOptions.DEFAULT, listener);

        //SearchTemplate Response
        SearchResponse searchResponse = response.getResponse();
        BytesReference source = response.getSource();
    }

Multi-SearchTemplate APIs介紹:

/**
     * 多個查詢模板執行
     * @throws Exception
     */
    public void MultiSearchTemplate() throws Exception{
        String[] searchTerms = {"elasticsearch", "logstash", "kibana"};
        MultiSearchTemplateRequest multiRequest = new MultiSearchTemplateRequest();
        for (String searchTerm: searchTerms) {
            SearchTemplateRequest request = new SearchTemplateRequest();
            request.setRequest(new SearchRequest("posts"));

            request.setScriptType(ScriptType.INLINE);
            request.setScript(
                    "{" +
                            " \"query\": { \"match\": { \"{{field}}\": \"{{value}}\" }}," +
                            " \"size\": \"{{size}}\"" +
                            "}"
            );

            Map<String, Object> scriptParams = new HashMap<>();
            scriptParams.put("field", "title");
            scriptParams.put("value", searchTerm);
            scriptParams.put("size", 5);
            request.setScriptParams(scriptParams);

            multiRequest.add(request);
        }
        
        //同步執行
        MultiSearchTemplateResponse multiResponse = client.msearchTemplate(multiRequest, RequestOptions.DEFAULT);

        //異步執行
        ActionListener<MultiSearchTemplateResponse> listener = new ActionListener<MultiSearchTemplateResponse>() {
            @Override
            public void onResponse(MultiSearchTemplateResponse response) {

            }

            @Override
            public void onFailure(Exception e) {

            }
        };
        client.msearchTemplateAsync(multiRequest, RequestOptions.DEFAULT, listener);

        //MultiSearchTemplateResponse
        for (MultiSearchTemplateResponse.Item item : multiResponse.getResponses()) {
            if (item.isFailure()) {
                String error = item.getFailureMessage();
            } else {
                SearchTemplateResponse searchTemplateResponse = item.getResponse();
                SearchResponse searchResponse = searchTemplateResponse.getResponse();
                searchResponse.getHits();
            }
        }
    }

其余APIs可以參考:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high.html

1.3 Jest

Jest是第三方工具,是ElasticSearch的Java HTTP Rest客戶端。Jest填補了ElasticSearch缺少Http Rest接口客戶端的空白。

Jest的API為:

技術分享圖片

Jest的具體用法參考:https://blog.csdn.net/u010466329/article/details/75020956/

Jest的代碼github地址:https://github.com/searchbox-io/Jest

1.4 Spring Data Elasticsearch

可參考https://blog.csdn.net/qq_33314107/article/details/80725994

2. 常見報錯

NoNodeAvailableException報錯,主要是外網IP沒有配置

在elasticSearch.yml上配置transport.host和transport.tcp.port即可

transport.host: localhost
transport.tcp.port: 9300

localhost可以是具體的IP地址

個人編寫的TransportClient和RestClient的github Demo:

https://github.com/qiushangwenyue/ElasticSearchDemo.git

參考資料:

https://www.elastic.co/guide/en/elasticsearch/client/index.html

https://www.elastic.co/guide/en/elasticsearch/client/java-rest/6.4/java-rest-overview.html

https://blog.csdn.net/qq_33314107/article/details/80725913

Elasticsearch 6.4基本操作 - Java版