Elasticsearchで、漢字データでも平仮名でサジェスト取得

Elasticsearchでサジェスト機能を使いたいんだけど、英語でのネタしか見つからなかったので、日本語でサジェストするメモ。

例えば「と」と打って「東京都」が出てきてほしいけど、そのままデータ登録しても「東」じゃないと出てこない。
なので、Kuromojiのカタカナ変換機能を使ってやってみた。

## インデックス作成

まずインデックスの作成と設定。（例として「`suggest_test`」というインデックス名）

```js
// curl -X PUT 'localhost:9200/suggest_test' -d
{
    "settings": {
        "analysis":{
            "analyzer" : {
                "katakana_analyzer" : {
                    "tokenizer" : "kuromoji_tokenizer",
                    "filter" : ["katakana_readingform"]
                }
            },
            "filter" : {
                "katakana_readingform" : {
                    "type" : "kuromoji_readingform",
                    "use_romaji" : false
                }
            }
        }
    }
}
```

とりあえずサジェスト用のインデックスということで、`katakana_analyzer`だけ使用。
「`kuromoji_readingform`」というのがカタカナかローマ字に変換するモジュール。
参考） [Elasticsearch 日本語で全文検索 その２](https://medium.com/hello-elasticsearch/833a0704e44b#46f6)


## マッピング

次にタイプのマッピング。（例として「`location`」というタイプ名）

```js
// curl -X PUT 'localhost:9200/suggest_test/location/_mapping' -d
{
    "location" : {
        "properties" : {
            "name" : {
                "type" : "string"
            },
            "suggest" : {
                "type" : "completion",
                "index_analyzer" : "katakana_analyzer",
                "search_analyzer" : "katakana_analyzer"
            }
        }
    }
}
```


## サンプルデータ

そしてサンプルデータを入れる。

```js
// curl -X PUT 'localhost:9200/suggest_test/location/1' -d
{
  "name" : "東京都",
  "suggest" : {
    "input": [ "東京都" ],
    "output": "東京都"
  }
}

// curl -X PUT 'localhost:9200/suggest_test/location/2' -d
{
  "name" : "東京都千代田区",
  "suggest" : {
    "input": [ "東京都", "千代田区" ],
    "output": "東京都千代田区"
  }
}

// curl -X PUT 'localhost:9200/suggest_test/location/3' -d
{
  "name" : "千葉県船橋市",
  "suggest" : {
    "input": [ "千葉県", "船橋市" ],
    "output": "千葉県船橋市"
  }
}
```

これで、Kuromojiが自動的にカタカナに変換して格納してくれる模様。

## 検索する

クエリを投げてみる。
※「katakana_analyzer」だけど平仮名でもいける

```js
// curl -X POST 'localhost:9200/suggest_test/_suggest?pretty' -d
{
  "location": {
    "text": "と",
    "completion": {
      "field": "suggest"
    }
  }
}
```

結果

```json
{
   "_shards": {
      "total": 5,
      "successful": 5,
      "failed": 0
   },
   "location": [
      {
         "text": "と",
         "offset": 0,
         "length": 1,
         "options": [
            {
               "text": "東京都",
               "score": 1
            },
            {
               "text": "東京都千代田区",
               "score": 1
            }
         ]
      }
   ]
}
```

サンプルデータを入れる時に「`input`」の部分を分割して入れたので、以下のような検索でも、

```js
// curl -X POST 'localhost:9200/suggest_test/_suggest?pretty' -d
{
  "location": {
    "text": "ち",
    "completion": {
      "field": "suggest"
    }
  }
}
```

「東京都千代田区」はヒットする。

```json
{
   "_shards": {
      "total": 5,
      "successful": 5,
      "failed": 0
   },
   "location": [
      {
         "text": "ち",
         "offset": 0,
         "length": 1,
         "options": [
            {
               "text": "千葉県船橋市",
               "score": 1
            },
            {
               "text": "東京都千代田区",
               "score": 1
            }
         ]
      }
   ]
}
```

「ち」が頭文字である千葉県が先に出てきてるのもいい感じ。

## 不明点あり

上記の設定で「と」で「東京都」が引っ張り出せたけど、こんどは ***「東」だと出てこない*** ・・・
これはどうすればいいかいまのところ不明。