Solrの形態素解析で使えるフィルタあれこれ | A Day In The Boy's Life

A Day In The Boy's Life

とあるエンジニアのとある1日のつぶやき。

Apache Solrのschema.xmlを読み解く 」にて少し書いたことですが、Apache Solrの設定ファイル(schema.xml)には様々なフィルタが設定可能で、それによって検索結果が大きく異なってきます。

フィルタの数は多数あって、利用用途やトークナイザーによって変わってきますのでここで書いているのは一部なんですが、こんな検索にヒットさせたいといった場合にフィルタの使い方次第で検索精度を高められたりするので、どういったフィルタがあるのか知っておけば用途に応じて使い分けられて便利です。


ここではApache Solrはバージョン4.6.1を使ってフィルタの検証をしています。



filterとcharFilter要素の違い


フィルタ(filter)要素はschema.xmlファイルのfieldType要素内に定義していきますが、charFilterという要素もあったりして少し混同したりします。

charFilterは、文章を解析する前処理としてデータの加工をするためのフィルタを指定する要素で、文字を置換するためのルールを定義しそれに従って変換するsolr.MappingCharFilterFactory、正規表現でパターンを指定しそれに従って変換するsolr.PatternReplaceCharFilterFactory、HTMLタグを取り除き中の文章だけを抜き取るsolr.HTMLStripCharFilterFactoryなどが標準であります。


HTMLStripCharFilterFactoryはSolrへのデータ投入前にデータ加工しておけばよいのではと思ったり、PatternReplaceCharFilterFactoryは正規表現を使うということでパフォーマンスに影響が出るって記事も見たりするので実質手軽に使えそうなのがMappingCharFilterFactoryぐらいなのかなと思ったりしますが。

MappingCharFilterFactoryの使い方は、


<charFilter class="solr.MappingCharFilterFactory" mapping="mapping.txt"/>

というようにマッピング用の定義ファイル(mapping.txt)を指定します。

mapping.txtは、下記のように変換ルールを定義します。


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

上記の例は、全角の数字を半角に変換するルールを書いています。

これにより、全角数字でも半角数字でも同じ検索結果を返せるようになったりします。

もう1つの効用として、トークナイザに形態素解析(solr.JapaneseTokenizerFactory)を使っている場合、下図のように全角数字はトークンを1つ1つに分解してしまうようで、事前に半角数字に変換することでトークナイザーに対して正しいトークンとして認識させることができたりします。


SolrAnylyze-1


charFilterはこのように文章をトークンに分割する際のルールを定義するもののため、tokenizer要素より前に指定する必要があります。
fiter要素とあわせるとその指定できる順序は、charFilter → tokenizer → filterという順番になります。


<fieldType name="text_ja" class="solr.TextField">
<analyzer type="index">
<charFilter class="solr.MappingCharFilterFactory" mapping="mapping.txt"/>
<tokenizer class="solr.JapaneseTokenizerFactory" mode="search" userDictionary="lang/userdict_ja.txt"/>
<filter class="solr.SynonymFilterFactory" synonyms="synonyms_index.txt" ignoreCase="true" expand="true"/>
</analyzer>
</fieldType>


フィルタの種類とその用途


本題のSolrのフィルタの種類ですが、下記のようなものがあります(一部です)。

先に書いたように、フィルタはトークナイザの種類によって使えるものと使えないものがあったりして、ここで列挙しているのは形態素解析(solr.JapaneseTokenizerFactory)を使っている場合に使えるフィルタですので注意してください。

あまり情報が無かったりして検証結果で書いている部分もあるので適当なところがあるかもしれません。


・ solr.SynonymFilterFactory


類語を登録できるフィルタです。


<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>

元々サンプルファイルがあるのでその中を見ればわかりやすいのですが、


aaafoo => aaabar
GB,gib,gigabyte,gigabytes

というように、「aaafoo」という単語を「aaabar」に置換したり、「GB」と「gigabyte」を同じ意味になるように定義しています。


SolrAnalyze-2


上記のようにSF(SynonymFilter)でaaafooがaaabarに置き換えられていることがわかります。

同義語や略語を登録したいという場合に便利だったりします。

ただ、英語の場合は一綴りで書いた単語はトークンが1つと認識してくれるのでよいですが、日本語を扱う場合は注意が必要でトークナイザがトークンに分割する際に同義語に定義した単語がそもそもきちんと認識してくれないケースがあったりします。


情報システム部,情シス

というような定義をしていてもトークナイザが下記のようなトークンに分割してしまい、「情報システム部」の同義語を登録していても正しく認識されません(「情シス」という単語も同様)。


SolrAnalyze-3


こういった場合は、事前に辞書データ(lang/userdict_ja.txt)にこれらの単語を登録してSolrに認知させる必要があります。


