形態素解析器を使って日本語検索ができるようにelasticsearchのプラグインであるkuromojiをインストールします.

インストール

前回のelasticsearch-headと同様,プラグインコマンドで一発インストールが可能です(*当然事前にelasticsearchのインストールが必要).
まず,elasticsearch-analysis-kuromojiのページにあるREADME.mdから使用しているelasticsearchのバージョンにあったkuromojiのバージョンを確認します.そして,elasticsearchを設置した場所で

./bin/plugin -install elasticsearch/elasticsearch-analysis-kuromoji/2.1.0

(2.1.0の部分に適切なバージョン数を記載します.)
これでプラグインのインストールが完了しました.
追加したプラグインを有効にするためにelasticsearchを再起動します.

使い方

kuromojiが正常にインストールされているかどうか確認します.

$ 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" : 5
                },
                "greek_lowercase_filter" : {type: "lowercase", language: "greek"}
            },
            
            "tokenizer" : {
                "kuromoji" : {
                   "type":"kuromoji_tokenizer"
                }
            },
            "analyzer" : {
                "kuromoji_analyzer" : {
                    "type" : "custom",
                    "tokenizer" : "kuromoji_tokenizer",
                    "filter": ["kuromoji_baseform", "kuromoji_ks", "kuromoji_pos", "greek_lowercase_filter", "cjk_width"]
                }
            }
            
        }
    }
}'
# 以下が出力されればok
{"ok":true,"acknowledged":true}

上記のようにindexを定義する際にanalyzerやfilterの設定が出来ます.”analysis”内の”filter”で独自にfilterを定義することも可能です.そうして定義したfilterやデフォルトで用意されているfilterを独自に定義したanalyzer(今回はkuromoji_analyzer)にセットすることが出来ます.以下,上記のjsonについて何点か解説します.

analyzerの定義

インデックス対象とクエリの解析に使うanalyzer.

"kuromoji_analyzer": {
  "type" : "custom",
  "tokenizer" : "kuromoji_tokenizer",
  "filter": ["kuromoji_baseform", 
             "cjk_width", 
             "kuromoji_ks", 
             "kuromoji_pos",
             "greek_lowercase_filter"]}

kuromoji_analyzerというanalyzerを新たに定義し,tokenizerとしてkuromoji_tokenizerを使うように設定しています.この設定により日本語形態素解析が行われるようになります.それに加えいくつかfilterを設定しています.設定できるfilterの種類はREADME.mdに詳しく記載されているのでそちらを参照してください.

kuromoji_baseform

日本語の動詞と形容詞を原型に戻すfilter.ドキュメント内の単語も原型に戻されてインデックスされ,クエリの単語も原型に戻されるようにすることでマッチングの精度を高めます.

cjk_width

全角英数字を半角に直し,半角カタカナを全角に直すなど,漢字圏の文字の全半角を整えることでマッチングをしやすくします.

kuromoji_pos

下記で独自に定義した品詞のフィルタです.特定の品詞をインデックスからもクエリからも除外し,マッチングの精度を高めています.

"kuromoji_pos" : {type: "kuromoji_part_of_speech", 
                  stoptags: ["# verb-main:", "動詞-自立", "助詞-格助詞-一般", "助詞-終助詞"]}

kuromoji_ks

下記で独自に定義したカタカナ単語の末尾にある伸ばし音処理に関するフィルタです.minimum_lengthで定義した文字数以上のカタカナ語の末尾伸ばし棒をインデックスからもクエリからも除外し,マッチングの精度を高めています(例:コンピューター → コンピュータ).デフォルトのminimum_lengthは4です.

"kuromoji_ks" : {"type": "kuromoji_stemmer","minimum_length" : 5}

greek_lowercase_filter

下記で独自に定義した英字を小文字化するフィルタです.インデックスもクエリもすべて小文字化し,大文字小文字を無視した検索になるようにします.

"greek_lowercase_filter" : {type: "lowercase", language: "greek"}

analyzerの設定

上記で定義したanalyzerはmappingを指定する際に以下のように記載することで,それぞれのpropertyに対し設定が可能です.
(動的mappingについてはまた別の機会にメモを載せます.)

...
properties: {
        title: {type: "string", 
                store: true, 
                index: "analyzed", 
                analyzer: "kuromoji_analyzer"},
...

デフォルトのtokenizerの設定

毎回インデックス作成時にtokenizer設定するのが面倒な場合は,elasticsearch/config/elasticsearch.ymlをいじることでデフォルトのtokenizerを変えることが出来ます.

vi ./config/elasticsearch.yml
 
index.analysis.analyzer.default.type: custom
index.analysis.analyzer.default.tokenizer: kuromoji_tokenizer

動作確認

実際にkuromojiによって日本語の形態素解析が行われているか確認してみます.
まずはデフォルトのanalyzerでどのように単語が解析されるかをみてみましょう.

$ curl -XGET 'http://localhost:9200/test3/_analyze?pretty=true' -d '国士無双大吟醸'
{
  "tokens" : [ {
    "token" : "国",
    "start_offset" : 0,
    "end_offset" : 1,
    "type" : "<IDEOGRAPHIC>",
    "position" : 1
  }, {
    "token" : "士",
    "start_offset" : 1,
    "end_offset" : 2,
    "type" : "<IDEOGRAPHIC>",
    "position" : 2
  }, {
    "token" : "無",
    "start_offset" : 2,
    "end_offset" : 3,
    "type" : "<IDEOGRAPHIC>",
    "position" : 3
  }, {
    "token" : "双",
    "start_offset" : 3,
    "end_offset" : 4,
    "type" : "<IDEOGRAPHIC>",
    "position" : 4
  }, {
    "token" : "大",
    "start_offset" : 4,
    "end_offset" : 5,
    "type" : "<IDEOGRAPHIC>",
    "position" : 5
  }, {
    "token" : "吟",
    "start_offset" : 5,
    "end_offset" : 6,
    "type" : "<IDEOGRAPHIC>",
    "position" : 6
  }, {
    "token" : "醸",
    "start_offset" : 6,
    "end_offset" : 7,
    "type" : "<IDEOGRAPHIC>",
    "position" : 7
  } ]
}

結果が一文字ずつに分割されてしまっています.
次にanalyzerとして先ほど独自に定義したkuromoji_analyzerを指定して実行します.

curl -XGET 'http://localhost:9200/test3/_analyze?pretty=true&analyzer=kuromoji_analyzer' -d '国士無双大吟醸'
{
  "tokens" : [ {
    "token" : "国士",
    "start_offset" : 0,
    "end_offset" : 2,
    "type" : "word",
    "position" : 1
  }, {
    "token" : "国士無双",
    "start_offset" : 0,
    "end_offset" : 4,
    "type" : "word",
    "position" : 1
  }, {
    "token" : "無双",
    "start_offset" : 2,
    "end_offset" : 4,
    "type" : "word",
    "position" : 2
  }, {
    "token" : "大",
    "start_offset" : 4,
    "end_offset" : 5,
    "type" : "word",
    "position" : 3
  }, {
    "token" : "吟醸",
    "start_offset" : 5,
    "end_offset" : 7,
    "type" : "word",
    "position" : 4
  } ]
}

「国士無双」や「吟醸」がきちんと単語として認識されていることがわかります.
なお,デフォルトのtokenizerの設定をkuromojiにしている場合は,analyzerを明示的に指定しなくても上記の結果が得られます.

Share Button

elasticsearchで日本語全文検索

<2014/04/21>