我确实看到this question和事件认为这是我需要的。它与我的要求非常相似。然而,chaning一个小东西似乎打破了整个逻辑。
所以这是我的架构:
/** @Entity **/
class Product
{
/**
* @ManyToMany(targetEntity="Category", inversedBy="products")
**/
private $categories;
public function __construct() {
$this->categories = new \Doctrine\Common\Collections\ArrayCollection();
}
// ...
}
/** @Entity **/
class Category
{
/**
* @ManyToMany(targetEntity="Product", mappedBy="categories")
**/
private $products;
public function __construct() {
$this->products = new \Doctrine\Common\Collections\ArrayCollection();
}
}
我需要查询所有不属于特定类别的产品。我的尝试是:
// ProductRepository
public function getProducts() {
return $this->createQueryBuilder('p')
->innerJoin('p.categories', 'c')
->where('c.id != :id')
->setParameter('id', 1)
->getQuery()
->getResult();
}
我不在这里发布我的数据,因为此查询的结果是所有产品。我有大约5000种产品,并且非常确定并非所有产品都属于我的类别。我试过不同的类别。它显示所有不依赖于我的查询的产品。
我也在这里留下SQL查询:
SELECT p0_.* FROM products p0_
INNER JOIN product_categories p2_ ON p0_.id = p2_.product_id
INNER JOIN categories c1_ ON c1_.id = p2_.category_id
WHERE c1_.id != 1
另一个问题是它给了我产品重复。我可以使用group by p0_.id
,但我不知道它是否有效。
我阅读了关于多对多关系以及如何查询它们的谷歌信息,但我发现它关于相等查询,我有不相等。
要排除属于类别1的所有产品,您可以不在doctrine中使用表达式
$categoryProducts = $this->createQueryBuilder('p1')
->select('p1.id')
->innerJoin('p1.categories', 'c')
->where('c.id = :id')
->setParameter('id', 1)
->getDQL();
$qb = $this->createQueryBuilder('p');
$products = $qb->where(
$qb->expr()->not(
$qb->expr()->in(
'p.id',
$categoryProducts
)
)
)
->getQuery()
->getResult();
另一种方法,但不确定,我想这应该通过使用左连接查询产生相同的结果
$this->createQueryBuilder('p')
->leftJoin('p.categories', 'c', 'WITH', 'c.id = :id')
->where('c.id IS NULL' )
->setParameters('id',1)
->getQuery()
->getResult();