Elasticsearchの新しいJavaクライアント

Posted by johtani on Monday, June 13, 2022

目次

7.16で正式リリースされましたが、Elasticsearchの新しいJavaのクライアントが出ています。 使ってみたので、ちょっとだけ紹介でもしてみようかな。

このクライアントが出るまでは、ElasticsearchのJavaクライアント(REST版)はElasticsearch本体の一部として実装・管理されていました(Elasticsearchのリポジトリにあるclientディレクトリ)。

HTTP経由でElasticsearchにアクセスするクライアントだったのですが、Elasticsearch本体のリポジトリで管理されていることもあり、Elasticsearch本体で利用されているクラスを使用していました。 このため、クライアントライブラリなのですが、Elasticsearch本体のJarが必要になりサイズが大きくなっていました。 また、JavaのObjectへの詰め替えなどの機能も備えておらず、すこし古臭い感じでもあります。 この辺りを刷新する目的もあり新しいクライアントが公開されたようです。 3月くらいに触った時はまだ、ドキュメントが揃ってなかったのですが利用方法などが増えているので移行も楽になってきているようです。 根本的に作り直されたため、これまでのREST Clientとは使い方が違います。ですので、jarだけの差し替えでこれまで動いていたプログラムを移行ができるわけではないので注意が必要です。

どの辺が便利?

順次移行が可能

これまでのRESTクライアントとはパッケージ名もjarも別モノになっています。 ですので、少しずつ新しいJava Clientに切り替えていくことが可能になっています。 根本的に使い方が変わっているので、大きなシステムのクライアントを全部切り替えるのは結構大変かと思います。 ですので、Indexをしている部分だけとか、検索部分だけなどといった部分的な置き換えをしつつ新しいクライアントに慣れていくことができます。

ラムダっぽく書ける

検索のクエリのサンプルを見るとわかりますが、こんな感じでクエリが書けます(公式ドキュメントより抜粋)。

SearchResponse<Product> response = esClient.search(s -> s
    .index("products") 
    .query(q -> q      
        .match(t -> t   
            .field("name")  
            .query(searchText)
        )
    ),
    Product.class      
);

また、最後で渡しているProduct.classは、検索結果をどのクラスのインスタンスにして返すかの指定です。 Elasticsearchのレスポンス(JSON)から値をコピーして返してくれるようになっています。 ですので、値を入れ替える処理を書く必要がなくなっています。

JSON文字列をそのまま使える

触り始めてからリリース(7.17.2より後なら使える)された、JSON文字列からリクエストを作る機能もあります。

これまでのREST Clientだと、Elasticsearchへのリクエストを必ずJavaのメソッドで構築する必要がありました。 今回のこの機能を利用すると、JSON文字列(やファイル)からリクエストオブジェクトを作るためのメソッド.withJson()が提供されています。 例えば、スキーマや設定変更用のリクエストのJSONなどは、Kibanaやcurlから試験的に投げたリクエスト(JSON)と同じものを使いたいことが多いです。また、ElasticsearchのAPIは数が多く、ドキュメントを見ながら利用方法を調べてJSONでまず試行錯誤することが多いです。 このwithJsonメソッドを利用することで、動作確認などをしたJSONがそのままソースにも利用できるので、リクエスト変更時の確認なども容易になると思います。

使ってみて困ったのは?

便利な面も多いのですが、使っていて少し困ったこともあったのでそれもメモを残しておきます。

どんなリクエストを投げているかが不明

先ほども書きましたが、Elasticsearchのリクエストを試行錯誤するときは公式ドキュメントを見ながら、Kibanaなどを利用して試すことが多いです。 ですので、自分がやりたいことのJSONは手元にあることが多いです。 ただ、プログラムでクエリを組み立てる必要も出てきます。この時、実際にRESTリクエストとしてどんなJSONを投げているのかを知りたいことがあります(実際、検索クエリ作っててメソッドの使い方がうまくいかなくて四苦八苦してました)。 4月時点では簡単にリクエストで投げているJSONを文字列としてログに出すメソッドなどは用意されていないようでした。 デバッグ用に次のようなメソッドを書いてみました。 Elasticsearchへ投げるRequestのクラス(例:CreateTemplateRequestとか)を引数に渡すことで、JSON文字列に変換できるようになっています(StringWriterに書き出されてる)。 ここのLoggerはサンプルです。writer.toString()で取り出せる文字列がJSON文字列になっているので、ログに出してみるなり、ファイルに落とすなりしてデバッグのお供にしてください。


import java.io.StringWriter;
import co.elastic.clients.elasticsearch._types.RequestBase;
import co.elastic.clients.json.SimpleJsonpMapper;
import jakarta.json.stream.JsonGenerator;


...
    private void printRequestBodyJsonForDebug(RequestBase request) {

        //for debug
        Logger.log("** Debug print start **");
        StringWriter writer = new StringWriter();
        SimpleJsonpMapper mapper = new SimpleJsonpMapper();
        JsonGenerator generator = mapper.jsonProvider().createGenerator(writer);
        mapper.serialize(request, generator);
        generator.close();
        Logger.log(writer.toString());
        Logger.log("** Debug print finish **");
    }

プラグインなどで提供されるクエリが書けない

LtRプラグインなどは、Elasticsearchの検索クエリを拡張しています。 残念ながら、現時点(2022/06/13)ではカスタムクエリを新しいJavaクライアントで利用しようとした場合、エラーが発生してしまいます(知らないJSONだと判断されてしまいます)。

GitHubのIssueとして「[roadmap] Add support for plugin-defined custom components · Issue #252 · elastic/elasticsearch-java」があります。 これに対応されたら、拡張されたクエリも利用できるようになるでしょう。 プラグインなどで拡張されているものを使いたい場合は、残念ながら既存のRESTクライアントを当面は使うことになりそうです。

まとめ

新しいElasticsearchのJavaクライアントを簡単ですが触ってみて、気になった点を記事にしました。 JavaのObjectに詰め替えてくれる機能など便利になっているので使ってみてください。 ドキュメントもちょっとずつ増えているようで、使い方も分かりやすくなっていました(触った時はレスポンスの扱い方などがJavaDocしか用意されてなかったんです)。 説明が欲しいなぁと思うことがあれば、GitHubにIssueを上げてみるといいかもです。

参考


comments powered by Disqus

See Also by Hugo


Related by prelims-cli