Solrの困惑み方
・Solrで悩んだんだよというお話
初めてSolrというものを触り、データの作成からUI作成まで一通り行ったので、そのうえで困ったとか、悩んでうーんうーん言ってたことを書き連ねてみようと思います。
1:Solrドキュメントの少なさ
なんか少ないんですよね。ちゃんと言えば、「日本語ドキュメント」が少ない。海外ではJIRAチケットだったり掲示板だったりで悩み書いてたり情報があったりするんですけど。
技術評論社のApache Solr入門を片手にうーんうーん言ってたりして。でも結局最後には海外で同じようなミスをしてる人の悩みを見てやっとわかったーってなった時には結構な時間割いてたり。
「日本でのドキュメントが少ないのはなんでだろう」って考えたんですけど、実は日本語ドキュメントもそこそこあるんだけど、問題はこう、初心者が悩むような悩みの対処が書いてないからではと思ったりしました。プログラムもあんまよく分からないひとがSolrさわってみよーとかならないんですね、きっと。
だから少しずつ、なんか書いて良ければと思います。
2:optimizeの必要性
Solrの機能の一つ、optimize機能。
Apache Solr入門のP266には「Solrはcommitのたびに一群11個のファイルを作成する。なので、commitを細かくし過ぎるとインデクスとして多くのファイルを使うようになるので、パフォーマンスとかファイルディクリプタに悪影響」と、いう話が書かれています。そのあと、続けて「目安としては5commitに一回optimizeしよう」と書いてます。
僕にとってはApatch Solr入門はバイブルのようなものだったので、へーそうなんだーと思っていました。
ところが、いろいろ見てみると下記サイトでは「optimize自体が高負荷。5commitに一回はインデクスサイズが小さい時ならいいけど、そうじゃないときはもっと頻度下げよう」という話が書いてあります。
http://aoking.hatenablog.jp/entry/20120809/1344507896
optimizeの頻度は結構時と場合によって変えなきゃいけないんだなというのがわかったところで、じゃぁ今のこの僕の検索システムではどれくらいが適切なんだ?と悩みました。
Solrの有識者の方に意見をうかがってみると、以下のようなアドバイスをいただきました。
・インデックスは1日1回更新とか小さいサイズでなければ optimizeしないほうがよい
・少なくとも Solr 4 以降は 通常の セグメントマージ(インデックスのセグメントをmergeFactorの数の中で適当にする)で適当にされるので, optimize は特にしなくていいらしい(https://twitter.com/kojisays/status/197863133119909888)
ということで、今回はoptimizeは明示的に行わない方向で結論となりました。
3:再インデキシング時の罠
schema.xmlについて、あるfieldをtype:Aで定義してました。
<field name="name" type="string" indexed="true" stored="true" />
この定義で、1度インデキシングを行いました。
その後、そのfieldについてtype:Bで定義しなおしました。
<field name="name" type="2-gram" indexed="true" stored="true" />
この時、インデキシングし直すときに、前のインデキシングしたデータを消さずに再インデキシングしてしまうと、このfieldについて検索したときに、トークナイズできないよとか、サーバーに言われます。例えばこんな感じ
SEVERE: java.lang.IllegalStateException: field "name" was indexed without position data; cannot run PhraseQuery (term=210)
僕はこれの原因がトークナイザの設定にあるもんだとばかり思っていたため、トークナイザを変更してはうまくいかない、うーんうーんと言っていたわけです。
しかも、利用していたのがn-gramでのトークナイズを行う NGramTokenizerFactory だったり、WhiteSpaceTokenizer + LowerCaseFilterFactory + NGramFilterFactory だったりしたわけないんですが、こいつらも実は問題を持っていて、そのせいなのかなーうーむと首をかしげる時間が長かったです。
http://moyolab.blog57.fc2.com/blog-entry-90.html
http://sharp-m.hatenablog.com/entry/2013/05/21/014403
しかしいろいろ検索しているうちに、以下の投稿を見つけました。
Did you maybe index the initial data with different field types and then change to the current field types, say "string" and then move to "text_..."?
If so, simply delete the index and re-index.
(意訳)「もしかしてお前、前に別タイプでインデキシングしてないか?それなら消してから再インデキシングしろよ」
そうだ、消して無かったー。
なので、インデクスを消してから再インデキシングされるとちゃんと検索できました。
・終わりに
僕が始めてSolrで全文検索システムを構築したときに悩んだ三つをあげてみました。
同じように悩んでいる人が少しでもすぐに答えを見つけてモヤモヤを脱出できることを願います。