简体   繁体   English

如何在使用内部Join时优化Doctrine查询的数量?

[英]How to optimize number of Doctrine queries when using an inner Join?

I have to simple Entity: Log and User. 我必须简单的实体:日志和用户。 Log has a ManyToOne relationship with Entity. Log与Entity具有ManyToOne关系。

Log:
  type: entity
  repositoryClass: LogRepository
  id:
    id:
      type: integer
      generator:
        strategy: AUTO
  fields:
    message:
      type: string      
  manyToOne:
    user:
      targetEntity: User
      joinColumns:
        user_id:
          referencedColumnName: id

My use case is to show the list of the logs and one or two information about the user (like his name and his mail for example) 我的用例是显示日志列表和一两个用户信息(例如他的名字和邮件)

If I use the findall method, Symfony debug toolbar shows me that Doctrine performs a lot of queries. 如果我使用findall方法,Symfony调试工具栏会告诉我Doctrine执行了很多查询。 One query gives me the logs and one query is performed for each user! 一个查询给我日志,并为每个用户执行一个查询! It is not good of course because I can have thousand logs in my view. 当然不好,因为我可以在我的视图中拥有数千个日志。 I don't want to overload my database server. 我不想重载我的数据库服务器。 This problem seems very simple to solve. 这个问题似乎很容易解决。 But I'm searching for a while and the results seems to be "bad practices". 但我正在寻找一段时间,结果似乎是“不良做法”。

So I began by writing a new method in the LogRepository class using the querybuilder: 所以我开始使用querybuilder在LogRepository类中编写一个新方法:

public function getLog(){
        $qb = $this->createQueryBuilder('l')
            ->select('l')
            ->innerJoin(
                'ApplicationSonataUserBundle:User', 'u', 
                Expr\Join::WITH,'l.user = u.id')
        ;
        return $qb->getQuery()->getResult();
}

I still had the same problem. 我仍然有同样的问题。 I have changed the select parameters on my method to : 我已将方法上的选择参数更改为:

public function getLog(){
        $qb = $this->createQueryBuilder('l')
            ->select('l','u')
            ->innerJoin('ApplicationSonataUserBundle:User','u', 
                        Expr\Join::WITH,'l.user = u.id')
        ;
        return $qb->getQuery()->getResult();
}

Eureka? 尤里卡? OK, I only have one query but my method didn't return only Log, BUT User too... So my Twig template crashes because my loop contains User, not only Log. 好的,我只有一个查询,但我的方法没有只返回Log,但是用户也是......所以我的Twig模板崩溃,因为我的循环包含User,而不仅仅是Log。 When this is a User, my view crash because I want to write message fields. 当这是一个用户时,我的视图崩溃,因为我想写消息字段。 (Log.message exists. But User.message is not a valid field, of course) (Log.message存在。但User.message当然不是有效字段)

It works pretty good, if I change one more time my method with a loop to filter my results : 它工作得很好,如果我再用一个循环来改变我的方法以过滤我的结果:

public function getLog(){
        $qb = $this->createQueryBuilder('l')
            ->select('l','u')
            ->innerJoin('ApplicationSonataUserBundle:User','u',
                        Expr\Join::WITH,'l.user = u.id')
        ;
        //THE STRANGE LOOP
        $results = array();
        foreach ($qb->getQuery()->getResult() as $result){
            if ($result instanceof Log){
                $results[] = $result;
            }
        };
        return $results;
}

I have only one query, it is what I'm searching for. 我只有一个查询,这是我正在寻找的。 My twig template doesn't crash, because my array contains only Log. 我的twig模板不会崩溃,因为我的数组只包含Log。

So what's the matter? 那有什么关系? It works, but I think this is not the good/best practices. 它有效,但我认为这不是好/最佳实践。

Someone can explain me a better way, a better practice to use an inner join query, to minimize the performed query and have an ArrayCollection result which contains only instance of Log? 有人可以向我解释一个更好的方法,更好的做法是使用内连接查询,最小化执行的查询并且有一个只包含Log实例的ArrayCollection结果?

It should not be necessary to use the loop. 没有必要使用循环。 Try like this: 试试这样:

public function getLog(){
    $qb = $this->createQueryBuilder('l')
        ->select('l','u')
        ->innerJoin('l.user', 'u');
    $logs = $qb->getQuery()->getResult();
    return $logs;
}

It should only return $logs with a populated (fetch joined) association user. 它应该只返回带有填充(fetch加入)关联用户的$logs

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM