学说:与左连接的分页

Jea*_*aud 15 pagination symfony doctrine-orm

我想用至少2个左连接对复杂请求进行分页,但我正在使用的分页包(KnpPaginationBundle)无法告诉Doctrine如何计算结果(这是分页过程所需的),并继续这样做例外.

Cannot count query which selects two FROM components, cannot make distinction

这是使用Doctrine QueryBuilder构建的示例请求.

public function findGroupsByUser(User $user, $listFilter, $getQuery = false, $order = 'ASC')
{
    $query = $this->createQueryBuilder('r')
        ->select('r as main,g')
        ->select('r as main,g, count(gg) as members')
        ->leftjoin('r.group', 'g')
        ->innerjoin('MyBundle:GroupMemberRel', 'gg', 'WITH', 'r.group = gg.group')
        ->addGroupBy('g.groupId')
        ->add('orderBy', 'g.name ' . $order);
   if ($getQuery == true) {
        return $query;
    }

    return $query->getQuery()->getResult();
}
Run Code Online (Sandbox Code Playgroud)

然后我将此请求提供给knp_paginator服务,然后我就得到了异常

    $groupQuery = $this->em->getRepository('MyBundle:GroupMemberRel')->findGroupsByUser($user, $listFilter, true);
    $paginator = $this->container->get('knp_paginator');
    /* @var $groups Knp\Component\Pager\Pagination\PaginationInterface */
    $groups = $paginator->paginate(
        $groupQuery, $this->container->get('request')->query->get('page', 1), 10 /* limit per page */
    );
Run Code Online (Sandbox Code Playgroud)

关于如何对复杂请求进行分页的任何想法,我很确定这个用例很常见,不希望在分页后保留我的结果.

men*_*lic 22

对于任何寻求这方面答案的人来说,有一个很好的解决方案:https: //github.com/KnpLabs/KnpPaginatorBundle/blob/master/Resources/doc/manual_counting.md

$paginator = new Paginator;

// determine the count of the entire result set
$count = $entityManager
    ->createQuery('SELECT COUNT(c) FROM Entity\CompositeKey c')
    ->getSingleScalarResult();

// create a query to be used with the paginator, and specify a hint
$query = $entityManager
     ->createQuery('SELECT c FROM Entity\CompositeKey c')
     ->setHint(
        'knp_paginator.count', 
        $count
    );

// paginate, and set "disctinct" option to false
$pagination = $paginator->paginate(
    $query, 
    1, 
    10, 
    array(
        'distinct' => false,
    )
);
Run Code Online (Sandbox Code Playgroud)

基本上,你正在做的是,你正在创建自己的'count'查询并指示knp paginator使用它.

  • 伙计们,请注意**数组('distinct'=> false)**...花了我很多年 (6认同)

fut*_*eal 14

很难理解原始问题中的实体,但我遇到了同样的问题,它确实是可以解决的.

假设您有这样的实体:

  class User
  {
    // ...
    /**
     * @ORM\OneToMany(targetEntity="Registration", mappedBy="user")
     */
    private $registrations;
    // ...
  }
Run Code Online (Sandbox Code Playgroud)

重要的是它与另一个实体有一对多的关系,并且您希望能够通过QueryBuilder以任何原因加入到该关系中(例如,您可能希望HAVING在查询中添加一个子句来选择只有那些具有一个或多个其他实体的实体).

您的原始代码可能如下所示:

  $qb = $this->createQueryBuilder();

  $query = $qb
    ->select('u')
    ->add('from', '\YourBundle\ORM\Model\User u')
    ->leftJoin('\YourBundle\ORM\Model\Registration', 'r', 'WITH', 'u.id = r.user')
    ->groupBy('u.id')
    ->having($qb->expr()->gte($qb->expr()->count('u.registrations'), '1')
    ->getQuery();
Run Code Online (Sandbox Code Playgroud)

这将抛出异常: Cannot count query which selects two FROM components, cannot make distinction

要解决此问题,请重写查询,以便QueryBuilder只有一个"from"组件 - 正如异常所示 - 通过内联移动连接.像这样:

  $qb = $this->createQueryBuilder();

  $query = $qb
    ->select('u')
    ->add('from', '\YourBundle\ORM\Model\User u LEFT JOIN u.registrations r')
    ->groupBy('u.id')
    ->having($qb->expr()->gte($qb->expr()->count('r'), '1')
    ->getQuery();
Run Code Online (Sandbox Code Playgroud)

使用Doctrine的Paginator类可以正常工作,不需要其他捆绑包.还要注意连接的简写语法; 使用Doctrine你没有看到明确指定连接实体(尽管你可以),因为映射已经知道它是什么.

希望这可以帮助别人,在这个问题上没有太多.您可以在此处查看@ halfer的评论,以了解内部如何处理此问题.