Solr vs elasticsearch 類似文書検索 (日本語解析の設定)


こんにちは、馬場です。

Luceneベースのオープンソースの全文検索エンジンとしては、Solrとelasticsearchが知られていますが、この記事では日本語の類似文書検索機能に関して、両者を比較します。この記事は機能の比較はせずに、日本語の類似文書検索を実現するにあたり設定やプログラムの実装がどのように違うのか、具体的な設定やプログラムとともに紹介します。

※ この記事では、Solr 4.6.0 とelasticsearch 0.90 の比較を行います。

実現したいこと

  • 類似文書検索機能をScalaで実装する
  • 文書は日本語。
  • 文書はID、タイトル、本文、公開日からなる。
  • 顔文字の検索も可能にしたいので、記号もインデクシングする。ユーザ辞書を利用する

ドキュメント

Solr のサイトは以下です。
http://lucene.apache.org/solr/
簡単なチュートリアルがありますが、もう少し詳しい情報はWikiにあります。

elasticsearchのサイトは以下です。
http://www.elasticsearch.org/
Solr よりもマニュアルが豊富できれいですし、ビデオによるチュートリアルもたくさん用意されています。
ただ、ネット上の情報、特に日本語の情報/日本語に関する情報は、まだSolrの方が多いと感じました。例えば、今回の設定は、Solrであればそのものずばり、コピー&ペーストすれば終わるような設定方法が書かれた記事がたくさん存在するのに対して、elasticsearchの場合は、elasticsearchのマニュアル(英語)やQ&Aサイト(英語)、日本語のブログ記事などを全て読み、設定しました。

日本語の解析

最初は、日本語の文書を解析できるように設定する方法を比較します。
Solr もelasticsearchも、日本語解析器としてkuromoji を利用するのが一番簡単です。ただ、設定方法はかなり違います。

Solrの場合

Solr で日本語を利用できるようにするには、XMLの設定ファイルを編集し、再起動します。
まずは、config/schema.xml を編集します。記号を扱えるようにtokenizer のdiscardPunctuation属性をfalseに設定しています。また、userDictionary を指定し、userdict_ja.txtを設定します。

<fieldType name="text_ja" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="false">
  <analyzer>
    <tokenizer class="solr.JapaneseTokenizerFactory" mode="search" discardPunctuation="false" userDictionary="lang/userdict_ja.txt"/>
    <!--<tokenizer class="solr.JapaneseTokenizerFactory" mode="search" userDictionary="lang/userdict_ja.txt"/>-->
    <!-- Reduces inflected verbs and adjectives to their base/dictionary forms (辞書形) -->
    <filter class="solr.JapaneseBaseFormFilterFactory"/>
    <!-- Removes tokens with certain part-of-speech tags -->
    <filter class="solr.JapanesePartOfSpeechStopFilterFactory" tags="lang/stoptags_ja.txt" />
    <!-- Normalizes full-width romaji to half-width and half-width kana to full-width (Unicode NFKC subset) -->
    <filter class="solr.CJKWidthFilterFactory"/>
    <!-- Removes common tokens typically not useful for search, but have a negative effect on ranking -->
    <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ja.txt" />
    <!-- Normalizes common katakana spelling variations by removing any last long sound character (U+30FC) -->
    <filter class="solr.JapaneseKatakanaStemFilterFactory" minimumLength="4"/>
    <!-- Lower-cases romaji characters -->
    <filter class="solr.LowerCaseFilterFactory"/>
  </analyzer>
</fieldType>

Solr で類似文書検索をするためには、あらかじめconf/schema.xml で文書を登録するスキーマを定義します。

   <field name="title" type="text_ja" indexed="true" stored="true" />
   <field name="body" type="text_ja" indexed="true" stored="true"/>
   <field name="published_at" type="date" indexed="true" stored="true"/>

type にtext_ja を設定することにより、Solr が日本語として解析を行ってくれます。

(参考: http://www.rondhuit.com/solrの日本語対応.html)

elasticsearchの場合

elasticsearch で日本語の解析ができるようにするためには、まずプラグインをインストールする必要があります。

bin/plugin -install elasticsearch/elasticsearch-analysis-kuromoji/1.7.0

インストール後、elasticsearchを再起動します。通常のプラグインの場合は再起動は不要なのですが、解析器の追加の場合は必要です。

さらに、日本語解析器、kuromoji_analyzerをデフォルトにしたインデックスを作成します。日本語解析器の設定はREST-API を利用して行います。

curl -XPUT 'http://localhost:9200/test/' -d'
{
  "index":{
    "analysis":{
      "tokenizer" : {
        "kuromoji_user_dict" : {
          "type" : "kuromoji_tokenizer",
          "mode" : "extended",
          "discard_punctuation" : "false",
          "user_dictionary" : "userdict_ja.txt"
        }
      },
      "analyzer" : {
        "default" : {
          "type" : "custom",
          "tokenizer" : "kuromoji_user_dict",
          "filter" : ["kuromoji_baseform","pos_filter","cjk_width","stop_ja","stemmer","lowercase"]
        }
      },
      "filter" : {
        "pos_filter" : {
          "type" : "kuromoji_part_of_speech",
          "stoptags" : ["接続詞","助詞","助詞-格助詞","助詞-格助詞-一般","助詞-格助詞-引用","助詞-格助詞-連語","助詞-接続助詞","助詞-係助詞","助詞-副助詞","助詞-間投助詞","助詞-並立助詞","助詞-終助詞","助詞-副助詞/並立助詞/終助詞","助詞-連体化","助詞-副詞化","助詞-特殊","助動詞","記号","記号-一般","記号-読点","記号-句点","記号-空白","記号-括弧開","記号-括弧閉","その他-間投","フィラー","非言語音"]
        },
        "stemmer" : {
          "type" : "kuromoji_stemmer",
          "minimum_length" : 4
        },
        "stop_ja" : {
          "type" : "stop",
          "stopwords_path" : "stopwords_ja.txt"
        }
      }
    },
    mappings: {
      default: {
        _timestamp: {enabled: true, path: "published_at"},
        _all: {enabled: true, analyzer: "kuromoji_analyzer"},
        properties : {
          update_date : { type: "date" , formate : "yyyy/MM/dd"}
        }
      }
    }
  }
}
‘

ポイントは以下の通りです。

  • analysis.tokenizer でtype=kuromoji_tokenizerのkuromoji_user_dictを設定。Solr と同様、discard_puctuation/user_dictionary を設定
  • default analyzerとして、kuromoji_user_dictを利用するkuromoji_analyzerを設定
  • kuromoji_analyzerはSolr がデフォルトで設定していたFilterを全て利用する
  • mappingで、_allのanalyzerを作成したkuromoji_analyzerに

上記で動作しましたが、もう少しスマートな設定があるかもしれません。

(参考:https://github.com/elasticsearch/elasticsearch-analysis-kuromoji

おわりに

今回は、日本語解析のための設定方法について、比較を行いました。Solr のメリットは情報の多さだと思います。対して、elasticsearchのメリットは、REST-API による設定変更が可能な点でしょう。

次回はドキュメントの登録方法について、比較してみたいと思います。


This entry was posted in その他. Bookmark the permalink.