2009-07-29 4 views
0

Je ne peux pas le faire fonctionner. J'utilise cette requête:Pourquoi Rose :: DB :: Object sort_by RAND() fait ce que j'attends?

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

Quand je tourne dans le débogage Rose :: DB :: Object :: Gestionnaire, je vois que la clause d'ordre est:

ORDER BY t1.id, RAND() 

Où est-ce t1.id provenir de? Et aucune idée comment je peux corriger le ORDER BY pour être juste RAND()?

Répondre

3

De l'documentation for the sort_by parameter:

Si la sélection de sous-objets (via require_objects ou with_objects) qui sont liés par « un à plusieurs » ou « plusieurs à plusieurs » rapports, la première condition dans la clause de l'ordre de tri doit être une colonne dans la table primaire (t1). Si cette condition n'est pas remplie, la liste des colonnes de clé primaire sera ajoutée au début de la clause d'ordre de tri automatiquement.

Ceci est nécessaire pour associer correctement des sous-objets à leurs objets parents.

Si vous souhaitez remplacer ce comportement, vous pouvez utiliser le paramètre booléen no_forced_sort (non encore documenté).

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

Mais il est fort probable que cela entraînera des sous-objets à associer les objets parent incorrect. Ce dont vous aurez besoin pour faire ce travail est une sorte qui est basée de façon déterministe sur une caractéristique unique de t1, mais qui est autrement aléatoire. Autrement dit, somefunc(t1.id) serait aléatoire mais retournerait toujours le même résultat pour une valeur donnée de t1.id, en gardant tous les enfants avec les bons parents.

Une évidente (et probablement beaucoup plus pragmatique) approche consiste à chercher toutes les questions de sécurité pour l'utilisateur $username et puis juste au hasard choisir deux:

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)); 
} 

Maintenant, vous avez votre (maximum) NUM_RANDOM_QUESTIONS au hasard questions sélectionnées au @questions.

+0

Merci John. Plus je creuse dans votre travail, plus je l'apprécie. Puisqu'il y a un maximum de 5 questions, je pense que cette approche est acceptable dans ce cas. Peut-être qu'un jour j'obtiendrai tout ce qu'il y a dans les modules (beaucoup de choses à faire quand même :) – cliveholloway

Questions connexes