Elasticsearchで日本語人名検索を実装した時のまとめ

f:id:kitahashi-ryoichi:20160110143523p:plain

ゴール:Elasticsearchでサジェストが実装できるようになる

Elasticsearchを1分インストール手順

必要環境

  1. java 7+
  2. Linux (CentOS 6.7) 

インストール手順

Elasticsearch 1.7.4 (本体) v2系はプラグイン未対応が多いため非推奨
wget https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-1.7.4.tar.gz -O elasticsearch.tar.gz
tar xvzf elasticsearch.tar.gz
mv elasticsearch-1.7.4/ /opt/.
cd /opt
ln -s elasticsearch-1.7.4 elasticsearch
kuromojiプラグインインストール(日本語形態素プラグイン)
cd elasticsearch
bin/plugin install elasticsearch/elasticsearch-analysis-kuromoji/2.7.0
headプラグインインストール(データ参照プラグイン)
bin/plugin install mobz/elasticsearch-head
config設定 /opt/elasticsearch/config/elasticsearch.yml
network.bind_host: 0.0.0.0
cluster.name=xxxxx

※Elasticsearchはデフォルトクラスター構成になっているので、同じネットワークにあるマスターから勝手にコピーしたり、自分がマスターになって荒ぶったことをするためcluster.nameは変えておいた方が身のためです。

Elasticsearch起動!
/opt/elasticsearch/bin/elasticsearch start &
headプラグインで起動確認!

http://serverip:9200/_plugin/head

 

RESTで設定とデータを突っ込む

Elasticsearchは全部RESTAPI経由でやれるので今回はそれを利用しました。

インデックスを作ってサジェストさせるまでの流れ 

  1. データセットを準備
  2. 設定jsonをcurlで叩き込む
  3. データをcurlで叩き込む
  4. サジェストAPIを叩く

 

データセットを準備

ここから芸能人Instagramランキングのスクレイピングデータをダウンロードしてください。

 

設定jsonをcurlで叩き込む

データセットはこんなフィールドになっています。

{
"name": "木下優樹菜",
"instagram_name": "yuuukiiinaaa",
"instagram_id": "173974522",
"content": "タレント、モデルの木下優樹菜(ゆっきーな)さんのInstagram(インスタグラム)アカウントです。夫はお笑い芸人の藤本敏史。木下優樹菜(きのしたゆきな):1987年12月4日生まれ 出身地:東京都 血液型:A型 ",
"category": "女性タレント",
"profile_picture": "https://scontent.cdninstagram.com/hphotos-prn/t51.2885-19/10809026_387581471408973_2084297648_a.jpg",
"user_full_name": "yuuukiiinaaa"
}

 

とりあえずnameを入れたらサジェストされる所だけならこれを実行。kana_convなどのフィルターやトークナイザーはひらがなデータがある場合にElasticsearch側がいいかんじにしてくれる用なので今回は使用していません。

設定 

  • index "instagram"
  • type "user"
  • サジェストするfield "name" 
curl -XPUT 'localhost:9200/instagram' -d '
{
"settings": {
"analysis": {
"filter": {
"kana_conv": {
"type": "kuromoji_readingform",
"use_romaji": false
}
},
"analyzer": {
"kuromoji_analyzer": {
"type": "custom",
"tokenizer": "kuromoji_tokenizer"
}
}
}
},
"mappings": {
"user": {
"_source": {
"enabled": true
},
"_all": {
"enabled": true,
"analyzer": "kuromoji_analyzer"
},
"properties": {
"name": {
"type": "completion",
"analyzer": "kuromoji_analyzer",
"search_analyzer": "kuromoji_analyzer",
"payloads": false
}
}
}
}
}'

{"acknowledged":true}が帰ってきたら設定OK

ポイントはtype completionでフィールドを定義してインデックスを作ること。payloadsをtrueにしてサジェスト結果にデータを持たせることもできます。

参考:Completion Suggester

 

データをcurlで叩き込む

得意のワンライナーでデータを入れます。 

cat instagram_data.json | while read line; do curl -XPOST http://localhost:9200/instagram/user/?pretty -d "${line}"; done

headから入れたデータを確認するとこんな感じ

http://serverip:9200/_plugin/head

f:id:kitahashi-ryoichi:20160110141324p:plain

サジェストAPIを叩いてみる

[request]
curl -X POST 'localhost:9200/instagram/_suggest?pretty' -d '{
"hoge" : {
"text" : "木下",
"completion" : {
"field" : "name",
"size" : 10
}
}
}'
※hogeとなっているところは何でも良い、使ってないらしい

[response]
{
"_shards" : {
"total" : 5,
"successful" : 5,
"failed" : 0
},
"hoge" : [ {
"text" : "木下",
"offset" : 0,
"length" : 2,
"options" : [ {
"text" : "木下ココ",
"score" : 1.0
}, {
"text" : "木下優樹菜",
"score" : 1.0
}, {
"text" : "木下安奈",
"score" : 1.0
}, {
"text" : "木下愛未",
"score" : 1.0
}, {
"text" : "木下春奈",
"score" : 1.0
}, {
"text" : "木下理樹",
"score" : 1.0
}, {
"text" : "木下隆行",
"score" : 1.0
} ]
} ]
}

 

でたー!ですが、今のところデータセットが漢字なので、ユーザビリティはかなり低いです。ここからUIUXを高めるために、色んな自然入力へ対応するには2つ大きく対応方法があります。

  1. データセットでひらがなデータを作る
  2. フィルターとトークナイザーを駆使する

フィルターとトークナイザーを駆使するやり方だとkuromojiで漢字→ひらがな変換をいれたり細かい設定作業になるのでそれは次回の説明としましょう。

 

まとめ

type:completionでインデックス作成して、/index/_suggestのAPIを叩けばOK

ほんじゃねー。