2015-04-22 70 views
1

背景的一點點:凡主義多對多IN查詢標籤關係

  • 我有辦實體。
  • 辦公室可能有文章。
  • 文章有標籤。
  • 辦公室可以與其他辦公室(以及物品)共享一個標籤。

現在我試圖建立一個查詢,說:「獲取屬於我的辦公室或有與我的辦公室共享的標籤的所有文章。

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

我的實體如下:

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

標籤

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

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; 

} 

所以,我怎麼能查詢這DQL或與QueryBuilder的?我已經嘗試了幾種方法,但我似乎無法使用WHERE IN()查詢中關係articles.tagstag_id

預先感謝您!


編輯:

一些試驗和錯誤,並感謝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 

回答

0

您應該使用一個連接,而不是子查詢。這樣你就有更好的性能和更簡單的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 
+0

謝謝!它以正確的方式運行,但仍然需要一些額外的限制。文章't'中的標籤需要與共享標籤表中的標籤匹配(並且該共享標籤需要將布爾'文章'設置爲1)。所以我仍然需要找到一種方法來查詢'a.tags.id'嗎? – DaFrenk

+0

對不起,我不明白...這個查詢已經被共享標籤過濾了,因爲'o.id = 2'條件強制這個標籤在ID 2的辦公室中使用...你還需要什麼? – Jean

+0

是的,你是對的!有條件,但有一些調整,我發現我的用例正確的,我更新了我的問題與工作DQL。 – DaFrenk