・ solr.JapaneseBaseFormFilterFactory


動詞とかを基本形に直してくれるフィルタです。


<filter class="solr.JapaneseBaseFormFilterFactory"/>

例えば「動いた」を解析してみると


SolrAnalyze-4


のような結果が返ってきます。

まぁ、取りあえず日本語使う場合は使っておけって言うフィルタですかね。


・ solr.JapanesePartOfSpeechStopFilterFactory


余計な品詞を検索対象にしないためのフィルタです。


<filter class="solr.JapanesePartOfSpeechStopFilterFactory" tags="lang/stoptags_ja.txt" enablePositionIncrements="true"/>

設定ファイルを見てみると助詞や記号などを除外するようにしているみたいです。


・ solr.CJKWidthFilterFactory


全角の英字を半角にしたり、半角カタカナを全角にするフィルタです。

全角の数字は対象になっていないようで、先に書いたMappingCharFilterFactoryを事前に通すといった処理が必要です。


<filter class="solr.CJKWidthFilterFactory"/>

Solrの管理機能で解析してみると半角カナの場合は確かに全角に変換されてヒットしている表示になるのですが、全角大文字の英字になると半角に変換されているようですがヒットしているようには表示されません(全角でも小文字の英字だとヒットしているように表示される)。

ただ、その他のフィルタの文字を見るときちんと半角に変換された英字が対象になっているので、機能としてはきちんと働いており単に表示の不備なのかもしれません。


・ solr.StopFilterFactory


名前の通り、インデックスさせたくない単語を登録できるフィルタです。

「て」「に」「を」「は」といった助詞や、「によって」「において」「に関して」など要は検索する上では邪魔になる単語を排除してくれます。


<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ja.txt" />


オプションのignoreCaseは英字の大文字小文字を区別するかどうかというものになります。

このフィルタは、もちろん検索されたくない、インデックスさせたくないといったNGワードを登録することもできます。

例えば、「itboy」をNGワードとして登録しておき、「itboyさんは素敵です」の検索結果は下記のようになります。


SolrAnalyze-5


見事に消されているのがわかります。


・ solr.JapaneseKatakanaStemFilterFactory


カタカナの長音(ー)を消してくれるフィルタです。

「コンピューター」と「コンピュータ」など人によって使い方が違ってくる言葉を統一してくれます。


<filter class="solr.JapaneseKatakanaStemFilterFactory" minimumLength="4"/>

オプションのminimumLengthは対象とする最大文字数を指定するもので、上記の場合4文字以上が対象となるため、「ソニー」が「ソニ」になることはありません。


SolrAnalyze-6


・ solr.JapaneseReadingFormFilterFactory


日本語の読みを検索対象にするためのフィルタです。

例えば、「日本」に対して「にっぽん」でも「ニッポン」でも読み方に対してヒットさせることができたりします。

(「日本」は「ニッポン」で登録されているため、キーワードが「ニホン」ではヒットしません。これをヒットさせたい場合、SynonymFilterFactoryにて類語登録をしておけばヒットさせることができます)


<filter class="solr.JapaneseReadingFormFilterFactory" useRomaji="false"/>

オプションのuseRomajiはローマ字も読みの対象にするか指定するもので先の例で言えば、「nippon」でもヒットさせることができるようになります。


・ solr.ICUTransformFilterFactory


カタカナを平仮名に変換できたりするフィルタですが、先ほどのJapaneseReadingFormFilterFactoryでも同じようなことができるのであまり詳しく調べてません。


<filter class="solr.ICUTransformFilterFactory" id="Katakana-Hiragana"/>

ちなみにこのフィルタはそのままだと使えないので、下記のようにライブラリをSolrへ事前にロードさせる必要があります。


まず、使いたいSolrコアのディレクトリ以下にlibディレクトリを作っておきます。

次に、そのlibディレクトリに下記のjarファイルをコピーします。


$ cp /path/to/solr/contrib/analysis-extras/lib/icu4j-49.1.jar /path/to/solr/example/solr/coreName/lib/
$ cp /path/to/solr/contrib/analysis-extras/lucene-libs/lucene-analyzers-icu-4.6.1.jar /path/to/solr/example/solr/coreName/lib/

最後にSolrを再起動します。


・ solr.LowerCaseFilterFactory


こちらは、英字を小文字にすることで大文字・小文字を使い分けた表記ゆれを統一することができるフィルタです。


<filter class="solr.LowerCaseFilterFactory"/>

「solr」でも「SOLR」でも「Solr」でもヒットさせることができるようになります。



フィルタは結構数が多いですし、Javaが書けたら自作もできるようですので色んな有識者が作成したものが公開されていたりします。

検索の用途や精度に応じて色々試してみたら実現したい検索システムを手早く作れるかもしれません。