Elasticsearch触ってみた。


elasticsearch少しさわってみたという記事。

環境:ubuntu 15.10 / elasticsearch 2.2.0

elasticsearchは、全文検索エンジンのデータベース。
curlで要求を出すとjsonで返ってくる、というインターフェイスに、プラグインもあり、自動でクラスタ構成もできると、いろいろ便利ですごい。

#install

まずjavaをインストール。

次にelasticsearchのインストール。

公式サイトのレポジトリページからコピペhttps://www.elastic.co/guide/en/elasticsearch/reference/current/setup-repositories.html

```
wget -qO - https://packages.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add

echo "deb http://packages.elastic.co/elasticsearch/2.x/debian stable main" | sudo tee -a /etc/apt/sources.list.d/elasticsearch-2.x.list

sudo apt-get update && sudo apt-get install elasticsearch
```

#起動

コマンドで起動。

```
sudo /etc/init.d/elasticsearch start
sudo /etc/init.d/elasticsearch restart

```
#pluginのインストール

elasticsearchには、pluginのインストールコマンドも最初から付いてる。
pluginはいろいろ公開されていて、日本語全文検索できるようになったりする。

analysis-kuromojiをインストールするには

```
sudo /usr/share/elasticsearch/bin/plugin install analysis-kuromoji
```
プラグイン設定は後述。

#とりあえず今の状態を確認する

クラスタ、ノード、といった単語が出てくる。
クラスタというのがあって、クラスタはnodeというものの集まりになっている。
同じクラスタ名が付いたelasticsearchが動く環境（node）を繋げると、自動でクラスタ構成で動く。

elasticsearchの状態を確認

```
curl -XGET http://localhost:9200/  
```

indexの確認

```
curl 'localhost:9200/_cat/indices?v'
```

nodeの状況を確認

```
curl 'localhost:9200/_cat/nodes?v'
```

クラスタの状態を確認（\_cat apiというapi）

```
curl 'localhost:9200/_cat/health?v'
```


##ブラウザで状態の確認をする
ブラウザで確認できるほうが便利だ。
mobz/elasticsearch-headというプラグインを入れるとブラウザで状態を確認することができる。

インストール

```
sudo /usr/share/elasticsearch/bin/plugin install mobz/elasticsearch-head

```
そして``http://localhost:9200/_plugin/head``にブラウザでアクセスする。

#設定を行う

設定の変え方はいくつかあって、設定ファイルを書き換える方法、mapping時に設定する方法、起動時に指定する方法がある。

##設定ファイルで設定する。

設定ファイルは``/etc/elasticsearch/elasticsearch.yml``といったところにある。

以下のように書き換えてみる。

```
cluster.name: my-application
node.name: node-1
index.number_of_shards: 1
index.number_of_replicas: 0
index.analysis.analyzer.default.type: custom
index.analysis.analyzer.default.tokenizer: kuromoji_tokenizer
```
クラスタの名前、ノードの名前、shardの数、replicaの数、デフォルトアナライザーの設定をしている。
デフォルトアナライザーをkuromojiに指定しておくと、とりあえず勝手に日本語全文検索できるようになる。
実際のプロダクトになると、フィールド毎に細かい設定が必要になるので、mappingで設定する。

設定ファイルを書き換えたらelasticsearchを再起動し反映させる。

##mapping
スキーマ定義のようなもので、tokenizerの設定を行ったり、フィールド毎に型や検索の設定をできる。

以下のように送る。単純にstring型だと設定した例。

```
curl -XPOST localhost:9200/tutorial -d '{
    "mappings" : {
        "helloworld" : {
            "properties" : {
                "message" : {
                  "type" : "string"
                  },
                "name" : {
                  "type" : "string"
                }
            }
        }
    }
}'
```

アナライザーや、検索の設定をしていくと、各レコードごとに
寿司がおいしいね->寿司　おいしい
飲み->飲む
寿司->スシ
サーバー->サーバ
といったヒットができるようになる。

mappingの確認。indexがtutorialでtypeがhelloworldの場合

```
curl -XGET 'localhost:9200/tutorial/_mapping/helloworld/?pretty'
```

#indexでデータを格納する
indexというのでデータを格納できる。
index,type,document　といった単語が出てきて、
index/type/documentという構造になっている。

index名をtutorial,typeをhelloworld,documentを｛message、name｝というデータ構造で保存するには以下のようにする。
（elasticは、mappingを行わなくても、データを送ると自動で型をつける。設定でしないようにできる）

```
curl -X POST 'http://localhost:9200/tutorial/helloworld/' -d '{ "message": "Hello World! こんにちは！" ,"name" : "hoge"}'

```

ブラウザでも確認できる。

またindex全体を削除するには以下のコマンド

`curl -XDELETE 'localhost:9200/tutorial?pretty'`

DBの中身全部全消しするには
`curl -XDELETE 'http://localhost:9200/*' {"acknowledged":true}%`


#query
クエリ。
文字列が完全一致するものを探すには以下のようにする。
pythonのelasticsearchクライアントを使っている。

```py
# -*- coding:utf-8 -*-
from elasticsearch import Elasticsearch
import json
es = Elasticsearch("localhost:9200")

matchstring = es.search(index="tutorial",
                        doc_type="helloworld",
                        body={
                            "query" : {
                                "match" : {
                                    "name" : "hoge"
                                }
                            }
                        })
```

simple_query_stringという文字列検索用の便利関数を使った場合。

```py
simpleString = es.search(index="tutorial",
                         doc_type="helloworld",
                         body={
                            "query" : {
                                "simple_query_string" :{
                                    "query" : "こんにちは",
                                    "fields" : ["message"]
                                }
                            }
                         })
```

and,or,を行うには、must,should,というクエリを使うらしい。
name in "hoge" && message in "Hello" はこうっぽい。

```py
queryBool = es.search(index="tutorial",
                      doc_type="helloworld",
                      body={
                        "query":{
                            "bool":{
                                "must":{
                                    "must":{
                                        "term" : {
                                            "name" : "hoge"
                                        }
                                    },
                                    "term" : {
                                        "message" : "Hello"
                                    }
                                }
                            }
                        }
                      })

```

他にもfilterや集計系のクエリがある。
クエリをつかうとスコアを使った検索もできるようだ。

#参考・発展
Elasticsearchの概念を知る
http://blog.shibayu36.org/entry/2015/07/08/095838

Elasticsearchチュートリアル
http://code46.hatenablog.com/entry/2014/01/21/115620

elastic実践的設定とクエリ
http://engineer.wantedly.com/2014/02/25/elasticsearch-at-wantedly-1.html

kuromoji_tokenizerの設定
https://github.com/elastic/elasticsearch-analysis-kuromoji

ElasticSearchのアナライザの設定
http://christina04.hatenablog.com/entry/2015/02/02/225734

pythonクライアントで始める「はじめてのElasticsearch」
http://qiita.com/ikawaha/items/c654f746cfe76b888a27

Elasticsearchとkuromojiでちゃんとした日本語全文検索をやるメモ
http://tech.gmo-media.jp/post/70245090007/elasticsearch-kuromoji-japanese-fulltext-search