php 如何从N+1优化查询而不破坏doctrine2中的数据?

pgx2nnw8  于 2023-10-15  发布在  PHP
关注(0)|答案(1)|浏览(112)

有以下表格:国家签证大使馆(一个国家可以有多个签证和大使馆)。
我做了一个查询,得到了几个国家的记录:

$countries = $this->entityManager
    ->createQueryBuilder()
    ->select('c')
    ->from(Country::class, 'c')
    ->setMaxResults($condition->first)
    ->setFirstResult($condition->offset)
    ->getQuery()
    ->getResult();

好的,一切正常。
此外,当我们在循环中使用$currencies并获取签证和大使馆时,我们会遇到N + 1个查询的问题。在我的情况下,它是200+查询一次。
让我们尝试用join来解决这个问题:

$countries = $this->entityManager
    ->createQueryBuilder()
    ->select('c')
    ->from(Country::class, 'c')
    ->leftJoin('c.visas', 'cv')
    ->addSelect('cv')
    ->leftJoin('c.embassies', 'ce')
    ->addSelect('ce')
    ->setMaxResults($condition->first)
    ->setFirstResult($condition->offset)
    ->getQuery()
    ->getResult();

因此,这解决了N+1的问题,将200+个查询变为4个查询,但出现以下问题:
例如,在我们的表中(或通过查询条件找到)有1个国家记录,但是这个国家,例如,在数据库中有3个签证和5个大使馆记录。
因此,在使用join的情况下,当找到1个国家时,签证和大使馆的关系也将返回1条记录(可能有更多记录也没关系)。
这种行为是由于leftJoin,一方面-这些是200多个查询,另一方面-如果国家记录少于可能的关系,则返回不完整的数据。
我该如何解决这个问题?

fd3cxomn

fd3cxomn1#

你不能用join解决它,你应该使用WHERE IN运算符对其他数据进行查询。首先,你得到你的国家,得到他们的id数组,例如$ids,然后查询,如

$queryBuilder->where('embassies.country_id IN (:ids)')
             ->setParameter('ids', $ids)

签证也是一样。因此,而不是200多个查询,您可以使用3个查询获得所有数据。

相关问题