ElasticSearchでの類似キーワード検索
ElasticSearchをここ数日使っていて、レーベンシュタイン距離による類似キーワードの検索ができないか試していた
下記のような銀行口座の明細テキストを扱うデータでの類似度による検索をやりたかった
東京電力 料金 17/04 東京電力 料金 17/06 東京電力 料金 17/07 東京電力 料金 17/08 東京電力 料金 17/09 東京電力 料金 17/10 東京電力 料金 17/11 東京電力 料金 17/12 東京電力 料金 18/01 東京電力 料金 18/02
例えば「東京電力 料金 17/12」というキーワードで検索したら、上記のテキストがすべて返ってくるようにしたい
サンプルデータ登録
PUT /whitespace/doc/_bulk {"index": {"_id": 1}} {"analyzer": "whitespace","text": "東京電力 料金 17/11"} {"index": {"_id": 2}} {"analyzer": "whitespace","text": "au ご利用代金 12月ご利用分"} {"index": {"_id": 3}} {"analyzer": "whitespace", "text": "au ご利用代金 1月ご利用分"} {"index": {"_id": 4}} {"analyzer": "whitespace", "text": "au ご利用代金 10月ご利用分"} {"index": {"_id": 5}} {"analyzer": "whitespace", "text": "au ご利用代金 11月ご利用分"} {"index": {"_id": 6}} {"analyzer": "whitespace", "text": "au ご利用代金 12月ご利用分"} {"index": {"_id": 7}} {"analyzer": "whitespace", "text": "au ご利用代金 2月ご利用分"} {"index": {"_id": 8}} {"analyzer": "whitespace", "text": "au ご利用代金 3月ご利用分"} {"index": {"_id": 9}} {"analyzer": "whitespace", "text": "VISA国内利用 VS ニユ-ズピツクス"} {"index": {"_id": 12}} {"analyzer": "whitespace", "text": "東京電力 料金 17/03"} {"index": {"_id": 13}} {"analyzer": "whitespace", "text": "東京電力 料金 17/04"} {"index": {"_id": 14}} {"analyzer": "whitespace", "text": "東京電力 料金 17/06"} {"index": {"_id": 15}} {"analyzer": "whitespace", "text": "東京電力 料金 17/07"} {"index": {"_id": 16}} {"analyzer": "whitespace", "text": "東京電力 料金 17/08"} {"index": {"_id": 17}} {"analyzer": "whitespace", "text": "東京電力 料金 17/09"} {"index": {"_id": 18}} {"analyzer": "whitespace", "text": "東京電力 料金 17/10"} {"index": {"_id": 19}} {"analyzer": "whitespace", "text": "東京電力 料金 17/03"} {"index": {"_id": 20}} {"analyzer": "whitespace", "text": "東京電力 料金 17/04"} {"index": {"_id": 21}} {"analyzer": "whitespace", "text": "東京電力 料金 17/06"} {"index": {"_id": 22}} {"analyzer": "whitespace", "text": "東京電力 料金 17/07"} {"index": {"_id": 23}} {"analyzer": "whitespace", "text": "東京電力 料金 17/08"} {"index": {"_id": 24}} {"analyzer": "whitespace", "text": "東京電力 料金 17/09"} {"index": {"_id": 25}} {"analyzer": "whitespace", "text": "東京電力 料金 17/10"}
analyzerに関しては、明細テキストの場合普通の日本語文章とは異なるので、よく日本語を扱うときに使用されるkuromojiは使わなかった。 代わりにスペースで区切ればいいだろうと思ったので"whitespace"を使用した
検索クエリは下記のような感じ
GET whitespace/_search { "from" : 0, "size" : 20, "query": { "fuzzy": { "text.keyword": { "value": "東京電力 料金 17/10" } } } }
このようにfuzzy query検索をすると、レーベンシュタイン距離による類似度検索が行える いくつかパラメータがあるようだけど内容は
Fuzzy Query | Elasticsearch Reference [6.3] | Elastic
公式を参照
自分がハマったのだが、textというフィールドを対象にするとき .keyword
を付けないとうまくいかなかった。なぜだかはまだわかっていないけど、mappingを確認するとtype: keywordになっていたので、type: keywordのときは明示的に書かないといけないのかな。