我有一个Webinar
实体与Tag
有多对多关联。
我想通过标签列表获取网络研讨会,因此网络研讨会必须让列表中的所有标签都显示在结果中。
我有以下代码来查询它:
$tags = [1, 2];
// Base query.
$builder = $this->getEntityManager()->createQueryBuilder()
->select('W, VR, AR, T')
->from('Model:Webinar', 'W')
->leftJoin('W.videoRecord', 'VR')
->leftJoin('W.audioRecord', 'AR')
->leftJoin('W.tags', 'T')
;
// Tags query.
if (isset($tags)) {
$builder
->andWhere('T.id IN (:tags)')
->setParameter('tags', $tags)
;
}
// Other conditions.
// ...
// Issuing the query.
return $builder->getQuery()->getResult();
此查询将为我提供列表中至少有一个标记(OR)的所有网络研讨会,但我希望它在列表中包含所有标记(AND)。
我发现了answer。但看起来我有一个更复杂的例子,我不知道如何重新编写我的代码以启用正确的行为,我有其他连接的实体和其他条件。是否可以在单个块中隔离此行为而不会破坏整个查询和其他条件?
答案 0 :(得分:3)
我无法在单个查询中同时使用聚合和提取,因此我决定将其拆分为两个。
通过使用第一个查询,我将应用所有必要条件以接收网络研讨会ID列表,并使用第二个查询我将获取这些ID的对象图。
以下是完整的示例:
// I. Making the first query to fetch only webinar IDs.
// Base query.
$builder = $this->getEntityManager()->createQueryBuilder()
->select('W.id')
->from('Model:Webinar', 'W')
->orderBy('W.' . $sort, $order)
;
// Selected tags condition.
if (is_array($criteria['tags']) && count($criteria['tags']) > 0) {
$builder
->innerJoin('W.tags', 'T', 'WITH', 'T.id IN (:tags)')
->setParameter('tags', $criteria['tags'])
->groupBy('W.id')
->having('COUNT(T.id) = :tags_count')
->setParameter('tags_count', count($criteria['tags']))
;
}
// Any additional conditions
// ...
// Building the list of webinar IDs.
$ids = [];
foreach ($builder->getQuery()->getScalarResult() as $record) {
$ids[] = $record['id'];
}
// II. And now selecting complete object graph for specified webinar IDs.
// Base query.
$builder = $this->getEntityManager()->createQueryBuilder()
->select('W, VR, AR, T')
->from('Model:Webinar', 'W')
->leftJoin('W.videoRecord', 'VR')
->leftJoin('W.audioRecord', 'AR')
->leftJoin('W.tags', 'T')
->where('W.id IN (:ids)')
->setParameter('ids', $ids)
;
// Issuing the query.
return $builder->getQuery()->getResult();
我希望它会帮助别人。干杯!
答案 1 :(得分:1)
这是sql的IN
子句的工作方式,它会占用ANY
列表中IN
个项目的所有行。你必须像你提供的答案那样做类似的事情,所以在你的情况下你的查询看起来像:
// Base query.
$builder = $this->getEntityManager()->createQueryBuilder()
->select('W, VR, AR, T')
->from('Model:Webinar', 'W')
->leftJoin('W.videoRecord', 'VR')
->leftJoin('W.audioRecord', 'AR')
->leftJoin('W.tags', 'T')
;
// Tags query.
if (isset($tags)) {
$builder
->andWhere('T.id IN (:tags)')
->setParameter('tags', $tags)
;
$builder->groupBy('T.id')
->having("COUNT(DISTINCT T.id) = :count")
->setParameter("count", count($tags));
}
这应该可以正常工作我猜