使用来自 ManyToMany 关联的值过滤具有 NOT EXISTS 条件的 DQL 查询

Filtering DQL query with NOT EXISTS condition using values from ManyToMany association

很抱歉让第一个 post 成为一个问题,但我认为我还没有足够的经验来提供有价值的帮助。希望有人愿意帮助解决我一直陷入的困境。

我在编写条件 DQL 子句来过滤掉其 ID 存在于由 ManyToMany 关联创建的枢轴 table 中的实体时遇到了问题。

class Product
{
    /**
      * @ORM\ManyToMany(targetEntity="App\Entity\GroupProduct", fetch="EXTRA_LAZY", inversedBy="products")
      * @ORM\JoinTable(name="product_group_product" )
      */

    private $groupProduct; 
}

我无法在 DQL 查询中使用 product_group_product 枢轴 table,因为它不是由专用实体映射的。 是否可以编写与此 SQL 查询:

执行相同操作的 DQL 查询
SELECT * FROM product as p WHERE NOT EXISTS (
SELECT 1 FROM product_group_product as gp WHERE gp.product_id = p.id
);

我试过:

->andWhere('p NOT MEMBER OF p.groupProduct')  

但是 SQL 查询中生成的 NOT EXISTS 子句包含 Product 和 GroupProduct 实体 ID 之间的索引比较,这使得它 return 错误:

AND NOT EXISTS (SELECT 1 FROM product_group_product p1_ 
INNER JOIN group_product g2_ ON p1_.group_product_id = g2_.id 
WHERE p1_.product_id = p0_.id 
-->AND g2_.id IN (p0_.id)<--)

如有任何想法,我们将不胜感激。

如果我的理解正确,我认为您可以使用 left join 而不是子查询来做到这一点。

在SQL

例如,在SQL中:

select * from product p
left join product_group_product gp on gp.product_id = p.id
where gp.id is null

此查询应该获取不在 product_group_product.

中的产品

之所以有效,是因为左联接包含所有产品,即使它们没有 product_group_product 条目。当产品没有 product_group_product 条目时,这些列将返回为空。 where 语句然后过滤掉那些将其对应的 product_group_product.id 为空的产品。

一个"gotcha"如果一个产品确实有一个product_group_product,但是product_group_product的ID是空的,它也会被退回。如果 product_group_product.id 不可为 null(通常是这种情况),这不是问题。

在 DQL 中

在 Doctrine 中,基于 product_group_product 进行查询有点棘手,因为它是一个 JoinTable,它没有实体并被 Doctrine 抽象掉。

相反,您应该能够使用相同类型的左连接,除了使用您的 GroupProduct 实体定义的关系:

$query = $em->createQuery('SELECT p FROM App\Entity\Product p LEFT JOIN p.groupProduct gp where gp is NULL');