Get random records with Doctrine

柔情痞子 提交于 2019-12-05 01:21:35

I'm not aware of any way to ORDER BY RAND() "efficiently" from Doctrine. In your situation, the best thing is probably to get primary keys first, shuffle these keys and then make use of them within an IN statement.

You could also add a caching layer where to put (a subset of) the keys from the first query, especially if you have many records, so to avoid repeating the query on keys each time.

To not decrease performances I generally do as follows:

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

Of course, the $amount users object you will retrieve are consecutive (i.e. the i-th, (i+1)-th,...,(i+$amount)-th), but usually there is the need of taking one or two entities at random, not the whole list. Hence, I think that this is an effective alternative.

You could use the query you found in order to efficiently retrieve the ids of N random records via a native sql query, then do a doctrine query in order to fetch the objects via a WHERE IN(...) using dql.

Example:

// 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) . '
');

The same strategy applies if you fetch random ids from a cache (like redis, maybe using SRANDMEMBER) - first fetch the ids, then fetch the entities via a WHERE IN.

You just have to make sure your cached ids are in sync with the database (deleted ids are removed from database and from cache etc.)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!