Solrで全角数字を半角数字で検索できない

発生した問題

Solr 3.6.1を使っていて、typeがtext_ja(設定は標準のまま)のフィールドに全角数字を含む文字列を格納すると、半角数字で検索してもヒットしなかった。

例えば、全角で「AKB48」という文字列をSolrに格納すると、

  • 半角「AKB」で検索 ⇒ ヒットする
  • 全角「AKB」で検索 ⇒ ヒットする
  • 半角「48」で検索 ⇒ ヒットしない!
  • 全角「48」で検索 ⇒ ヒットする

という結果になる。

なぜかというと、Solrに含まれているの日本語形態素解析エンジン(kuromoji)では、全角数字は連続していても1文字ずつトークンに分割されてしまうからだった。
(全角英字は1文字ずつ分割されることはなかった。)

  • 全角「AKB48」 ⇒ 「AKB」「4」「8」の3つのトークン

Solrでは全角を半角に変換するフィルタなどが用意・設定されているが、このフィルタが適用されるのは形態素解析後なので、最終的なtermは次のようになる。

  • 全角「AKB48」 ⇒ 「akb」「4」「8」
  • 半角「AKB」 ⇒ 「akb」
  • 全角「AKB」 ⇒ 「akb」
  • 半角「48」 ⇒ 「48」
  • 全角「48」 ⇒ 「4」「8」

このように、半角数字による検索だけtermがマッチしないことがわかる。

対応方法

Solrに格納する前に文字列を正規化すれば解決するのは間違いないけれど、格納する文字列を変えたくなかったので、CharFilterを使ってSolr側で対応することとした。

具体的には、全角数字を半角数字に変換するマッピングファイルを作成し、CharFilterの設定を追加した。

mapping-FullNumber.txt ファイル

 1"0" => "0"
 2"1" => "1"
 3"2" => "2"
 4"3" => "3"
 5"4" => "4"
 6"5" => "5"
 7"6" => "6"
 8"7" => "7"
 9"8" => "8"
10"9" => "9"

schema.xml ファイル(抜粋、charFilter を追加)

1<fieldType name="text_ja" ...省略...>
2  <analyzer>
3    <charFilter class="solr.MappingCharFilterFactory" mapping="mapping-FullNumber.txt"/>
4    <tokenizer class="solr.JapaneseTokenizerFactory" mode="search"/>
5    <filter class="solr.JapaneseBaseFormFilterFactory"/>
6    ...省略...
7  </analyzer>
8</fieldType>

これにより、インデックスを再作成すれば、全角数字は半角数字に変換されたあとで形態素解析され、期待通りの検索結果になった。

  • 全角「AKB48」 ⇒ 「AKB48」 ⇒ 「AKB」「48」 ⇒ 「akb」「48」

lucene-gosen の場合は?

ここまで書いて、日本語形態素解析で lucene-gosen を使った場合はどうなるのか気になったので軽く調べてみた。

lucene-gosen のSolr設定のサンプルは以下のURL先にある。
http://lucene-gosen.googlecode.com/svn/trunk/example/

schema.xml のスニペットを見ると、CharFilterが仕込まれており、mapping-japanese.txt に変換ルールがちゃんと書かれていた。
(全角英数記号を半角に、半角カタカナ+濁点を全角に変換するルール。)

さすが実績のあるライブラリだ。このマッピングファイルを使わせてもらおう…。