Objectifyを使用して Google App Engine データストアからランダムな要素を取得するにはどうすればよいですか? エンティティのすべてのキーを取得して、それらからランダムに選択する必要がありますか、それともより良い方法がありますか?
4 に答える
保存するときに、各エンティティに0〜1の乱数を割り当てます。ランダムレコードをフェッチするには、0から1までの別の乱数を生成し、それより大きいランダム値を持つ最小のエンティティをクエリします。
オブジェクト化されたデータストアからいくつかのランダムな要素を選択することに関するこの投稿から引用:
ID が連続している場合、1 つの方法は、使用されていることがわかっている ID 範囲からランダムに 5 つの番号を選択することです。次に、「in」filter() でクエリを使用します。
5 つのエントリが隣接していてもかまわない場合は、count()、limit()、および offset() を使用して、5 つのエントリのブロックをランダムに見つけることができます。
それ以外の場合は、おそらく limit() と offset() を使用して、一度に 1 つのエントリをランダムに選択する必要があります。
-- ジョシュ
すべてを取得する必要はありません。例えば:
- countall = query(X.class).count() // http://groups.google.com/group/objectify-appengine/browse_frm/thread/3678cf34bb15d34d/82298e615691d6c5?lnk=gst&q=count#82298e615691d6c5
- rnd = 乱数を生成 [0..countall]
- ofy.query(X.class).order("- date").limit(rnd); //たとえば -date またはいくつかの慢性的なインデックス付きフィールド
- 最後のIDはあなたです...(平均して50%ファッチするか、少なくとも最初の読み取りが平均で50%少ない)
改善 (キャッシュ内のキー テーブルを小さくするため)!
最初に読み取った後、すべての X 要素を記憶します。キャッシュ ID とその位置。そのため、次回は選択した ID からさらに条件を照会します (最大 ".limit(rnd%X)" は X-1 になります)。
ランダムは単なるランダムです。100% 公平に近づける必要がない場合は、慢性的なフィールド値を推測します (たとえば、10 日間で 1000 レコードがある場合、ランダム 501 の場合、5 日目よりも大きい 2 番目の要素を選択します)。
その他のオプションとして、慢性的なフィールド日付 (または類似のもの) がある場合は、ランダムな日付よりも古く、ランダムな日付 + 1 よりも若い要素をフェッチします (最初の日付と最後の日付を知る必要があります)。次に、フェッチされたレコード間でランダムに選択します。クエリが空の場合は、より大きいものを選択します...