简体   繁体   English

如何减少Doctrine正在执行的查询数量?

[英]How can I reduce the number of queries Doctrine is performing?

I'm building a product management tool where the product can have an arbitrary number of attributes , documents , features , images , videos as well as a single type , brand , and category . 我正在构建一个产品管理工具,该product可以具有任意数量的attributesdocumentsfeaturesimagesvideos以及单个typebrandcategory There are a few other related tables, but this is enough to demonstrate the problem. 还有一些其他相关表,但这足以说明问题。

There's a Model class called ProductModel that contains a method like this (reduced for clarity): 有一个称为ProductModel的Model类,其中包含这样的方法(为清楚起见已简化):

  public function loadValues() {
    //Product entity data
    $this->id = $this->entity->getId();
    $this->slug = $this->entity->getSlug();

    // One of each of these
    $this->loadType();
    $this->loadBrand();
    $this->loadCategory();

    // Arbitrary number of each of these
    $this->loadAttributes();
    $this->loadDocuments();
    $this->loadFeatures();
    $this->loadImages();
    $this->loadVideos();
    ...
  }

Each of the load methods does some boiler plate that eventually executes this method: 每个加载方法都会执行一些样板,最终执行此方法:

  public function loadEntitiesByProductId($productId=0) {

    // Get all the entities of this type that are associated with the product.
    $entities = $this->entityManager
      ->getRepository($this->entityName)
      ->findByProduct($productId);

    $instances = array();

    // Create a Model for each entity and load the data.
    foreach ($entities as $entity) {
      $id = $entity->getId();
      $instances[$id] = new $this->childClass();
      $instances[$id]->entity = $entity;
      $instances[$id]->loadValues();
    }

    return $instances;

  }

This is OK for cases where the related entity is a single table, but usually it's a mapper. 对于相关实体是单个表但通常是映射器的情况,这是可以的。 In those cases, I get all the mapper entities in the first query then I have to query for the related entity within the loadValues() method (via Doctrine's get<Entity>() method). 在那些情况下,我将在第一个查询中获得所有映射器实体,然后必须在loadValues()方法中查询相关实体(通过Doctrine的get<Entity>()方法)。 The result of this process is a huge number of queries (often >100). 此过程的结果是大量查询(通常> 100)。 I need to get rid of the extraneous queries, but I'd like to do so without losing the idioms I'm using across my data models. 我需要摆脱无关的查询,但是我希望这样做而不会丢失我在数据模型中使用的惯用语。

Is there a way to get the entityManager to do a better job at using joins to group these queries? 有没有办法让EntityManager在使用联接对这些查询进行分组方面做得更好?

There were a couple problems with my previous approach: 我以前的方法存在两个问题:

First, I was getting the entities from the repository instead of loading them from the existing entity: 首先,我从存储库中获取实体,而不是从现有实体中加载它们:

$entities = $this->entityManager
  ->getRepository($this->entityName)
  ->findByProduct($productId);

Better is: 更好的是:

$method = $this->deriveGetMethod($this->entityName);
$entities = $productEntity->$method()

Second, I was retrieving the product entity using $this->entityManager->getRespository... which works fine for loading small data sets (a single table or one or two relations), but there's no way to get the repository's findBy methods to load relations in a single query. 其次,我正在使用$this->entityManager->getRespository...检索产品实体$this->entityManager->getRespository...这对于加载小型数据集(单个表或一个或两个关系)可以很好地工作,但是无法获取存储库的findBy方法来在单个查询中加载关系。 The solution is to use the queryBuilder. 解决方案是使用queryBuilder。

$qb = $this->entityManger->createQueryBuilder();
$query = $this->select('product',/*related tables*/)->/*joins etc.*/
$productEntity = $query->getSingleResult();

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

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