我在产品和标签之间有很多关系。目前,它被定义为与产品为拥有方的单向关系,但是如果需要,我可以将其更改为双向。
我想构建一个功能,为现有产品建议标签。我希望首先建议最受欢迎的标签,并且显然我不希望建议已分配给产品的任何标签。流行标签是指那些更常分配给其他产品的标签。另外,建议的标签必须以给定的前缀开头。
我有一个有效的SQL查询,可以为我提供所需的确切结果,但是在尝试将其转换为DQL或查询生成器格式时遇到麻烦。
假设1
是我要获取标签建议的产品的ID,并假设建议标签的前缀为prefix
,则此查询返回我想要的结果:>
SELECT
t.id,
t.name,
COUNT(pt.product_id) AS popularity
FROM
tags t LEFT JOIN product_tag pt ON (t.id = pt.tag_id)
WHERE
t.id NOT IN (SELECT tag_id FROM product_tag WHERE product_id = 1) AND
t.name LIKE 'prefix%'
GROUP BY
t.id,
t.name
ORDER BY
popularity DESC,
t.name
我当前的方法是这种方法,但是返回空结果
$queryBuilder = $entityManager->createQueryBuilder();
$product = $productRepository->find(1);
$prefix = 'prefix';
$suggestions = $queryBuilder
->select('t.id, t.name, COUNT(p) AS popularity')
->from('Tag', 't')
->leftJoin('Product', 'p', \Doctrine\ORM\Query\Expr\Join::WITH, $queryBuilder->expr()->eq('p.id', $product->getId()))
->andWhere('t NOT MEMBER OF p.tags')
->andWhere('t.name LIKE :prefix')->setParameter('prefix', "$prefix%")
->groupBy('t.id, t.name')
->addOrderby('popularity', 'desc')
->addOrderby('t.name')
->getQuery()
->getResult();
上面的代码生成的SQL关闭但不正确:
SELECT
t.id,
t.name,
COUNT(p.id) AS popularity
FROM
tags t2_ LEFT JOIN products p ON (p.id = 1),
tags t
WHERE
NOT EXISTS
(
SELECT 1
FROM
product_tag pt INNER JOIN tags t ON pt.tag_id = t4_.id
WHERE
pt.product_id = p.id AND
t4_.id IN ( t.id )
)
AND t.name LIKE ?
GROUP BY
t.id,
t.name
ORDER BY
popularity DESC,
t.name ASC