現在、使用している3.6から4.6にバージョンアップしようと思い、移行を進めていたところ、NGramFilterFactoryの挙動がバージョン間で異なっていたので簡単に調べてみた。
schema.xmlは、次のように修正した。
<fieldType name="text_general" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="true">
<analyzer>
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.NGramFilterFactory" minGramSize="2" maxGramSize="2"/>
</analyzer>
</fieldType>
3.6.2
<str name="querystring">name:こぶくろ</str>
<str name="parsedquery">PhraseQuery(name:"こぶ ぶく くろ")</str>
4.2.1
<str name="querystring">name:こぶくろ</str>
<str name="parsedquery">PhraseQuery(name:"こぶ ぶく くろ")</str>
4.3.1
<str name="querystring">name:こぶくろ</str>
<str name="parsedquery">PhraseQuery(name:"こ ぶ く ろ こぶ ぶく くろ")</str>
4.5.1
<str name="querystring">name:こぶくろ</str>
<str name="parsedquery">(name:こぶ name:ぶく name:くろ)/no_coord</str>
4.6.1
<str name="querystring">name:こぶくろ</str>
<str name="parsedquery">(name:こぶ name:ぶく name:くろ)/no_coord</str>
4.5.1から、autoGeneratePhraseQueries="true" にしても、BooleanQueryになってしまっている。4.3.1は、PhraseQueryになっているものの、minGramSizeが無視されているような結果だ。
さて、どうするか。Solr4.4以降のNGramTokenizeeFactoryは、フィールドの文字列長が1024バイトを超えてもトークナイズをするように、不具合修正されているとのことなので、それを使ってみることに。
(@johtaniさんから助言いただきました)
改めて、4.6.1のschema.xmlは、次のように修正した。
<fieldType name="text_general" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="true">
<analyzer>
<tokenizer class="solr.NGramTokenizerFactory" minGramSize="2" maxGramSize="2"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
4.6.1
<str name="querystring">name:こぶくろ</str>
<str name="parsedquery">PhraseQuery(name:"こぶ ぶく くろ")</str>
期待した結果(PhraseQuery)となるが、WhitespaceTokenizerFactoryからトークナイザが変更されているため、これまでと一緒と言うわけにはいかない。そのため、検索結果の検証が必要。しばらく、動作検証してみる。
3.6から4.6にバージョンアップして驚いたのが、インデックスの圧縮率の高さ。42GBあったインデックスが36GBまで圧縮された。WhitespaceTokenizerFactoryのときは、27GBまで圧縮されていた。(NGramTokenizerで仕方がないが、増加したのは残念)これだけでも、4.6系が使いたかったので、どうにか活路が見つかって一安心した。autoGeneratePhraseQueriesを指定しても、PhraseQueryにならなかったときは、相当焦った。
Solrでの全文N-Gram検索は、NGramTokenizerFactoryを使用するということになりそうだ。