【问题标题】:Search for Entity that has multiple tags in doctrine在教义中搜索具有多个标签的实体
【发布时间】:2017-12-04 20:05:11
【问题描述】:

我在 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 也不行,因为没有一个标签可以同时拥有这两个标签。

【问题讨论】:

标签: symfony doctrine


【解决方案1】:

您可以通过为每个标签添加额外的内部连接来实现此目的:

例子:

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

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

如果您有更多标签要搜索,您可以简单地为此添加另一个联接。

【讨论】:

  • 看起来可行,而且解释得很好,谢谢赏金猎人,得到你的赏金:)
  • 我真的对这个问题或答案不感兴趣,但想说添加这张图片的道具!
  • 这是一个很好的解决方案,当您的数据库不是很大并且查询的标签数量很少时。对于大型数据库或复杂查询,我使用 Elasticsearch。这听起来可能有点矫枉过正,但随着网站的发展,这种方法值得考虑。
猜你喜欢
  • 1970-01-01
  • 2018-08-31
  • 1970-01-01
  • 2012-10-22
  • 1970-01-01
  • 1970-01-01
  • 2023-04-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多