0

私はそれを働かせることができません。私はこのクエリを使用しています:

my $user_questions 
    = RoseDB::UserSecurityQuestion::Manager->get_user_security_questions(
        query        => [
                          'user.username' => $username,
                        ],
        with_objects => ['User','SecurityQuestion'],
        sort_by      => 'RAND()',
        limit        => 2,
    );

Rose::DB::Object::Manager でデバッグをオンにすると、order 句が次のようになっていることがわかります。

ORDER BY t1.id, RAND()

それはどこt1.idから来ているのですか?そして、どうすれば を正しいものに修正できるORDER BYでしょRAND()うか?

4

1 に答える 1

3

パラメータドキュメントsort_byから:

「1 対多」または「多対多」の関係によって関連付けられているサブオブジェクトを (require_objects または with_objects を介して) 選択する場合、並べ替え順序句の最初の条件は、プライマリ テーブル (t1) の列である必要があります。この条件が満たされない場合、主キー列のリストがソート順句の先頭に自動的に追加されます。

これは、サブオブジェクトをその親オブジェクトに正しく関連付けるために必要です。

この動作をオーバーライドしたい場合は、(まだ文書化されていない) no_forced_sortboolean パラメータを使用できます。

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ます。

于 2009-07-29T12:28:18.760 に答える