简体   繁体   English

在IN上查询Doctrine ManyToMany标签的关系

[英]Where IN query on Doctrine ManyToMany tags relation

A little bit of background: 一点背景:

  • I've got Office entities. 我有Office实体。
  • Offices may have articles. 办公室可能有文章。
  • Articles have tags. 文章带有标签。
  • Offices can share a tag with other offices (and therefore articles). 办事处可以与其他办事处共享标签(因此可以与文章共享)。

Now I'm trying to build a query that says: "Fetch all articles that either belong to my office or have tags that have been shared with my office". 现在,我正在尝试建立一个查询,该查询说:“获取属于我的办公室或具有与我的办公室共享的标签的所有文章”。

I've tried this in MySQL and the following query works as expected: 我已经在MySQL中尝试过此操作,并且以下查询按预期工作:

SELECT 
    *  
FROM 
    `articles` `a` 
WHERE 
    (
        `office_id` = 2 
        OR 
        `a`.`id` IN (
            SELECT 
                `at`.`article_id` 
            FROM 
                `article_tags` `at` 
            WHERE 
                `at`.`article_id` = `a`.`id` 
            AND 
                `at`.`tag_id` IN 
                (
                    SELECT 
                        `st`.`tag_id` 
                    FROM 
                        `shared_tags` `st` 
                    WHERE 
                        `st`.`shared_with_id` = 2 
                    AND 
                        `st`.`article` = 1
                )
            )
    ) 
AND 
    `status` = 1

My entities are as follows: 我的实体如下:

Article 文章

/**
 * @ORM\ManyToMany(targetEntity="Tag", inversedBy="articles")
 * @ORM\JoinTable(name="article_tags")
 * @var ArrayCollection|Tag[]
 */
protected $tags;

Tag 标签

/**
 * @ORM\ManyToMany(targetEntity="Article", mappedBy="tags")
 * @var ArrayCollection|Article[]
 */
protected $articles;

SharedTag SharedTag

class SharedTag extends Entity
{

    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     * @var int
     */
    protected $id;

    /**
     * @ORM\ManyToOne(targetEntity="Office", inversedBy="sharedTags")
     * @ORM\JoinColumn(name="shared_with_id", referencedColumnName="id")
     * @var Office
     */
    protected $sharedWith;

    /**
     * @ORM\ManyToOne(targetEntity="Office", inversedBy="sharedTags")
     * @ORM\JoinColumn(name="shared_by_id", referencedColumnName="id")
     * @var Office
     */
    protected $sharedBy;

    /**
     * @ORM\ManyToOne(targetEntity="Tag", inversedBy="sharedTags")
     * @var Tag
     */
    protected $tag;

    /**
     * @ORM\Column(type="boolean", options={"default" = 0})
     * @var bool
     */
    protected $template = 0;

    /**
     * @ORM\Column(type="boolean", options={"default" = 0})
     * @var bool
     */
    protected $article = 0;

    /**
     * @ORM\Embedded(class = "\ValueObjects\CreatedAt", columnPrefix=false)
     * @var CreatedAt
     */
    protected $createdAt;

}

So, how can I query this in DQL or with the QueryBuilder? 那么,如何在DQL或QueryBuilder中对此进行查询? I've tried several methods but I can't seem to use the tag_id from the relationship articles.tags in a WHERE IN() query. 我试过几种方法,但我似乎无法使用tag_id从关系articles.tags在其中()查询。

Thank you in advance! 先感谢您!


Edit: 编辑:

After some trial and error and thanks to Jean's answer I was able to query it like this: 经过一番尝试和错误,并感谢Jean的回答,我能够这样查询它:

SELECT
  a
FROM
  Article a
LEFT JOIN a.tags t
LEFT JOIN a.office o
LEFT JOIN o.sharedTags st
WHERE
  (
    a.office = :office
    OR
    (
      t = st.tag
      AND
      st.sharedWith = :office
      AND
      st.article = 1
    )
  )
AND
  a.status.status = :status
AND
  a.template IS NULL
GROUP BY a.id

You should use a join and not subqueries. 您应该使用联接而不是子查询。 This way you have better performance and less complicated DQL code: 这样,您将具有更好的性能和更少的DQL代码:

SELECT DISTINCT `a`
FROM `articles` `a` 
LEFT JOIN `a.tags` `t`
LEFT JOIN `t.shared_with_id` `o`
WHERE (`a`.`office_id` = 2 OR `o`.`id` = 2) 
AND `status` = 1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM