Solr同梱のRandomSortFieldは乱数シードが同じでもインデックス更新でソート順がリセットされることはこちらの記事で書きました。
SolrのRandomSortFieldはシード値変更以外でも順番が変わる - Qiita
このままだと頻繁にインデックス更新が走るような運用では使いにくいので、インデックス更新に影響されないランダムソートプラグインを作りました。またこれを実際に使っているサービスでは一定期間ごとにソート順を更新しているので、その仕様もSolr側で吸収すべくシード値を変更しなくても指定した時間にソート順をリセットする仕組みも作りました。
PeriodicalRandomSortField
このPeriodicalRandomSortFieldを使えば、クライアント側でソート順更新のタイミングを管理できます。またクライアント側でプログラムを書かなくても、一定時間が経ったら自動的にソート順を更新してくれます。
GitHub - deltam/PeriodicalRandomSortField
インストール
jdk >= 1.6
solr >= 4.0.0
README.mdの繰り返しになっちゃうので書きません。基本的に以下のReleaseからJARを持ってきてsolrconfig.xml
にロードの設定を追加してコアをRELOADすればOKです。
Releases · deltam/PeriodicalRandomSortField
使い方
schema.xml
に次の2行を付け足しときます。
<fieldType name="prandom" class="com.bengo4.solr.schema.PeriodicalRandomSortField" indexed="true" />
<dynamicField name="prandom_*" type="prandom" />
インデックス更新に影響されないランダムソートとして使う
ソート条件をprandom_1234 asc
として検索してみます。
この使い方だと常に同じランダムソート順が使われます。シード値の1234
を変えない限り同じソート順になります。(Solr同梱のRandomSortFieldだとインデックス更新でソート順が変わります。)
定期更新機能と合わせて使う
たとえば検索するときにソート条件をprandom_1234_10h,15h asc
と設定します。
この場合は、
-
1234
を乱数シードとして - 今日の0時から10時間後と15時間後にソート順を更新する
ランダムソートとして機能します。(10時と15時以外はインデックス更新をしてもランダムソート順は変わりません)
時間単位ではなく分単位も指定できます。sort=prandom_1234_30m,1h,90m asc
は0時30分、1時ちょうど、1時30分にランダムソートが更新されます。
時間と分を混ぜる10h30m
みたいな書き方はまだできません(需要があったら作るかも)。
定期更新の開始時刻も指定する
何も指定しないと本日午前0時0分を開始時刻として使いますが、UNIXTIMEでその時刻を指定できます。(これは例えば1日単位ではなく1週間単位で更新時刻をバラバラに指定したい場合などに使えると思います。)
prandom_1234_10h,15h_1427493600 asc
と書くと(1427493600=2015年3月28日午前7時0分)、ソート順更新は17時と22時にずれ込みます。
実際に使うときの注意点
- queryResultCache
PeriodicalRandomSortFieldではソート順が更新される時刻になっても、見た目上クエリ文字列が変わらないのでキャッシュが効いたままになり、新しいソート順にならないことがあります。だからといってキャッシュを切るのも現実的でないので、次のような工夫をしています。
sort=prandom_1234_10h,15h asc, prandom_1427508000 asc
どういうことかというと、2番めのprandomのシード値は1時間毎のUNIXTIMEです。これはクライアント側でクエリを投げるときにその時刻の分を切り捨てて付け足しています。
もし時刻更新のタイミングが時間単位なら2番めのprandomのクエリ文字列が変わるタイミングでソート順も更新されるので、queryResultCacheの影響を受けずにソート順が更新されます。
…どうみても バッドノウハウ です。ほんとうにありがとうございました。
PeriodicalRandomSortFieldの内部からはキャッシュの仕組みに手が出せないので、こうなっちゃうんですよね。何かいいHackを知っている方がおりましたら教えて下さい!!
まとめ
- 頻繁に更新が走る運用のSolrでも安定して使えるランダムソートプラグインを作りました
- 時刻を指定して更新する機能もついてます。
- 実際に使うには少しだけバッドノウハウが必要でさーせん。
おわり。