如何随机select教条

这里是我如何查询我的数据库的一些单词

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

我正在使用mysql,我想要得到符合条件的随机行,我会在我的查询中使用rand()命令。

我发现这个类似的问题基本上是由于ORDER BY RAND在原理中是不支持的,你可以把主键改为随机的。 但是,这不能在我的情况下完成,因为我有一个search条件和一个where子句,以便不是每个主键都将满足该条件。

我还发现了一个代码片断 ,build议您使用OFFSET来像这样随机化行:

 $userCount = Doctrine::getTable('User') ->createQuery() ->select('count(*)') ->fetchOne(array(), Doctrine::HYDRATE_NONE); $user = Doctrine::getTable('User') ->createQuery() ->limit(1) ->offset(rand(0, $userCount[0] - 1)) ->fetchOne(); 

我有点困惑,这是否会帮助我解决在我的情况下是否随意支持秩序的问题。 我无法在setMaxResult之后添加偏移量。

任何想法如何可以完成?

该学说团队不愿意实现这个function 。

你的问题有几种解决scheme,每个都有自己的缺点:

  • 添加一个自定义数字函数 :参见这个DQL RAND()函数
    (如果你有很多匹配的行可能会很慢)
  • 使用本机查询
    (我个人试图避免这个解决scheme,我发现很难维护)
  • 首先发出一个原始的SQL查询以随机获得一些ID,然后使用DQL WHERE x.id IN(?)加载关联的对象,通过传递ID数组作为参数。
    这个解决scheme涉及到两个单独的查询,但是可能会比第一个解决scheme有更好的性能(其他原始SQL技术比ORDER BY RAND()存在,我不会在这里详细介绍,你会发现这个网站有一些很好的资源)。

按着这些次序:

在您的项目中定义一个新的类,如下所示:

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

注册类config.yml

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

直接使用它:

 $qb->addSelect('RAND() as HIDDEN rand')->orderBy('rand'); 

或者你可以这样做 – >

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

当然,如果你有很多logging的话,这样做效率很低,所以要谨慎使用。

Doctrine 2不支持ORDER BY rand(),但是我发现这篇文章里包含了这个问题的修复。

为什么不使用存储库?

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

根据Hassan Magdy Saad的build议 ,您可以使用受欢迎的DoctrineExtensions库:

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

经过ORM 2.6.x-dev的学习testing,你可以做到:

 ->orderBy('RAND()') 

可以对查询(数组)结果进行混洗,但混洗不会随机选取。

为了从实体中随机select,我更喜欢在PHP中这样做,这可能会减慢随机选取的速度,但是它使我能够控制testing我正在做的事情,并使最终的debugging更容易。

下面的例子将来自实体的所有ID放入一个数组中,然后我可以使用它来在php中“随意处理”。

 public function getRandomArt($nbSlotsOnPage) { $qbList=$this->createQueryBuilder('a'); // get all the relevant id's from the entity $qbList ->select('a.id') ->where('a.publicate=true') ; // $list is not a simple list of values, but an nested associative array $list=$qbList->getQuery()->getScalarResult(); // get rid of the nested array from ScalarResult $rawlist=array(); foreach ($list as $keyword=>$value) { // entity id's have to figure as keyword as array_rand() will pick only keywords - not values $id=$value['id']; $rawlist[$id]=null; } $total=min($nbSlotsOnPage,count($rawlist)); // pick only a few (ie$total) $keylist=array_rand($rawlist,$total); $qb=$this->createQueryBuilder('aw'); foreach ($keylist as $keyword=>$value) { $qb ->setParameter('keyword'.$keyword,$value) ->orWhere('aw.id = :keyword'.$keyword) ; } $result=$qb->getQuery()->getResult(); // if mixing the results is also required (could also be done by orderby rand(); shuffle($result); return $result; } 

我希望这会帮助其他人:

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

请注意这里的表格问题是一个AppBundle:问题实体。 相应地更改细节。 问题的数量取自编辑表单,请务必检查表单构build器的variables并相应地使用。

只需添加以下内容:

 ->orderBy('RAND()')