How to select randomly with doctrine

前端 未结 13 955
耶瑟儿~
耶瑟儿~ 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:26

    Why not to use repository?

    <?php
    
    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');
    
            # make query
            return $this->getEntityManager()->createNativeQuery("
                SELECT p.id FROM {$table} p ORDER BY RAND() LIMIT 0, {$amount}
            ", $rsm);
        }
    }
    
    0 讨论(0)
  • 2020-11-27 20:26

    For me, the most useful way was to create two arrays where i say order type and different properties of the Entity. For example:

        $order = array_rand(array(
            'DESC' => 'DESC',
            'ASC' => 'ASC'
        ));
    
        $column = array_rand(array(
            'w.id' => 'w.id',
            'w.date' => 'w.date',
            'w.name' => 'w.name'
        ));
    

    You could add more entries to array $column like criteria.

    Afterwards, you can build your query with Doctrine adding $column and $order inside ->orderBy. For example:

    $query = $qb->select('w')
    ->from('DbEntities\Entity\Word', 'w')
    ->where('w.indictionary = 0 AND w.frequency > 3')
    ->orderBy($column, $order)
    ->getQuery()
    ->setMaxResults(100);
    

    This way improved the performance of my application. I hope this helps someone.

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

    Follow these steps:

    Define a new class at your project as:

    namespace My\Custom\Doctrine2\Function;
    
    use Doctrine\ORM\Query\Lexer;
    
    class Rand extends \Doctrine\ORM\Query\AST\Functions\FunctionNode
    {
    
        public function parse(\Doctrine\ORM\Query\Parser $parser)
        {
            $parser->match(Lexer::T_IDENTIFIER);
            $parser->match(Lexer::T_OPEN_PARENTHESIS);
            $parser->match(Lexer::T_CLOSE_PARENTHESIS);
        }
    
        public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
        {
            return 'RAND()';
        }
    }
    

    Register the class config.yml:

    doctrine:
         orm:
             dql:
                 numeric_functions:
                     Rand: My\Custom\Doctrine2\Function\Rand
    

    Use it directly as:

    $qb->addSelect('RAND() as HIDDEN rand')->orderBy('rand()'); //Missing curly brackets
    
    0 讨论(0)
  • 2020-11-27 20:28

    Or you could do this -->

    $words = $em->getRepository('Entity\Word')->findAll();
    shuffle($words);
    

    Of course this would be very inefficient if you have many records so use with caution.

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

    First get the MAX value from DB table & then use this as offset in PHP i.e $offset = mt_rand(1, $maxId)

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

    In line with what Hassan Magdy Saad suggested, you can use the popular DoctrineExtensions library:

    See mysql implementation here: https://github.com/beberlei/DoctrineExtensions/blob/master/src/Query/Mysql/Rand.php

    # config.yml
    
    doctrine:
         orm:
             dql:
                 numeric_functions:
                     rand: DoctrineExtensions\Query\Mysql\Rand
    

    Tested in Doctrine ORM 2.6.x-dev, you can then actually do:

    ->orderBy('RAND()')
    
    0 讨论(0)
提交回复
热议问题