Amazon Elasticsearch ServiceにJDBCで接続してSQL実行する

Amazon Elasticsearch Service(以下、AES)にJDBC接続する方法です。

AESのSQL機能

AESのSQL機能はOpen Distro for ElasticsearchというAWS主導のプロジェクトで開発されています。

github.com

この辺りは、AESのSQLのエンドポイントやプラグイン名にも表れています。

GET _cat/plugins
~省略
04befbe556ee0e29db85fcf4625c2003 opendistro_sql       x.x.x.x
~省略

まずはSQLを実行してみる

以下のテーブル作ってSQLでクエリします。

POST test/1
{
  "col1": 1000,
  "col2": "OTOMO"
}

SQLの実行は以下のように行います。エンドポイントがopendistroとなっています。

POST _opendistro/_sql
{
  "query": "SELECT * FROM test LIMIT 10"
}

結果が取得できました。

{
  "took" : 6,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "test",
        "_type" : "1",
        "_id" : "DxYI8G4BWCF0H9SzjMIk",
        "_score" : 1.0,
        "_source" : {
          "col1" : 1000,
          "col2" : "OTOMO"
        }
      }
    ]
  }
}

JDBCで接続

やっと本題のJDBC接続です。

JDBCドライバ

上記のように、Elasticserchの純正でなく、AWS主導のプロジェクトで進められた実装のため、JDBCドライバも異なります。

github.com

READMEにあるように以下のようにGradleで簡単にビルドできます。

  • Linux
$ ./gradlew shadowJar
  • Windows
> .\gradlew.bat shadowJar

接続サンプルコード

ざっくりコードで申し訳ないですが、やりたいことはだいたいはわかると思います。EC2のロール使ってつなぎにいっています。オプションはGithubのリポジトリにあるREADMEに記載があります。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.sql.ResultSet;
import java.util.Properties;

public class Test {
    public static void main(String[] argv) {
        String aesHost = "vpc-xxxxxxxxx.ap-northeast-1.es.amazonaws.com";
        String region = "ap-northeast-1";

        Connection con = null;
        try {
            Class.forName("com.amazon.opendistroforelasticsearch.jdbc.Driver");
            String url = String.format("jdbc:elasticsearch://%s:443", aesHost);

            Properties properties = new Properties();
            properties.put("region", region);
            properties.put("useSSL", "true");
            properties.put("auth", "AWS_SIGV4");

            con = DriverManager.getConnection(url, properties);
            Statement st = con.createStatement();
            ResultSet rs = st.executeQuery("SELECT * FROM test LIMIT 10");
            while (rs.next()) {
                System.out.println(rs.getString("col1"));
                System.out.println(rs.getString("col2"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (con != null) {
                    con.close();
                }
            } catch (Exception ex) {
                ex.printStackTrace();

            }
        }
    }
}

実行

ビルドしたJDBCのjarファイルをクラスパスに追加して、実行してみます。

> javac Test.java
> java -cp .;./opendistro-sql-jdbc-1.3.0.0-SNAPSHOT.jar Test

ちゃんとデータクエリできています。 f:id:yomon8:20191210225248p:plain

関連

yomon.hatenablog.com