如何用教义随机选择

2022-08-30 12:07:37

以下是我查询数据库以获取一些单词的方法

$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,因此您可以随机化主键。但是,在我的情况下无法做到这一点,因为我有一个搜索条件和一个where子句,因此不是每个主键都满足该条件。

我还发现了一个代码片段,建议您使用 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之后添加偏移量。

任何想法如何做到这一点?


答案 1

Doctrine 团队不愿意实现此功能

您的问题有几种解决方案,每种方法都有其自身的缺点:

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

答案 2

请按照下列步骤操作:

在项目中定义一个新类::

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()'); //Missing curly brackets

推荐