2011-09-17 22 views
9

Me pregunto cómo obtener un número aleatorio de Miembros de un Grupo, pero no sé cuál es la mejor manera de hacerlo, y creo que ORDER BY RAND() no es la mejor alternativa, ya que un Grupo puede tener más de 100,000 Miembros, realizar este tipo de consultas podría ser muy lento.Obtenga registros aleatorios con Doctrine

He encontrado esta manera de hacer uso de SQL, pero no saben cómo hacer lo mismo en DQL: How can i optimize MySQL's ORDER BY RAND() function?

+1

Posible duplicado de [Cómo seleccionar al azar con la doctrina] (http://stackoverflow.com/questions/10762538/how-to-select-randomly-with-doctrine) –

Respuesta

0

No estoy al tanto de ninguna manera a la orden por RAND() "eficiente" de Doctrina. En su situación, lo mejor es, probablemente, obtener primero claves primarias, barajar estas claves y luego hacer uso de ellas dentro de una instrucción IN.

También podría agregar una capa de almacenamiento en caché donde poner (un subconjunto de) las claves de la primera consulta, especialmente si tiene muchos registros, para evitar repetir la consulta en las claves cada vez.

4

Puede usar la consulta que encontró para recuperar eficientemente los identificadores de N registros aleatorios a través de una consulta SQL nativa, luego hacer una consulta de doctrina para buscar los objetos a través de un WHERE IN(...) usando dql.

Ejemplo:

// fetch $randomIds via native sql query using $em->getConnection()->... methods 
// or from a memory based cache 

$qb = $em->createQueryBuilder('u'); 

$em->createQuery(' 
    SELECT u 
    FROM Entity\User 
    WHERE ' . $qb->expr()->in('u.id', $randomIds) . ' 
'); 

La misma estrategia se aplica si usted lo trae las identificaciones aleatorias de una memoria caché (como redis, tal vez usando SRANDMEMBER) - en primer lugar buscar los identificadores de, a continuación, ir a buscar las entidades a través de un WHERE IN.

Sólo hay que asegurarse de que sus identificadores de caché están en sincronía con la base de datos (IDS eliminados se quitan de la base de datos y de la memoria caché, etc.)

+0

Tengo una observación. Obtener los ids a través de la consulta SQL nativa usando '$ em-> getConnection() -> ...' o vía '$ em-> createQuery ('... SQL query ...')' no es lo mismo para ¿tú? – JeanValjean

12

Para no disminuir actuaciones en general que hago de la siguiente manera:

//Retrieve the EntityManager first 
$em = $this->getEntityManager(); 

//Get the number of rows from your table 
$rows = $em->createQuery('SELECT COUNT(u.id) FROM AcmeUserBundle:User u')->getSingleScalarResult(); 

$offset = max(0, rand(0, $rows - $amount - 1)); 

//Get the first $amount users starting from a random point 
$query = $em->createQuery(' 
       SELECT DISTINCT u 
       FROM AcmeUserBundle:User u') 
->setMaxResults($amount) 
->setFirstResult($offset); 

$result = $query->getResult(); 

Por supuesto, los usuarios $amount objeto que va a recuperar son consecutivas (es decir, el i, (i + 1) -ésimo, ..., (i + $amount) -ésimo), pero por lo general no existe la necesidad de tomar una o dos entidades al azar, no toda la lista. Por lo tanto, creo que esta es una alternativa efectiva.

+0

También puede usar un fn numérico personalizado o DoctrineExtensions Lib como [alternativa] (http://digitalfortress.tech/php/get-random-rows-in-doctrine/). –

Cuestiones relacionadas