Elasticsearchで、分かち書き(kuromoji:形態素解析)したqueryを_searchする。

analyzeのkuromoji適用は色々なところに書いてあったが、
searchのkuromoji適用はあまり書いていなかったので、ここにメモします。


# 動作環境
* macOS Mojave 10.14.2
* Java 11.0.2
* Elasticsearch 6.6.0
* kibana 6.6.0
* kuromoji

**Elasticsearch**は全文検索エンジンです。
**Kibana**は、データ可視化ツールです。ポート5601で確認できます。
**kuromoji**は、日本語の形態素解析エンジンです。

# インストール
Java入れたりElasticsearch入れたりのあたりは、以下の記事がとても参考になります。
参考：[はじめての Elasticsearch](https://qiita.com/nskydiving/items/1c2dc4e0b9c98d164329)
ありがとうございました。
基本のキは↑を参考にしてください。

# そもそも押さえておきたいこと
_analyzeと_searchは違うっぽい。

- analyze　…文章をGET(POST?)すると、文章解析した結果がコンソールに表示される。
- search　…検索

# kuromoji(形態素解析)の適用

※`localhost:5601`で **kibana** を立ち上げ、左メニューの **Dev Tools** で操作するものとします。

また、Elasticsearchの言葉として
**index/type/document**
という構造になっています。

・mappingは変更できない。
・さらに、elasticsearch6.0からは複数type×。
ということを踏まえて、インデックスから分けて作り、比較します。

### ・インデックスの設定
はじめに基盤となるインデックスを作っておきましょう。

```json:DevTools
PUT /test_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "hoge_kuromoji_analyzer": {
          "type": "custom",
          "tokenizer": "kuromoji_tokenizer"
        }
      }
    }
  }
}
```
analyzerのところに**"hoge_kuromoji_analyzer"**というものを作っています。※名前は任意の名前で良い。
中にはtokenizerというものを設定していて、形態素解析してくれます。
※**"tokenizer": "kuromoji_tokenizer"**という書き方は変えてはいけません。
参考：[Elasticsearchを日本語で使う設定のまとめ](https://qiita.com/shin_hayata/items/41c07923dbf58f13eec4#kuromoji_tokenizer)

test_indexというインデックスが作成されました。

### ・タイプとドキュメント
ドキュメントをいっぺんに作成しておきます。

```json:DevTools
POST /test_index/test_type/_bulk
{"index": {"_id": 1}}
{"title" : "メモ1","sentence"  : "梅酒は水"}
{"index": {"_id": 2}}
{"title" : "メモ2","sentence"  : "養命酒は水"}
{"index": {"_id": 3}}
{"title" : "メモ3","sentence"  : "私はリンゴが大好きです"}
{"index": {"_id": 4}}
{"title" : "メモ4","sentence"  : "妹の好物は真っ赤なリンゴです"}
```

### ・データの確認
データが入っているかどうかは以下のコマンドで確認しましょう。

```json:DevTools
GET /test_index/test_type/_search
{
  "explain": true,
  "query": {
    "match_all": {}
  }
}
```

これで基礎設定はOKです。

## /インデックス/_analyze
文章をGETすると、文章解析した結果がコンソールに表示されます。
すでにインデックスの設定でanalyzerの箇所にkuromojiを設定してあります。
それを呼び出して使います。

### 普通のanalyze

```json:普通のanalyze
GET /test_index/_analyze
{
  "text": "梅酒が好き"
}
```
【結果】
梅/酒/が/好/き
一文字ひともじ、分析されます。

### kuromoji適用analyze
```json:kuromoji適用analyze
GET /test_index/_analyze
{
  "analyzer": "hoge_kuromoji_analyzer", 
  "text": "梅酒が好き"
}
```
【結果】
梅酒/が/好き
形態素解析(分かち書き)されて、分析されます。


## /インデックス/_search
searchにkuromojiを適用させる場合は、mappingに色々と書くようです。
現在のmapping状況の確認はこちら
`GET /test_index/_mapping` 

※elasticsearch6.0から複数typeのmappingができなくなりました！oh...

### 普通のsearch

```json:普通のsearch
GET /test_index/test_type/_search
{
  "query": {
    "match": {
      "sentence": "梅酒が好き"
    }
  }
}
```
【結果】
0.8630463　"私はリンゴが大好きです"　
0.83355963　"養命酒は水"
0.59321976　"妹の好物は真っ赤なリンゴです"
0.5753642　"梅酒は水"

### kuromoji適用search
searchにもkuromojiを適用させるには、mappingに書き込まなければいけません。
しかし、既存のmappingを変更することはできないので、一番最初(indexを作るとき)に一緒に設定します。

#### ・インデックス作成
```json:/kuromoji_index/kuromoji_type/を作ります。
PUT /kuromoji_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "hoge_kuromoji_analyzer": {
          "type": "custom",
          "tokenizer": "kuromoji_tokenizer"
        }
      }
    }
  },
  "mappings": {
    "kuromoji_type": {
      "properties": {
        "title": {
          "type": "text",
          "analyzer": "hoge_kuromoji_analyzer"
        },
        "sentence": {
          "type": "text",
          "analyzer": "hoge_kuromoji_analyzer"
        }
      }
    }
  }
}
```
**kuromoji_type**に**"tokenizer": "kuromoji_tokenizer"**が設定されました。
これで、searchで飛んできても、分かち書きが適用されます。

#### ・ドキュメント入れ込み
データを入れ込みます。

```json:
POST /kuromoji_index/kuromoji_type/_bulk
{"index": {"_id": 1}}
{"title" : "メモ1","sentence"  : "梅酒は水"}
{"index": {"_id": 2}}
{"title" : "メモ2","sentence"  : "養命酒は水"}
{"index": {"_id": 3}}
{"title" : "メモ3","sentence"  : "私はリンゴが大好きです"}
{"index": {"_id": 4}}
{"title" : "メモ4","sentence"  : "妹の好物は真っ赤なリンゴです"}
```

#### ・データの確認
```json:
GET /kuromoji_index/kuromoji_type/_search
{
  "explain": true,
  "query": {
    "match_all": {}
  }
}
```

#### ・kuromoji適用search

```json:kuromoji適用されているので、そのインデックスでsearch
GET /kuromoji_index/kuromoji_type/_search
{
  "query": {
    "match": {
      "sentence": "梅酒が好き"
    }
  }
}
```
【結果】
0.2876821　"梅酒は水"
0.2876821　"私はリンゴが大好きです"　

精度は落ちましたが、 梅酒/が/好き で検索された結果がきています。
`"explain": true,`を追加すると細かいことが書かれていますがちょっとよくわかりません。

```json:explainを追加してみる
GET /kuromoji_index/kuromoji_type/_search
{
  "explain": true, 
  "query": {
    "match": {
      "sentence": "梅酒が好き"
    }
  }
}
```

# その他参考記事
* [ElasticsearchでKuromoji Tokenizerを試す](http://pppurple.hatenablog.com/entry/2017/05/28/141143)
* [Kuromojiで日本語全文検索 – AWSで始めるElasticSearch(1)](https://dev.classmethod.jp/cloud/aws/use-elasticsearch-1-use-kuromoji/)


# コンソールからやる場合
kibanaのDevToolsを使わず、コンソールからやる場合は
Elasticsearch v6から色々変わっているようです。
Content-Typeの指定が必須となりました。以下のようにコンソールに書いてください。

```console:
curl -H "Content-Type: application/json" -X PUT 'localhost:9200/hoge_index' -d '
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_kuromoji_analyzer": {
          "type": "custom",
          "tokenizer": "kuromoji_tokenizer"
        }
      }
    }
  },
  "mappings": {
    "natsume": {
      "properties": {
        "title": {
          "type": "text",
          "index": "true",
          "analyzer": "my_kuromoji_analyzer"
        },
        "sentence": {
          "type": "text",
          "index": "true",
          "analyzer": "my_kuromoji_analyzer"
        }
      }
    }
  }
}'
```