Elasticsearchを初めて使ってみる

#はじめに
Elasticsearchを使った案件を行うことになったので、
インストールをして勉強していきたいと思います。
事前知識は次の通りです。

- SQLではなくて、RESTAPIで動かす
- インストールして起動すれば動く
- あいまい検索とかにもつかえる
- 早くて使いやすいらしい

それ以外はまだ何もわからない状態です。

#環境
- CentOS7.2
- java1.8.0_152


#Elasticsearchとは
[公式ページ](https://www.elastic.co/jp/products/elasticsearch)より抜粋
>様々なユースケースを解決する、分散型RESTful検索/分析エンジンです。予期した結果や、そうでないものまで検索できるようにデータを格納するElastic Stackの中核です。

その他の要点をまとめると
1. とにかく早い
2. いろんな言語からアクセスできる
3. シンプルでバンザイ

ってことが書いてありました。すごい良いこと尽くめです。

そして、TOPページを読んでも何したらいいかまだ全然わかりません。

#Elasticsearchを始めてみよう(動画)
公式ページからアドレスを登録すると、
動画でチュートリアルを見ることができます。
ここからは、チュートリアルの内容をベースに記載していきます。

[公式ページ | Elasticsearchを始めてみよう](https://www.elastic.co/jp/videos/getting-started-elasticsearch)
[Github](https://github.com/kosho/elasticsearch-api-usage-examples)

#ダウンロードとインストール
[公式ページ](https://www.elastic.co/jp/)からダウンロードのボタンを押します

![スクリーンショット 2017-12-23 11.08.34.png](https://qiita-image-store.s3.amazonaws.com/0/201860/bec76d5c-fec8-b20e-abbb-d8fa2966c1ea.png)

Elasticsearchを選択
![スクリーンショット 2017-12-23 11.09.05.png](https://qiita-image-store.s3.amazonaws.com/0/201860/38e4fc77-eca1-1acd-0180-2477325eac3f.png)


Tarファイルをダウンロードします。
![スクリーンショット 2017-12-23 10.57.55.png](https://qiita-image-store.s3.amazonaws.com/0/201860/955c0356-3d40-1688-c4ce-11ee542b6ce0.png)

今回はアドレスをコピーしてCurlコマンドを使用します。

```
[ryuji@ryuji ~]$ curl https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.1.1.tar.gz | tar xzf -
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 27.1M  100 27.1M    0     0  5263k      0  0:00:05  0:00:05 --:--:-- 6969k

```

コマンドで起動します。

```
[ryuji@ryuji ~]$ cd elasticsearch-6.1.1/
[ryuji@ryuji elasticsearch-6.1.1]$ bin/elasticsearch
```
起動の確認を行います。次のような結果が返ってくれば成功です。

```
[ryuji@ryuji ~]$ curl http://localhost:9200/
{
  "name" : "ydN1dXT",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "iF-7FAZxTqSgDpy1Uy84qA",
  "version" : {
    "number" : "6.1.1",
    "build_hash" : "bd92e7f",
    "build_date" : "2017-12-17T20:23:25.338Z",
    "build_snapshot" : false,
    "lucene_version" : "7.1.0",
    "minimum_wire_compatibility_version" : "5.6.0",
    "minimum_index_compatibility_version" : "5.0.0"
  },
  "tagline" : "You Know, for Search"
}
```

続いて、Elasticsearchと同様な手順で
可視化ツールのkibanaをインストールし、起動します。

```
[ryuji@ryuji ~]$ curl https://artifacts.elastic.co/downloads/kibana/kibana-6.1.1-linux-x86_64.tar.gz | tar xzf -
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 61.6M  100 61.6M    0     0  2359k      0  0:00:26  0:00:26 --:--:-- 4951k
[ryuji@ryuji ~]$ cd kibana-6.1.1-linux-x86_64/
[ryuji@ryuji kibana-6.1.1-linux-x86_64]$ bin/kibana
```

ブラウザから確認できるということですが、
接続できない・・・
調べてみると、elasticsearchがローカルホストからしか接続可能でないためでした。設定を変更していきます。
`vim elasticsearch-6.1.1/config/elasticsearch.yml`で次の設定を追記します。

```
network.host: 0.0.0.0
```

この設定だと、どこからでもアクセス可となるため、
本来はあまりよくないかもしれません。注意が必要です。

設定を追加後、再度elasticsearchを起動します。
次のエラーがでて失敗しました・・・。

```
ERROR: [3] bootstrap checks failed
[1]: max file descriptors [4096] for elasticsearch process is too low, increase to at least [65536]
[2]: max number of threads [3857] for user [ryuji] is too low, increase to at least [4096]
[3]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
```

ホストを開放すると出てくるエラーのようです。
エラーとなっている3つの上限の設定を変更する必要があります。

ここでかなり時間がかかってしまいました。
本来ならば、`/etc/security/limits.conf`で設定を変更するのですが、
私の環境では、なぜか設定が反映されませんでした。

とりあえず動かしたいので
一時的に制限をあげる方針に変更し、次の通り設定していきます。

```
[ryuji@ryuji elasticsearch-6.1.1]$ sudo sh -c "ulimit -n 65536 && exec su $LOGNAME"
[ryuji@ryuji elasticsearch-6.1.1]$ sudo sysctl -w vm.max_map_count=262144
vm.max_map_count = 262144
[ryuji@ryuji elasticsearch-6.1.1]$ sudo sh -c "ulimit -u 4096 && exec su $LOGNAME"
```

これで無事に起動させることができました。
ですが、まだkibanaをブラウザから開けません。

kibanaもホストを開放する必要があるようなので、
`vim elasticsearch-6.1.1/config/elasticsearch.yml`から次の設定を追記します。

```
network.host: 0.0.0.0
```

ここで、そういえばポート開放していなかった！！と気づき
9200番と5601番のポートを開放しました。

そして、再度kibanaを起動し、ブラウザから確認したところ・・・・
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201860/8a1762c3-b139-e6b5-64ff-87bbf5f4eec3.png)

開けました！
ここまで、3時間ぐらいかかりました！！！
まだここ、公式動画のチュートリアルでは3分ぐらいのとこです。
サーバ設定の知識のなさを痛感させられました。

#データを追加、更新、削除してみよう
では、さっそく色々操作していきます！
##前提知識
RDBと比較した表

|   Elasticsearch   |    RDB      |
|:-----------------|:------------|
|       Index      |データベース  |
|       Type       |テーブル    　|
|     Document     |レコード      |

##データ挿入


```
POST /Index/Type/document_id

```

IndexというデータベースのTypeというテーブルに
document_idのレコードを挿入するといった意味になります。


```
#    +--- Index name
#    |       +--- Type name
#    |       |     +--- Document ID
#    |       |     |
#    V       V     V
PUT /library/books/1
{
  "title": "Norwegian Wood",
  "name": {
    "first": "Haruki",
    "last": "Murakami"
  },
  "publish_date": "1987-09-04T00:00:00+0900",
  "price": 19.95
}
```

##データ取得

```
GET /library/books/1
```

**実行結果**

```
{
  "_index": "library",
  "_type": "books",
  "_id": "1",
  "_version": 1,
  "found": true,
  "_source": {
    "title": "Norwegian Wood",
    "name": {
      "first": "Haruki",
      "last": "Murakami"
    },
    "publish_date": "1987-09-04T00:00:00+0900",
    "price": 19.95
  }
}
```

##アップデート
- PUTでアップデート

priceを29.95にアップデートします。

```
PUT /library/books/1
{
  "title": "Norwegian Wood",
  "name": {
    "first": "Haruki",
    "last": "Murakami"
  },
  "publish_date": "1987-09-04T00:00:00+0900",
  "price": 29.95
}
```

- POSTでアップデート

priceを10にアップデートします。

```
POST /library/books/1/_update
{
  "doc": {
    "price": 10
  }
}
```

##ドキュメントに新しいフィールドを追加
price_jpyを追加します。

```
POST /library/books/1/_update
{
  "doc": {
    "price_jpy": 1800
  }
}
```

**データ取得した結果**

```
{
  "_index": "library",
  "_type": "books",
  "_id": "1",
  "_version": 5,
  "found": true,
  "_source": {
    "title": "Norwegian Wood",
    "name": {
      "first": "Haruki",
      "last": "Murakami"
    },
    "publish_date": "1987-09-04T00:00:00+0900",
    "price": 10,
    "price_jpy": 1800
  }
}
```

price_jpyが追加されていることが確認できます。

##データ削除

- Document単位

```
DELETE /library/books/1
```

**データ取得した実行結果**

```
{
  "_index": "library",
  "_type": "books",
  "_id": "1",
  "found": false
}
```

- Index単位

```
DELETE /library
```

**データ取得した実行結果**

```
{
  "error": {
    "root_cause": [
      {
        "type": "index_not_found_exception",
        "reason": "no such index",
        "resource.type": "index_expression",
        "resource.id": "libray",
        "index_uuid": "_na_",
        "index": "libray"
      }
    ],
    "type": "index_not_found_exception",
    "reason": "no such index",
    "resource.type": "index_expression",
    "resource.id": "libray",
    "index_uuid": "_na_",
    "index": "libray"
  },
  "status": 404
}
```

#データを検索してみよう
##事前準備
検索対象データをひとまとめに作成します。

```
POST /library/books/_bulk
{"index": {"_id": 1}}
{"title": "The quick brown fox", "price": 5}
{"index": {"_id": 2}}
{"title": "The quick brown fox jumps over the lazy dog", "price": 15}
{"index": {"_id": 3}}
{"title": "The quick brown fox jumps over the quick dog", "price": 8}
{"index": {"_id": 4}}
{"title": "Brown fox and brown dog", "price": 2}
{"index": {"_id": 5}}
{"title": "Lazy dog", "price": 9}
```

##いろいろな検索

全件検索

```
GET /library/books/_search
```

ドキュメントの数を制限する。次の例は3件。

```
GET /library/books/_search?size=3
```

titleでキーワード検索をする。キーワードは「fox」


```
GET /library/books/_search
{
  "query": {
    "match": {
      "title": "fox"
    }
  }
}
```

#まとめ
今回はここまでにします。
他にもいろいろな検索条件で検索できたり、
あいまい検索したりなどできるようです。
思ったよりも難しくなさそうだなーという印象でした。