Solr による N-Gram 検索
日本語の文章に対して全文検索用のインデックスを作成する方法としては、形態素解析により分解した単語をインデックスする方法や、N-Gram によってインデックスを作成する方法などがあります。形態素解析はインデックスが小さく検索が早いこと、N-Gram は業界用語などの特定ドメインの言葉や日本語以外にも対応できて部分一致検索が可能であることなど、双方に利点があります。
今回は Solr を使用した N-Gram 系トークナイザーについて記述します。
設定方法
N-Gram 検索を行うには Solr コアの schema.xml
を開いてフィールド型を定義します。
<fieldtype name="text" class="solr.textField" positionIncrementGap="100"> <analyzer> <tokenizer class="solr.CJKTokenizerFactory"/> </analyzer> </fieldtype>
CJKTokenizerFactory
まず日本語を扱う場合によく使われている (と聞く) CJKTokenizerFactory
について。
これは文章内の CJK 統合漢字部分を N-Gram でインデックスし、アルファベット部分については単語単位でインデックスするというトークナイザーである。N-Gram はインデックスが巨大化する傾向があるため最小限のインデックスで済む。また大文字小文字の統一もこの中で行ってくれるので LowerCaseFilterFactory
を使わなくて済む。
全文検索(ぜんぶんけんさく、Full text search)とは、コンピュータにおいて、複数の文書(ファイル)から特定の文字列を検索すること。
[全文][文検][検索][ぜん][んぶ][ぶん][んけ][けん][んさ][さく][full][text][search][とは][コン][ンピ][ピュ ュー][ータ][タに][にお][おい][いて][複数][数の][の文][文書][ファ][ァイ][イル][から][ら特][特定][定の][の文][文字][字列][列を][を検][検索][索す][する][るこ][こと]
このため英単語に対しては完全一致の検索となる副作用がある。例えば「win」で検索しても「Windows」や「WinXP」がヒットしないという問題が発生する。このため、商品コードの一部で関連する文書を検索したいなどという場合には使うことができない。
NGramTokenizerFactory
続いて全文 N-Gram インデックスの NGramTokenizerFactory
について。このトークナイザーは CJK 統合漢字やアルファベット関係なく N-Gram でインデックスするため半角英数文字についても部分一致検索が可能。
全文検索(ぜんぶんけんさく、Full text search)とは、コンピュータにおいて、複数の文書(ファイル)から特定の文字列を検索すること。
[全文][文検][検索][索(][(ぜ][ぜん][んぶ][ぶん][んけ][けん][んさ][さく][く、][、F][Fu][ul][ll][l][ T][Te][ex][xt][t][ S][Se][ea][ar][rc][ch][h)][)と][とは][は、][、コ][コン][ンピ][ピュ][ュー][ータ][タに][にお][おい][いて][て、][、複][複数][数の][の文][文書][書(][(フ][ファ][ァイ][イル][ル)][)か][から][ら特][特定][定の][の文][文字][字列][列を][を検][検索][索す][する][るこ][こと][と。]
ただし、ここのコードを読む限り NGramTokenizerFactory は文章先頭の 1024 文字分 (ハードコードされた不変値) しかインデックス対象としてくれない。
たかだか 1024 文字では少し長いメールですぐに溢れてしまうわけだが、2008 年にバグ報告され未だ治っていないのはその気がないのだろう。このトークナイザーを使うなら 1024 文字以内のショートフィールド、または要件が文書の先頭のみで良い場合となる。
またこのトークナイザーが生成するトークンは大文字と小文字を区別するので LowerCaseFilterFactory と併せて使う必要がある。
全文 N-Gram 対応にするには
文書検索がしたい、アルファベット文字や数字も部分一致で検索がしたい、という場合はどうしたらよいかというと、結局のところ NGramFilterFactory
と WhitespaceTokenizerFactory
を組み合わせるという結論になる。またこれらの組み合わせでは大文字小文字が区別されてしまうため LowerCaseFilter
も併用する。
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.NGramFilterFactory" minGramSize="2" maxGramSize="2"/>
全文 N-Gram ではインデックスが大きくなるが、日本語がメインの文書であれば CJKTokenizerFactory でも英単語によるインデックス削減効果は期待できないので割りきろう。