ElasticsearchおよびKibanaのインストールとcurlを用いたElasticsearchへのデータの登録

# はじめに
仕事で話題になったので、ElasticsearchとKibanaに触ってみたいと思い、インストールから簡単なデータ投入までやってみます。

# 参考
- [Elasticsearchリファレンス [5.4] » 始めてみよう » インストール](https://www.elastic.co/guide/jp/elasticsearch/reference/current/gs-installation.html)
- [JDK Installation for Linux Platforms](https://docs.oracle.com/javase/8/docs/technotes/guides/install/linux_jdk.html#BJFJHFDD)
- [[Linux]PATHの設定方法](http://devb.hatenablog.com/entry/20101203/1291391256)
- [ElasticSearch6.4.1とkibanaをインストールしてみた]
(https://ameblo.jp/shinnaka54/entry-12407323721.html)
- [Elasticsearchのインストールからデータ投入まで](https://qiita.com/onlyzs/items/045fb33dbd6bd781ce23)
- [Elasticsearch 6 を利用する前に把握しておいた方がよさそうなこと](https://dev.classmethod.jp/server-side/elasticsearch/elasticsearch-6-breaking-changes/)
- [Elasticsearch 超入門](https://qiita.com/kws9/items/7695262be0befb94897f)
- [Elasticsearch マッピング](https://medium.com/hello-elasticsearch/elasticsearch-9a8743746467)
- [Elasticsearchのcurlを使ったindexの削除](https://qiita.com/fujieee/items/5f3795d8213373b3b450)


# 環境
- Amazon Linux 2 AMI (HVM), SSD Volume Type, 64ビット (x86)
- t2.medium(メモリ4GiB, vCPU 2 core)
- SSD 10GiB


#手順
## Java8のインストール
今回はrpmベースドなので、rpmでインストールします。rpmが使えるかは下記コマンドで確認できます。

```
# rpm --version
RPM version 4.11.3
```

ディレクトリ`/usr/java`を作成し、[ここ](https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html)からダウンロードしたjdk-8u191-linux-x64.rpmを配置します。
`rpm -ivh jdk-8u191-linux-x64.rpm`でインストールします。
インストール先のパスは`/usr/java/jdk1.8.0_191-amd64`となります。

パスが通っているかの確認を含めて、バージョンを確認してみます。

```
# java -version
java version "1.8.0_191"
Java(TM) SE Runtime Environment (build 1.8.0_191-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, mixed mode)
```

`export JAVA_HOME=/usr/java/jdk1.8.0_191-amd64`でパスを通します。
パスが通っているかは`echo $JAVA_HOME`で確認できます。

## Elasticsearchのインストール
yumレポジトリを追加します。

```
# vi /etc/yum.repos.d/elasticsearch.repo

[elasticsearch-6.x]
name=Elasticsearch repository for 6.x packages
baseurl=https://artifacts.elastic.co/packages/6.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-md
```
`yum -y install elasticsearch`でインストールできます。
インストールすると最後に下記の文章が表示されます。

```
  Installing : elasticsearch-6.5.4-1.noarch                                 1/1
### NOT starting on installation, please execute the following statements to configure elasticsearch service to start automatically using systemd
 sudo systemctl daemon-reload
 sudo systemctl enable elasticsearch.service
### You can start elasticsearch service by executing
 sudo systemctl start elasticsearch.service
Created elasticsearch keystore in /etc/elasticsearch
  Verifying  : elasticsearch-6.5.4-1.noarch                                 1/1

Installed:
  elasticsearch.noarch 0:6.5.4-1

Complete!
```


## Elasticsearchの設定と起動
Elasticserchにアクセスできるipを設定します。

```
#vi /etc/elasticsearch/elasticsearch.yml

# network.host: 192.168.0.1 # コメントアウト
network.host: 0.0.0.0 # 追加
```

メモリ使用量を設定します。今回はメモリが少ないので、512MBに設定します。

```
$ vi /etc/elasticsearch/jvm.options

# Xms represents the initial size of total heap space
# Xmx represents the maximum size of total heap space

#-Xms1g # コメントアウト
#-Xmx1g # コメントアウト
-Xms512m # 追加
-Xmx512m # 追加
```

`systemctl start elasticsearch`で起動します。
`curl`で起動しているか確認できます。

```
# curl localhost:9200
{
  "name" : "j9pM6nO",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "nu9-DxInSaufjNu-JHCsIg",
  "version" : {
    "number" : "6.5.4",
    "build_flavor" : "default",
    "build_type" : "rpm",
    "build_hash" : "d2ef93d",
    "build_date" : "2018-12-17T21:17:40.758843Z",
    "build_snapshot" : false,
    "lucene_version" : "7.5.0",
    "minimum_wire_compatibility_version" : "5.6.0",
    "minimum_index_compatibility_version" : "5.0.0"
  },
  "tagline" : "You Know, for Search"
}
```

## Kibanaのインストール
yumレポジトリを追加します。

```
#vi /etc/yum.repos.d/kibana.repo

[kibana-6.x]
name=Kibana repository for 6.x packages
baseurl=https://artifacts.elastic.co/packages/6.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-md
```

`yum -y install kibana`でインストールします。

```
# yum -y install kibana
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
Resolving Dependencies
--> Running transaction check
---> Package kibana.x86_64 0:6.5.4-1 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

================================================================================
 Package        Arch           Version          Repository                 Size
================================================================================
Installing:
 kibana         x86_64         6.5.4-1          elasticsearch-6.x         200 M

Transaction Summary
================================================================================
Install  1 Package

Total download size: 200 M
Installed size: 480 M
Downloading packages:
kibana-6.5.4-x86_64.rpm                                    | 200 MB   00:28
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : kibana-6.5.4-1.x86_64                                        1/1
  Verifying  : kibana-6.5.4-1.x86_64                                        1/1

Installed:
  kibana.x86_64 0:6.5.4-1

Complete!
```

## Kibanaの設定と起動

接続ipの設定をします。

```
vi /etc/kibana/kibana.yml

# Specifies the address to which the Kibana server will bind. IP addresses and h
ost names are both valid values.
# The default is 'localhost', which usually means remote machines will not be ab
le to connect.
# To allow connections from remote users, set this parameter to a non-loopback a
ddress.
#server.host: "localhost"
server.host: "0.0.0.0" #追加

# The URL of the Elasticsearch instance to use for all your queries.
elasticsearch.url: "http://localhost:9200" # コメントアウト解除
```

`systemctl start kibana`でkibanaを起動します。
activeになっているか確認します。

```
# systemctl status elasticsearch
● elasticsearch.service - Elasticsearch
   Loaded: loaded (/usr/lib/systemd/system/elasticsearch.service; enabled; vendor preset: disabled)
   Active: active (running) since Wed 2019-01-02 17:58:34 JST; 1h 25min ago
     Docs: http://www.elastic.co
 Main PID: 3283 (java)
   CGroup: /system.slice/elasticsearch.service
           tq3283 /bin/java -Xms512m -Xmx512m -XX:+UseConcMarkSweepGC -XX:CMS...
           mq3411 /usr/share/elasticsearch/modules/x-pack-ml/platform/linux-x...

Jan 02 17:58:34 ip-172-31-25-200.ap-northeast-1.compute.internal systemd[1]: ...
Jan 02 17:58:34 ip-172-31-25-200.ap-northeast-1.compute.internal systemd[1]: ...
Hint: Some lines were ellipsized, use -l to show in full.
```
ブラウザから`http://ipaddress:5601`にアクセスします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/211712/4f8ae91c-2640-e435-aeeb-d91db0f4f383.png)

## kuromojiのインストール
日本語を使用できるようにプラグインをインストールします。

```
# /usr/share/elasticsearch/bin/elasticsearch-plugin install analysis-kuromoji
-> Downloading analysis-kuromoji from elastic
[=================================================] 100%??
-> Installed analysis-kuromoji
```
インストールできたか確認します。

```
# /usr/share/elasticsearch/bin/elasticsearch-plugin list | grep analysis-kuromoji
analysis-kuromoji
```

## データ登録
[Elasticsearchのインストール手順と簡単な使い方](https://qiita.com/Esfahan/items/963225cd2d2b6b219c05)に従ってデータの投入をしてみます。

### インデックス作成
RDBのDatabaseに相当するものは、インデックスと呼ばれます。
インデックスを作成します。

```
# curl -X PUT "http://127.0.0.1:9200/sample_index"

{"acknowledged":true,"shards_acknowledged":true,"index":"sample_index"}
```

### インデックスの確認
作成したインデックスがあるか確認します。`pretty`とつけるとjsonが整形されて出力されます。
出力を見ると、先ほど作成した"sample_index"（とKibanaのsample dataである".kibana_1"）が登録されています。

また、エイリアスも表示されています。エイリアスはインデックスに着けられる別名で、データを検索するときにエイリアスでまとめて検索対象にする、などといった使い方をします。

```
# curl http://127.0.0.1:9200/_aliases?pretty

{
  ".kibana_1" : {
    "aliases" : {
      ".kibana" : { }
    }
  },
  "sample_index" : {
    "aliases" : { }
  }
}
```

### sample_indexの詳細確認
インデックスの各設定が表示されます。

```
# curl http://127.0.0.1:9200/sample_index/_settings?pretty

{
  "sample_index" : {
    "settings" : {
      "index" : {
        "creation_date" : "1546437654399",
        "number_of_shards" : "5",
        "number_of_replicas" : "1",
        "uuid" : "HeBhtAVkSlWPaQQhcNAzCw",
        "version" : {
          "created" : "6050499"
        },
        "provided_name" : "sample_index"
      }
    }
  }
}
```

### データ登録
RDBではカラムの名前や型といったテーブルの構造を予め定義する必要があります。
Elasticsearchでは投入したデータから自動で構造を定義します。Elasticsearchでは、この定義された構造のことをマッピングといいます。もちろんマッピングは予め自分で定義することもできます。

RDBのデータベースに相当するインデックス"sample_index"の下に、RDBのテーブルに相当する「タイプ」として"doc01"を作成し、RDBのレコードに相当する「ドキュメント」として下記のデータを投入します。`/sample_index/doc01/1`の最後尾にある"1"はドキュメントのIDです。指定しない場合は自動で採番されます。

バージョン5系からの変更点として、Content-Typeのヘッダーが必須となりました。

```
# curl -H "Content-Type: application/json" -X PUT "http://127.0.0.1:9200/sample_index/doc01/1" -d '{
    "title" : "Sample No.1",
    "description" : "This is a sample data",
    "tags" : ["Elasticsearch", "Search-Engine"],
    "date" : "2018-07-20T06:30:00",
    "no" : 82,
    "ratio": 0.73,
    "enabled": true
}'

{"_index":"sample_index","_type":"doc01","_id":"1","_version":1,"result":"created","_shards":{"total":2,"successful":1,"failed":0},"_seq_no":0,"_primary_term":1}
```

### マッピング確認
マッピングを確認してみます。

```
# curl "http://127.0.0.1:9200/sample_index/_mapping/doc01?pretty"

{
  "sample_index" : {
    "mappings" : {
      "doc01" : {
        "properties" : {
          "date" : {
            "type" : "date"
          },
          "description" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          },
          "enabled" : {
            "type" : "boolean"
          },
          "no" : {
            "type" : "long"
          },
          "ratio" : {
            "type" : "float"
          },
          "tags" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          },
          "title" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          }
        }
      }
    }
  }
}
```

### データ確認
登録したデータを確認してみます。

```
# curl "http://127.0.0.1:9200/sample_index/doc01/1?pretty"

{
  "_index" : "sample_index",
  "_type" : "doc01",
  "_id" : "1",
  "_version" : 1,
  "found" : true,
  "_source" : {
    "title" : "Sample No.1",
    "description" : "This is a sample data",
    "tags" : [
      "Elasticsearch",
      "Search-Engine"
    ],
    "date" : "2018-07-20T06:30:00",
    "no" : 82,
    "ratio" : 0.73,
    "enabled" : true
  }
}
```

### データ登録2周目
下記のデータを登録してみます。

```
curl -H "Content-Type: application/json" -X PUT "http://127.0.0.1:9200/sample_index/doc01/2" -d '{
    "title" : "Sample No.2",
    "description" : "This is a sample data",
    "tags" : ["Elasticsearch", "Search-Engine","Database"],
    "date" : "2018-07-21T06:40:00",
    "no" : 89,
    "ratio": 0.61,
    "enabled": true,
    "name": "4/2"
}'

{"_index":"sample_index","_type":"doc01","_id":"2","_version":1,"result":"created","_shards":{"total":2,"successful":1,"failed":0},"_seq_no":0,"_primary_term":1}
```

マッピングを確認してみます。"name"が追加されています。

```
# curl "http://127.0.0.1:9200/sample_index/_mapping/do01?pretty"

{
  "sample_index" : {
    "mappings" : {
      "doc01" : {
        "properties" : {
          "date" : {
            "type" : "date"
          },
          "description" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          },
          "enabled" : {
            "type" : "boolean"
          },
          "name" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          },
          "no" : {
            "type" : "long"
          },
          "ratio" : {
            "type" : "float"
          },
          "tags" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          },
          "title" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          }
        }
      }
    }
  }
}
```
マッピングと異なる型のデータを登録してみます。"no"を文字型にしてみましょう。
すると下記のようにエラーになります。

```
curl -H "Content-Type: application/json" -X PUT "http://127.0.0.1:9200/sample_index/doc01/3" -d '{
    "title" : "Sample No.3",
    "description" : "This is a sample data",
    "tags" : ["Elasticsearch", "Search-Engine","Database"],
    "date" : "2018-07-21T06:40:00",
    "no" : "ABCDE",
    "ratio": 0.61,
    "enabled": true,
    "name": "4/2"
}'

{"error":{"root_cause":[{"type":"mapper_parsing_exception","reason":"failed to parse field [no] of type [long]"}],"type":"mapper_parsing_exception","reason":"failed to parse field [no] of type [long]","caused_by":{"type":"illegal_argument_exception","reason":"For input string: \"ABCDE\""}},"status":400}
```
以上から、項目の追加は可変、一度登録したデータ型は不変になることがわかります。

### 手動でマッピング定義

新しいインデックスの作成と同時にマッピングを定義します。

```
curl -H "Content-Type: application/json" -X PUT "http://127.0.0.1:9200/sample_index2" -d '{
 "mappings" : {
   "doc02" : {
     "properties" : {
       "date" : {
         "type" : "date"
       },
       "description" : {
         "type" : "text",
         "fields" : {
           "keyword" : {
             "type" : "keyword",
             "ignore_above" : 256
           }
         }
       },
       "enabled" : {
         "type" : "boolean"
       },
       "name" : {
         "type" : "text",
         "fields" : {
           "keyword" : {
             "type" : "keyword",
             "ignore_above" : 256
           }
         }
       },
       "no" : {
         "type" : "long"
       },
       "ratio" : {
         "type" : "float"
       },
       "tags" : {
         "type" : "text",
         "fields" : {
           "keyword" : {
             "type" : "keyword",
             "ignore_above" : 256
           }
         }
       },
       "title" : {
         "type" : "text",
         "fields" : {
           "keyword" : {
             "type" : "keyword",
             "ignore_above" : 256
           }
         }
       }
     }
   }
 }
}'

{"acknowledged":true,"shards_acknowledged":true,"index":"sample_index2"}
```
マッピングの確認をします。

```
# curl "http://127.0.0.1:9200/sample_index2/_mapping/doc02?pretty"

{
  "sample_index2" : {
    "mappings" : {
      "doc02" : {
        "properties" : {
          "date" : {
            "type" : "date"
          },
          "description" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          },
          "enabled" : {
            "type" : "boolean"
          },
          "name" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          },
          "no" : {
            "type" : "long"
          },
          "ratio" : {
            "type" : "float"
          },
          "tags" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          },
          "title" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          }
        }
      }
    }
  }
}
```



### データの検索
`_search?q=タグ名:値`で検索クエリを投げることができます。

```
# curl "http://127.0.0.1:9200/sample_index/doc01/_search?q=tags:Database&pretty=true"
{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 1,
    "max_score" : 0.2876821,
    "hits" : [
      {
        "_index" : "sample_index",
        "_type" : "doc01",
        "_id" : "2",
        "_score" : 0.2876821,
        "_source" : {
          "title" : "Sample No.2",
          "description" : "This is a sample data",
          "tags" : [
            "Elasticsearch",
            "Search-Engine",
            "Database"
          ],
          "date" : "2018-07-21T06:40:00",
          "no" : 89,
          "ratio" : 0.61,
          "enabled" : true,
          "name" : "4/2"
        }
      }
    ]
  }
}
```
検索APIは[Elasticsearch 超入門](https://qiita.com/kws9/items/7695262be0befb94897f)が参考になります。

### インデックスの削除
インデックスは次のように削除します。

```
# curl -XDELETE localhost:9200/sample_index?pretty=true
```

# おわりに
きちんとしたデータの登録と、Kibanaでの可視化は別記事で書ければと思います。