Почему Rose::DB::Object sort_by RAND() не выполняет то, что я ожидаю?
Я не могу заставить его работать. Я использую этот запрос:
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 ответ
Из документации для sort_by
параметр:
При выборе подобъектов (через 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
,