Elasticsearch SQL CLIを外に出して使う

# 概要

Elasticsearechに対してSQLで結果を取得できるSQL Accessが6.3から提供されています。

SQL AccessのためのCLIは、Elasticsearch本体に含まれていますが、
SQLでSELECTして結果をCSVで保存するということを、**外からCIサーバやバッチでやりたい**と思うのは、人情です。

それをやってみましょう、という内容です。

# まず読むもの

https://www.elastic.co/guide/en/elasticsearch/reference/6.x/sql-cli.html#sql-cli

> The jar containing the SQL CLI is a stand alone Java application and the scripts just launch it. You can move it around to other machines without having to install Elasticsearch on them.


**You can move it around to other machines without having to install Elasticsearch on them.**

と書いてあるので、jarファイルだけ他所に持って行って動かしてしまいしょう。

そのjarファイルは、 /usr/share/elasticsearch/bin/elasticsearch-sql-cli-6.3.0.jar　にあります。
（Elastic社が公開しているDockerイメージだと）


# 方法

SQLCLIコマンドの第1引数に接続先のElasticsearchサーバのURLを書けば良い、となっています。

> You can pass the URL of the Elasticsearch instance to connect to as the first parameter:
```
$ ./bin/elasticsearch-sql-cli https://some.server:9200
```

jarファイルだけを持って行った例だと、このように書けます。

```
java -jar /usr/share/elasticsearch/bin/elasticsearch-sql-cli-6.3.2.jar 
```

通常起動すると、このように対話型モードとなっています。

![sql.png](https://qiita-image-store.s3.amazonaws.com/0/111676/8ba340b6-353a-dff4-9fea-3e7ea2f51df7.png)

対話型モードでないオプションはないかな？と　ヘルプを確認すると、こうなっています。

```
Elasticsearch SQL CLI

Non-option arguments:
uri                  

Option                   Description                                           
------                   -----------                                           
-c, --check <Boolean>    Enable initial connection check on startup (default:  
                           true)                                               
-d, --debug              Enable debug logging                                  
-h, --help               show help                                             
-k, --keystore_location  Location of a keystore to use when setting up SSL. If 
                           specified then the CLI will prompt for a keystore   
                           password. If specified when the uri isn't https then
                           an error is thrown.                                 
-s, --silent             show minimal output                                   
-v, --verbose            show verbose output 
```


コマンドを受け付けるオプションは特に用意されてないようです。(MySQLのeオプションのような）

# それでも外からSQL渡したい

定番のパイプやリダイレクトでSQLを渡すことができます。

```sh
echo "show tables;" | \
java -jar  /usr/share/elasticsearch/bin/elasticsearch-sql-cli-6.3.2.jar http:/xxx.xxx.xxx.xxx:9200
```

# WARNINGも消したいなら


![sql1.png](https://qiita-image-store.s3.amazonaws.com/0/111676/dae9c953-0374-ec7b-c29c-9a1dca97c835.png)

この起動方法だと、WARNINGログが出てしまうので、標準出力のみを残すようにする場合だとこんな感じに。

```sh
echo "show tables;" |\
 java -jar  /usr/share/elasticsearch/bin/elasticsearch-sql-cli-6.3.2.jar \
 http:/xxx.xxx.xxx.xxx:9200 2>/dev/null 
```
# X-Packのロゴが・・・

そんなあなたはsedコマンドを。

```sh
echo "show tables;" |\
 java -jar  /usr/share/elasticsearch/bin/elasticsearch-sql-cli-6.3.2.jar \
 http:/xxx.xxx.xxx.xxx:9200 2>/dev/null | \
 sed -e '1,26d'

```

![sql2.png](https://qiita-image-store.s3.amazonaws.com/0/111676/2e35a344-e478-65d6-a61e-827087fef2c7.png)


# まとめ

jarファイル１つで、sqlcliが動くのは心強い。

SQLCLIの使いどころは対話型で何かやるところ。無理やり単体で使おうとするより、決まったSQLを投げて結果を取得する、という目的であればcurlで_xpack/sqlにリクエストを投げる方が何倍も楽。
（あたりまえの結論だけども）



# 過去記事

[Elasticsearch 6.3.0 リリース記念　X-Pack SQL Accessをやってみよう](https://qiita.com/tsgkdt/items/7d0b82e571fcd5726a49)

# [番外編] Dockerにするなら

```Dockerfile
FROM openjdk:10-slim

ENV ELASTICSEARCH_URL= \
    SQL_VERSION=6.3.2

COPY run.sh /

RUN chmod +x /run.sh

ENTRYPOINT ["/run.sh"]
COPY elasticsearch-sql-cli-${SQL_VERSION}.jar /usr/share/elasticsearch/bin/
```

で、entrypointに指定しているrun.shはこんな感じに。

```sh
#!/bin/bash

SQL="-h"

if [ $# -eq 1 ]; then
  SQL=$1
fi

if [ -z "$ELASTICSEARCH_URL" ] && [ "${ELASTICSEARCH_URL:-A}" = "${ELASTICSEARCH_URL-A}" ] ; then
  ELASTICSEARCH_URL=http://localhost:9200
fi

 
echo $SQL | java -jar /usr/share/elasticsearch/bin/elasticsearch-sql-cli-${SQL_VERSION}.jar \
   ${ELASTICSEARCH_URL} 2>/dev/null \
   | sed -e '1,26d'
```
こうすると、docker runでSQL文を渡すと結果が返ってくる、ということができるようになります。
(-eオプションでElasticsearchの場所を、CMDでSQL文を渡している)

```sh
docker run --rm -it -e ELASTICSEARCH_URL=http://xxx.xxx.xxx.xxx:9200 es:latest "SELECT \* FROM test;"
```

![sql3.png](https://qiita-image-store.s3.amazonaws.com/0/111676/2e469713-2cfa-6279-2a16-930406d0ac67.png)

# [番外編] 違うバージョンのESに接続しようとしたら

SQLCLIのjarは、6.3.0として、試しに２つの環境に接続をしてみました。

* ES6.3.2への接続は出来る
* ES5.6.0への接続は不可

> ERROR: Cannot communicate with the server http://xxx.xxx.xxx.xxx:9200. This version of CLI only works with Elasticsearch version v6.3.0 [424e937]

![sql4.png](https://qiita-image-store.s3.amazonaws.com/0/111676/b7f10883-749d-fe16-263f-a635acb64114.png)

特段の事情がない限り、バージョンはあわせておくのが吉ですな。