How to select randomly with doctrine

前端 未结 13 957
耶瑟儿~
耶瑟儿~ 2020-11-27 20:21

Here is how I query my database for some words

$query = $qb->select(\'w\')
    ->from(\'DbEntities\\Entity\\Word\', \'w\')
    ->where(\'w.indiction         


        
相关标签:
13条回答
  • 2020-11-27 20:39

    Just add the following:

    ->orderBy('RAND()')
    
    0 讨论(0)
  • 2020-11-27 20:40

    @Krzysztof's solution is IMHO best here, but RAND() is very slow on large queries, so i updated @Krysztof's solution to gives less "random" results, but they are still random enough. Inspired by this answer https://stackoverflow.com/a/4329492/839434.

    namespace Project\ProductsBundle\Entity;
    
    use Doctrine\ORM;
    
    class ProductRepository extends ORM\EntityRepository
    {
        /**
         * @param int $amount
         * @return Product[]
         */
        public function getRandomProducts($amount = 7)
        {
            return $this->getRandomProductsNativeQuery($amount)->getResult();
        }
    
        /**
         * @param int $amount
         * @return ORM\NativeQuery
         */
        public function getRandomProductsNativeQuery($amount = 7)
        {
            # set entity name
            $table = $this->getClassMetadata()
                ->getTableName();
    
            # create rsm object
            $rsm = new ORM\Query\ResultSetMapping();
            $rsm->addEntityResult($this->getEntityName(), 'p');
            $rsm->addFieldResult('p', 'id', 'id');
    
            # sql query
            $sql = "
                SELECT * FROM {$table}
                WHERE id >= FLOOR(1 + RAND()*(
                    SELECT MAX(id) FROM {$table})
                ) 
                LIMIT ?
            ";
    
            # make query
            return $this->getEntityManager()
                ->createNativeQuery($sql, $rsm)
                ->setParameter(1, $amount);
        }
    }
    
    0 讨论(0)
  • 2020-11-27 20:49

    I hope this would help others:

            $limit = $editForm->get('numberOfQuestions')->getData();
            $sql = "Select * from question order by RAND() limit $limit";
    
            $statement = $em->getConnection()->prepare($sql);
            $statement->execute();
            $questions = $statement->fetchAll();
    

    Note here the table question is an AppBundle:Question Entity. Change the details accordingly. The number of questions is taken from the edit form, make sure to check the variable for the form builder and use accordingly.

    0 讨论(0)
  • 2020-11-27 20:49

    I know this is an old question. But I used the following solution to get the random row.

    Using an EntityRepository method:

    public function findOneRandom()
    {
        $id_limits = $this->createQueryBuilder('entity')
            ->select('MIN(entity.id)', 'MAX(entity.id)')
            ->getQuery()
            ->getOneOrNullResult();
        $random_possible_id = rand($id_limits[1], $id_limits[2]);
    
        return $this->createQueryBuilder('entity')
            ->where('entity.id >= :random_id')
            ->setParameter('random_id', $random_possible_id)
            ->setMaxResults(1)
            ->getQuery()
            ->getOneOrNullResult();
    }
    
    0 讨论(0)
  • 2020-11-27 20:51

    Probably the easiest (but not necessarily the smartest) way to get a single object result ASAP would be implementing this in your Repository class:

    public function findOneRandom()
    {
        $className = $this->getClassMetadata()->getName();
    
        $counter = (int) $this->getEntityManager()->createQuery("SELECT COUNT(c) FROM {$className} c")->getSingleScalarResult();
    
        return $this->getEntityManager()
    
            ->createQuery("SELECT ent FROM {$className} ent ORDER BY ent.id ASC")
            ->setMaxResults(1)
            ->setFirstResult(mt_rand(0, $counter - 1))
            ->getSingleResult()
        ;
    }
    
    0 讨论(0)
  • 2020-11-27 20:52

    The Doctrine team is not willing to implement this feature.

    There are several solutions to your problem, each having its own drawbacks:

    • Add a custom numeric function: see this DQL RAND() function
      (might be slow if you have lots of matching rows)
    • Use a native query
      (I personally try to avoid this solution, which I found hard to maintain)
    • Issue a raw SQL query first to get some IDs randomly, then use the DQL WHERE x.id IN(?) to load the associated objects, by passing the array of IDs as a parameter.
      This solution involves two separate queries, but might give better performance than the first solution (other raw SQL techniques than ORDER BY RAND() exist, I won't detail them here, you'll find some good resources on this website).
    0 讨论(0)
提交回复
热议问题