Как запросить отношения ManyToMany в Doctrine, где id ассоциации не равен - PullRequest
0 голосов
/ 10 сентября 2018

Я видел этот вопрос и событие подумало, что это то, что мне нужно.Это довольно похоже на мои требования.Как бы то ни было, мелочь изменила всю логику.

Итак, вот моя схема:

/** @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();
    }

Я не публикую здесь свои данные, потому что результатом этого запроса являются все продукты.У меня около 5 000 товаров, и я уверен, что не все из них относятся к моей категории.Я пробовал разные категории.Он показывает все продукты, не зависящие от моего запроса.

Я также оставляю запрос 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, но я не знаю, насколько это эффективно.

Я читаю информацию Google о взаимоотношениях "многие ко многим" и о том, как их запрашивать, но все, что я нашел о запросе на равенство, и у меня нетравенство.

1 Ответ

0 голосов
/ 12 сентября 2018

Чтобы исключить все продукты, которые относятся к категории 1, вы можете использовать не в выражении в доктрине, как

$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();

...