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

  • 60
    Like
  • 1
    Comment
More than 1 year has passed since last update.

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

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

インデックス作成

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

// 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 日本語で全文検索 その2

マッピング

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

// 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"
            }
        }
    }
}

サンプルデータ

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

// 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」だけど平仮名でもいける

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

結果

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

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

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

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

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

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

不明点あり

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