搜索在doctrine中具有多个标记的实体

时间:2017-06-30 19:27:28

标签: symfony doctrine

我在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

现在,我想搜索包含代码animalfiction的所有文档。我如何用学说实现这一目标?

这样的东西
$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)

不会完成这项工作,因为它会返回所有包含tag1tag2的文档。但是andX也不会起作用,因为没有单个标签同时包含两个标签。

1 个答案:

答案 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();

也许这个小图片有助于理解这个查询的作用。整个圆圈代表您的所有文件。如果您只使用一个连接,查询将返回绿色+红色或蓝色+红色部分。 使用额外的内连接,您将只获得单独看到的连接的交集(这只是红色部分)。

enter image description here

如果您还有更多要搜索的代码,则只需添加其他联接即可。