为什么不是Rose :: DB :: Object sort_by RAND()做我期望的事情?

时间:2009-07-29 08:30:59

标签: perl rose-db-object

我无法让它发挥作用。我正在使用此查询:

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()

1 个答案:

答案 0 :(得分:3)

来自documentation for the sort_by parameter

如果选择通过“一对多”或“多对多”关系相关的子对象(通过require_objects或with_objects),则排序顺序子句中的第一个条件必须是主表中的一列(t1) 。如果不满足此条件,主键列列表将自动添加到排序顺序子句的开头。

这是为了将子对象与其父对象正确关联所必需的。

如果您想覆盖此行为,可以使用(尚未记录的)no_forced_sort布尔参数。

my $user_questions =
  RoseDB::UserSecurityQuestion::Manager->get_user_security_questions(
    ...
    sort_by        => 'RAND()',
    no_forced_sort => 1);

但是很可能这会导致子对象与不正确的父对象相关联。你需要做的工作是确定性地基于t1的独特特征,但在其他方面是随机的。也就是说,somefunc(t1.id)将是随机的,但是对于给定的t1.id值,它总是返回相同的结果,使所有孩子都拥有正确的父母。

明显(可能更实用)的方法是为用户$username获取所有安全问题,然后随机选择两个:

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个{{1}}个问题。