パラメータのドキュメントsort_by
から:
「1 対多」または「多対多」の関係によって関連付けられているサブオブジェクトを (require_objects または with_objects を介して) 選択する場合、並べ替え順序句の最初の条件は、プライマリ テーブル (t1) の列である必要があります。この条件が満たされない場合、主キー列のリストがソート順句の先頭に自動的に追加されます。
これは、サブオブジェクトをその親オブジェクトに正しく関連付けるために必要です。
この動作をオーバーライドしたい場合は、(まだ文書化されていない) no_forced_sort
boolean パラメータを使用できます。
my $user_questions =
RoseDB::UserSecurityQuestion::Manager->get_user_security_questions(
...
sort_by => 'RAND()',
no_forced_sort => 1);
ただし、これにより、サブオブジェクトが誤った親オブジェクトに関連付けられる可能性が高くなります。これを機能させるために必要なのは、t1 の固有の特性に基づいて決定論的にソートすることですが、それ以外はランダムです。つまり、somefunc(t1.id)
ランダムになりますが、t1.id の特定の値に対して常に同じ結果を返し、すべての子を正しい親に保ちます。
明らかな (そしておそらくもっと実用的な) アプローチは、ユーザーのすべてのセキュリティ質問を取得してから、$username
ランダムに 2 つを選択することです。
my $user_questions =
RoseDB::UserSecurityQuestion::Manager->get_user_security_questions(
query => [ 'user.username' => $username ],
with_objects => ['User','SecurityQuestion']);
use constant NUM_RANDOM_QUESTIONS => 2;
my @questions;
for(1 .. NUM_RANDOM_QUESTIONS)
{
last unless(@$user_questions);
push(@questions, splice(@$user_questions, int(rand(@$user_questions)), 1));
}
これで、(最大)NUM_RANDOM_QUESTIONS
ランダムに選択された質問が にあり@questions
ます。