Elasticsearch 6.0 Java APIの使用方法

Elasticsearch 6.0におけるJava APIの活用

1:Java APIを使用したElasticsearchクライアントの作成

package com.example.elasticsearch.client;

import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.transport.client.PreBuiltTransportClient;

import java.net.InetAddress;

public class EsConnectionManager {
    private static TransportClient esClient;
    
    public TransportClient getEsConnection() {
        try {
            Settings configuration = Settings.builder()
                    .put("cluster.name", "production-cluster")  
                    .put("client.transport.ignore_cluster_name", true)  
                    .build();
            
            // クライアントの作成
            esClient = new PreBuiltTransportClient(configuration)
                    .addTransportAddress(new TransportAddress(InetAddress.getByName("localhost"), 9300));
            
            return esClient;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

2:クライアントを使用したインデックスの作成とIKアナライザの指定

package com.example.elasticsearch.operations;

import org.elasticsearch.action.DocWriteResponse;
import org.elasticsearch.action.admin.indices.analyze.AnalyzeRequestBuilder;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.IndicesAdminClient;
import org.elasticsearch.client.Requests;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.transport.client.PreBuiltTransportClient;

import java.io.IOException;
import java.net.InetAddress;
import java.util.Date;
import java.util.Map;

import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;

public class EsIndexHandler {

    private TransportClient esClient;
    
    public EsIndexHandler() {
        this.esClient = new EsConnectionManager().getEsConnection();
    }

    // インデックスの作成とIKアナライザの指定
    public void setupIndexWithAnalyzer() throws IOException {
        // マッピングの作成
        XContentBuilder mappingDefinition = XContentFactory.jsonBuilder()
                .startObject()
                .startObject("properties")
                .startObject("title").field("type", "text").field("analyzer", "ik_smart").endObject()
                .startObject("content").field("type", "text").field("analyzer", "ik_max_word").endObject()
                .endObject()
                .endObject();

        // インデックスとマッピングの設定
        PutMappingRequest mappingRequest = Requests.putMappingRequest("articles").type("document").source(mappingDefinition);
        
        // インデックスの作成
        esClient.admin().indices().prepareCreate("articles").execute().actionGet();
        
        // マッピングの適用
        esClient.admin().indices().putMapping(mappingRequest).actionGet();
    }
}

これでインデックスが作成され、マッピングが設定されます。

3:作成したインデックスへのデータ追加(IDは重複不可)

    public void addDocumentToIndex() throws IOException {
        IndexResponse response = esClient.prepareIndex("articles", "document", "doc1")
                .setSource(jsonBuilder()
                        .startObject()
                        .field("title", "Elasticsearch入門")   
                        .field("content", "Elasticsearchは高性能な検索エンジンです")
                        .endObject()
                ).get();
    }

Postmanを使用してインデックスをクエリできます:

4:インデックスの更新(IDが同じ場合は上書き)

    public void updateExistingDocument() throws IOException {
        UpdateResponse response = esClient.update(new UpdateRequest("articles", "document", "doc1")
                .doc(XContentFactory.jsonBuilder()
                        .startObject()
                        .field("title", "Elasticsearch完全ガイド")
                        .field("content", "Elasticsearchは分散型のオープンソース検索エンジンであり、大量のデータを高速に検索できます")
                        .endObject()
                )).get();
    }

Postmanを使用して更新後のインデックス内容を確認できます

5:インデックスのクエリ(アナライザによる分词処理)

contentフィールドのクエリ:

クエリ結果:

titleフィールドのクエリ:

クエリ結果:

6:インデックスへの追加データ投入

    public void addSecondDocument() throws IOException {
        IndexResponse response = esClient.prepareIndex("articles", "document", "doc2")
                .setSource(jsonBuilder()
                        .startObject()
                        .field("title", "検索エンジン技術")
                        .field("content", "検索エンジン技術は現代の情報検索において不可欠です")
                        .endObject()
                ).get();
    }

contentフィールドのクエリ:

結果:2件のドキュメントがヒットします。クエリ内容「Elasticsearch」が細かく分割され、「検索」という語句が両方のドキュメントに含まれるためです。

titleフィールドのクエリ:

クエリ結果:1件のみヒットします。titleフィールドでは粗粒度のアナライザが使用されるためです。

7:Search APIの操作:

   public void performSearchOperations() {<br></br>        // titleフィールドでの検索<br></br>        SearchResponse titleSearch = esClient.prepareSearch("articles")<br></br>                .setTypes("document")<br></br>                .setSearchType(SearchType.QUERY_THEN_FETCH)<br></br>                .setQuery(QueryBuilders.matchQuery("title", "Elasticsearch"))<br></br>                .setFrom(0).setSize(10).setExplain(true)<br></br>                .get();<br></br>        <br></br>        long titleHits = titleSearch.getHits().totalHits;<br></br>        System.out.println("titleでのヒット数: " + titleHits);<br></br>        <br></br>        // contentフィールドでの検索<br></br>        SearchResponse contentSearch = esClient.prepareSearch("articles")<br></br>                .setTypes("document")<br></br>                .setSearchType(SearchType.QUERY_THEN_FETCH)<br></br>                .setQuery(QueryBuilders.matchQuery("content", "検索"))<br></br>                .setFrom(0).setSize(10).setExplain(true)<br></br>                .get();<br></br>        <br></br>        long contentHits = contentSearch.getHits().totalHits;<br></br>        System.out.println("contentでのヒット数: " + contentHits);<br></br>    }

8:Get APIの操作:

    public void retrieveDocument() {
        GetResponse response = esClient.prepareGet("articles", "document", "doc1").get();
        Map<String, Object> documentSource = response.getSource();
        
        for (Map.Entry<String, Object> entry : documentSource.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
    }

9:Bulk APIによる一括データ追加

    /**
     * 一括でインデックスを作成しデータを追加
     */
    public void bulkIndexDocuments() throws IOException {
        BulkRequestBuilder bulkOperation = esClient.prepareBulk();

        // 最初のドキュメント
        bulkOperation.add(esClient.prepareIndex("articles", "document", "doc3")
                .setSource(jsonBuilder()
                        .startObject()
                        .field("title", "全文検索システム")
                        .field("postDate", new Date())
                        .field("content", "全文検索システムはドキュメント全体を対象に検索を行います")
                        .endObject()
                )
        );

        // 2番目のドキュメント
        bulkOperation.add(esClient.prepareIndex("articles", "document", "doc4")
                .setSource(jsonBuilder()
                        .startObject()
                        .field("title", "分散アーキテクチャ")
                        .field("postDate", new Date())
                        .field("content", "Elasticsearchは分散アーキテクチャを採用しています")
                        .endObject()
                )
        );

        BulkResponse bulkResponse = bulkOperation.get();
        if (bulkResponse.hasFailures()) {
            // エラー処理
            System.out.println("Bulk操作に失敗しました: " + bulkResponse.buildFailureMessage());
        } else {
            System.out.println("Bulk操作が成功しました");
        }
    }

10:検索結果のJSON形式での返却

   /**
     * 商品検索機能
     */
    public JSONObject searchProducts(String keyword) {
        SearchResponse searchResult = esClient.prepareSearch("products", "catalog")  
                .setTypes("item")  
                .setSearchType(SearchType.QUERY_THEN_FETCH)
                .setQuery(QueryBuilders.matchQuery("productName", keyword))  
                .setFrom(0).setSize(20).setExplain(true)
                .get();

        SearchHit[] matchedItems = searchResult.getHits().getHits();
        
        JSONObject resultJson = new JSONObject();
        for (int i = 0; i < matchedItems.length; i++) {
            String documentJson = matchedItems[i].getSourceAsString();
            resultJson.put("item_" + i, documentJson);
        }

        return resultJson;
    }

Elasticsearchの高速性の理由: https://www.elastic.co/jp/blog/why-is-elasticsearch-so-fast

Java API公式ドキュメント: https://www.elastic.co/guide/en/elasticsearch/client/java-api/6.0/index.html

タグ: Elasticsearch Java API TransportClient Indexing Search API

6月4日 22:04 投稿