LoginSignup
3
3

More than 5 years have passed since last update.

更新が多い運用でも使いやすいSolrのランダムソートプラグインを作りました

Last updated at Posted at 2015-03-28

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行を付け足しときます。

schema.xml
    <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でも安定して使えるランダムソートプラグインを作りました
  • 時刻を指定して更新する機能もついてます。
  • 実際に使うには少しだけバッドノウハウが必要でさーせん。

おわり。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3