elasticsearchとkuromojiプラグインで日本語の全文検索
に続き。elasticsearch0.90.2でやってみました。
大きな流れはこんな感じ。
kuromojiプラグインインストール前に、検索できないことをテスト
学術研究用にlivedoorグルメのデータが公開されているので、利用規約に同意してダウンロード、解凍展開した後、
下記のPHPスクリプトを使ってとりあえず47都道府県データのprefのみをelasticsearchへ登録してみました。
<?php setlocale(LC_ALL, 'ja_JP.UTF-8'); $delimiter = ','; $index = 'ldgourmet'; // 下記コメントアウトを外すと、pref以外のCSVファイルもelasticsearchへデータ登録します。 $csv_files = array( // 'area' => './areas.csv', // 'category' => './categories.csv', 'pref' => './prefs.csv', // 'rating' => './ratings.csv', // 'restaurant' => './restaurants.csv', // 'station' => './stations.csv', ); foreach($csv_files as $type => $file) { echo sprintf("[%s] START %s\n", date('Y-m-d H:i:s'), $type); $tp = fopen('php://temp', 'r+'); $fp = fopen($file, 'r'); while(!feof($fp)) { $l = fgets($fp); $l = str_replace('\\', '¥', $l); fwrite($tp, $l); } fclose($fp); rewind($tp); $columns = array(); $n = 0; while(($row = fgetcsv($tp, 0, $delimiter)) !== false) { if ($n++ == 0) { $columns = $row; } else { $data = array_combine($columns, $row); if (!is_array($data)) { print_r($columns); print_r($row); continue; } $id = isset($data['id'])? $data['id'] : $n; $uri = sprintf('http://localhost:9200/%s/%s/%d', $index, $type, $id); $ch = curl_init(); curl_setopt_array($ch, array( CURLOPT_URL => $uri, CURLOPT_HEADER => false, CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => 'PUT', CURLOPT_POSTFIELDS => json_encode($data), )); $result = curl_exec($ch); curl_close($ch); $result = json_decode($result, 'UTF-8'); if (empty($result['ok']) || $result['ok'] != true) { echo sprintf("[%s] ERROR /%s/%s/%s\n", date('Y-m-d H:i:s'), $index, $type, $id); } } } fclose($tp); echo sprintf("[%s] FINISH %s\n", date('Y-m-d H:i:s'), $type); } exit();
php -f import_ldgourmet.php
この状態で次のように検索してみます。
画面はelasticsearchのGUI「elasticsearch-head」がとても便利 - yuhei.kagayaでインストールしたelasticsearch-headのAnyRequestタブでリクエストを組み立てている箇所です。
すると、島根県の他に福島県、徳島県、広島県、鹿児島県がヒットしてしまいました。
島と根が1文字ずつで認識されて、「島」の方でヒットしているようです。
※N-gramのNの値が1であるユニグラム(uni-gram)。
curl -XGET 'http://localhost:9200/ldgourmet/_analyze?pretty' -d '島根' { "tokens" : [ { "token" : "島", "start_offset" : 0, "end_offset" : 1, "type" : "<IDEOGRAPHIC>", "position" : 1 }, { "token" : "根", "start_offset" : 1, "end_offset" : 2, "type" : "<IDEOGRAPHIC>", "position" : 2 } ] }
いったん登録データを消した後、次以降で「島根」で検索できるようにしてみます。
curl -XDELETE 'http://localhost:9200/ldgourmet'
kuromojiプラグインのインストール
をインストールします。pluginコマンド一発で完了です。
/usr/local/elasticsearch-0.90.2/bin/plugin -install elasticsearch/elasticsearch-analysis-kuromoji/1.4.0
インストールされたかテストします。
curl -XPUT 'http://localhost:9200/test/' -d ' { "index":{ "analysis":{ "filter":{ "kuromoji_rf":{ "type":"kuromoji_readingform", "use_romaji" : "true" }, "kuromoji_pos" : { "type": "kuromoji_part_of_speech", "enable_position_increment" : "false", "stoptags" : ["# verb-main:", "動詞-自立"] }, "kuromoji_ks" : { "type": "kuromoji_stemmer", "minimum_length" : 6 } }, "tokenizer" : { "kuromoji" : { "type":"kuromoji_tokenizer" } }, "analyzer" : { "kuromoji_analyzer" : { "type" : "custom", "tokenizer" : "kuromoji_tokenizer" } } } } }'
{"ok":true,"acknowledged":true} と返ってくればOKです。
テスト用のindexはいらないので削除します。
curl -XDELETE 'http://localhost:9200/test'
デフォルトでkuromojiを使うようにelasticsearch.ymlを設定
vi /usr/local/elasticsearch-0.90.2/config/elasticsearch.yml index.analysis.analyzer.default.type: custom index.analysis.analyzer.default.tokenizer: kuromoji_tokenizer
elasticsearchを再起動します。
/etc/init.d/elasticsearch restart
検索
「島根」で島根県のみヒットするようになりました。