【问题标题】:MATCH AGAINST script is not working with Symfony2MATCH AGAINST 脚本不适用于 Symfony2
【发布时间】:2013-07-08 19:49:43
【问题描述】:

我尝试在我的 Symfony2 项目中设置这个类: http://xlab.pl/en/full-text-searching/(匹配部分)

这个类应该允许我使用 Match 来对抗这样的学说:

$searchResult =      $em->createQueryBuilder('uvaluo_user')
                                ->addSelect("MATCH_AGAINST (uvaluo_user.firstname, uvaluo_user.lastname, :name 'IN NATURAL MODE') as score")
                                ->add('where', 'MATCH_AGAINST (uvaluo_user.firstname, uvaluo_user.lastname, :name) > 0.8')
                                ->setParameter('name', $name)
                                ->getQuery()
                                ->getResult();

正如他们在网站上所说,我把它放在我的应用程序的 config.yml 中:

orm:
    auto_generate_proxy_classes: %kernel.debug%
    auto_mapping: true
    dql:
      string_functions:
        match_against: Uvaluo\UserBundle\Extension\Doctrine\MatchAgainstFunction

我有像这样的 MatchAgainstFunction 类

<?

namespace Uvaluo\UserBundle\Extension\Doctrine;

use Doctrine\ORM\Query\Lexer;
use Doctrine\ORM\Query\AST\Functions\FunctionNode;

/**
 * @example by https://gist.github.com/1234419 Jérémy Hubert 
 * "MATCH_AGAINST" "(" {StateFieldPathExpression ","}* InParameter {Literal}? ")"
 */
class MatchAgainstFunction extends FunctionNode {
//Content that I got in the website
}

最后,当我尝试我的代码时,我得到了以下错误:

[语义错误] 第 0 行,第 107 列“MATCH_AGAINST”附近:错误:未定义“MATCH_AGAINST”类。 500 内部服务器错误 - QueryException 1 个链接异常:QueryException »

你知道这是什么原因吗?

【问题讨论】:

    标签: php symfony doctrine dql


    【解决方案1】:

    根据这篇文章Extending DQL in Doctrine 2: User-Defined Functions

    config.yml:

    doctrine:
      orm:
        dql:
          string_functions:
            MATCH: My\Bundle\DQL\MatchAgainstFunction
    

    MatchAgainstFunction.php

    <?php
    
    namespace My\Bundle\DQL;
    
    use Doctrine\ORM\Query\AST\Functions\FunctionNode;
    use Doctrine\ORM\Query\Lexer;
    use Doctrine\ORM\Query\Parser;
    use Doctrine\ORM\Query\SqlWalker;
    
    /**
     * MatchAgainstFunction ::=
     *  "MATCH" "(" StateFieldPathExpression {"," StateFieldPathExpression}* ")" "AGAINST" "("
     *      StringPrimary ["BOOLEAN"] ["EXPAND"] ")"
     */
    class MatchAgainstFunction extends FunctionNode {
    
      /** @var array list of \Doctrine\ORM\Query\AST\PathExpression */
      protected $pathExp = null;
    
      /** @var string */
      protected $against = null;
    
      /** @var boolean */
      protected $booleanMode = false;
    
      /** @var boolean */
      protected $queryExpansion = false;
    
      public function parse(Parser $parser) {
        // match
        $parser->match(Lexer::T_IDENTIFIER);
        $parser->match(Lexer::T_OPEN_PARENTHESIS);
    
        // first Path Expression is mandatory
        $this->pathExp = array();
        $this->pathExp[] = $parser->StateFieldPathExpression();
    
        // Subsequent Path Expressions are optional
        $lexer = $parser->getLexer();
        while ($lexer->isNextToken(Lexer::T_COMMA)) { 
          $parser->match(Lexer::T_COMMA); 
          $this->pathExp[] = $parser->StateFieldPathExpression(); 
        }
    
        $parser->match(Lexer::T_CLOSE_PARENTHESIS);
    
        // against
        if (strtolower($lexer->lookahead['value']) !== 'against') {
          $parser->syntaxError('against');
        }
    
        $parser->match(Lexer::T_IDENTIFIER);
        $parser->match(Lexer::T_OPEN_PARENTHESIS);
        $this->against = $parser->StringPrimary();
    
        if (strtolower($lexer->lookahead['value']) === 'boolean') {
          $parser->match(Lexer::T_IDENTIFIER);
          $this->booleanMode = true;
        }
    
        if (strtolower($lexer->lookahead['value']) === 'expand') {
          $parser->match(Lexer::T_IDENTIFIER);
          $this->queryExpansion = true;
        }
    
        $parser->match(Lexer::T_CLOSE_PARENTHESIS);
      }
    
      public function getSql(SqlWalker $walker) {
        $fields = array();
        foreach ($this->pathExp as $pathExp) {
          $fields[] = $pathExp->dispatch($walker);
        }
    
        $against = $walker->walkStringPrimary($this->against)
            . ($this->booleanMode ? ' IN BOOLEAN MODE' : '')
            . ($this->queryExpansion ? ' WITH QUERY EXPANSION' : '');
        
        return sprintf('MATCH (%s) AGAINST (%s)', implode(', ', $fields), $against);
      }
    }
    

    在您的存储库中:

    class MyRepository extends EntityRepository
    {
        
        public function getUsingAgainstMatch() {
            $qb = $this->getEntityManager()->createQueryBuilder();
            $qb
                ->select('m')
                ->from('MyBundle:MyEntity', 'm')
                ->andWhere('MATCH (m.field) AGAINST (:field) > 1')
                ->setParameter('field', 'value')
            ;
            return $qb;
        }
    
        //...
    
    }
    

    你可以在这个repository找到很多Doctrine Extensions。

    希望对你有帮助

    【讨论】:

    • 谢谢,但我现在明白了:SQLSTATE[HY000]: 一般错误:1214 使用的表类型不支持 FULLTEXT 索引
    • @Picoss dql 在您的 config.yml 中的位置对我来说不正确。它需要在 entity_manager 定义中
    • @Picoss 如何在您的存储库函数示例中设置布尔模式?
    • @Picoss 还有,我将如何重用 MATCH 返回的分数,例如选择 MATCH(..) 反对 (..) 作为分数
    【解决方案2】:

    您可以通过在作曲家中要求"beberlei/DoctrineExtensions":"^1.0", 来安装教义扩展。那么您将拥有很多 mysql 函数以及 Match 然后您可以在 querybuilder 或自定义查询的 where 子句中使用 match 函数,没有任何问题。

    安装捆绑包后,您需要转到配置文件并添加所需的功能

    doctrine:
       .
       .
       .
        orm:
        .
        .
        .
           dql:
               string_functions:
                    MATCH: DoctrineExtensions\Query\Mysql\MatchAgainst 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-07-03
      • 1970-01-01
      • 2013-01-24
      • 1970-01-01
      • 2012-05-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多