我在Document和Tag之间有很多关系。因此,Document
可以包含多个Tags
,并且可以将一个Tag
分配给不同的Document
。
这是Tag
AppBundle\Entity\Tag:
type: entity
table: tags
repositoryClass: AppBundle\Repository\TagRepository
manyToMany:
documents:
targetEntity: Document
mappedBy: tags
id:
id:
type: integer
id: true
generator:
strategy: AUTO
fields:
label:
type: string
length: 255
unique: true
Document
AppBundle\Entity\Document:
type: entity
table: documents
repositoryClass: AppBundle\Repository\DocumentRepository
manyToMany:
tags:
targetEntity: Tag
inversedBy: documents
joinTable:
name: documents_tags
id:
id:
type: integer
id: true
generator:
strategy: AUTO
fields:
title:
type: string
length: 255
现在,我想搜索包含代码animal
和fiction
的所有文档。我如何用学说实现这一目标?
像
这样的东西$repository = $this->getDoctrine()->getRepository('AppBundle:Document');
$query = $repository->createQueryBuilder('d');
$query ->join('d.tags', 't')
->where($query->expr()->orX(
$query->expr()->eq('t.label', ':tag'),
$query->expr()->eq('t.label', ':tag2')
))
->setParameter('tag', $tag)
->setParameter('tag2', $tag2)
不会完成这项工作,因为它会返回所有包含tag1
或tag2
的文档。但是andX
也不会起作用,因为没有单个标签同时包含两个标签。
答案 0 :(得分:8)
您可以通过为每个标记添加额外的内部联接来实现此目的:
示例:
$em = $this->getDoctrine()->getManager();
$repository = $this->getDoctrine()->getRepository('AppBundle:Document');
$query = $repository->createQueryBuilder('d');
$query->innerJoin('d.tags', 't1', Join::WITH, 't1.label = :tag1');
$query->innerJoin('d.tags', 't2', Join::WITH, 't2.label = :tag2');
$dql = $query->getDql();
$result = $em->createQuery($dql)
->setParameter('tag1', 'LabelForTag1')
->setParameter('tag2', 'LabelForTag2')
->getResult();
也许这个小图片有助于理解这个查询的作用。整个圆圈代表您的所有文件。如果您只使用一个连接,查询将返回绿色+红色或蓝色+红色部分。 使用额外的内连接,您将只获得单独看到的连接的交集(这只是红色部分)。
如果您还有更多要搜索的代码,则只需添加其他联接即可。