[英]How to query on related entities but return root entities?
這是一個假設的問題,因為我試圖了解Doctrine ORM,並且很難復制我在純SQL中所做的事情。
假設我在標簽和帖子之間有一個簡單的ManytoMany關系。 他們會映射,以便Post::tags
是擁有者, Tag::posts
是反向映射。
我理解,使用Doctrine的DQL,我可以選擇包含其標簽的帖子,或使用以下2個查詢引用其帖子的標簽
(1) SELECT p, t FROM MyBundle:Post p JOIN p.tags t WHERE p.id = :id
(2) SELECT t, p FROM MyBundle:Tag t JOIN t.posts p WHERE t.id = :id
但是,當我想通過多個標簽獲取帖子時,我必須在以下選項中進行選擇:
(3) SELECT p, t FROM MyBundle:Post p JOIN p.tags t WHERE t.value IN ('foo','bar')
(4) SELECT t, p FROM MyBundle:Tag t JOIN t.posts p WHERE t.value IN ('foo','bar')
這兩個似乎都錯了。
使用(3)我想數據庫會在將設置減少到標記之前掃描整個帖子表
隨着(4)我得到一個標簽對象的集合,這是我所追求的反過來。
我嘗試了以下內容,因為從邏輯上講它似乎反映了我在SQL中所做的事情:
SELECT p, pt FROM MyBundle:Tag t JOIN t.posts p JOIN p.tags pt
WHERE t.value IN ('foo','bar') GROUP BY p.id
它不起作用,因為Doctrine堅持我選擇根實體
選擇標簽的最佳方法是什么,但將獨特的帖子作為完整對象取回?
如果我理解了這個問題,你想要的是選擇所有至少有一個標簽的帖子,這些標簽的值在一個定義的集合中(“foo”,“bar”,...)並忽略所有其他帖子。
讓我們從(3)開始:
SELECT p, t FROM MyBundle:Post p JOIN p.tags t WHERE t.value IN ('foo','bar')
在MySQL中,這意味着:“選擇所有具有值為foo或bar的標記的帖子”。
但是在DQL中,這意味着“選擇所有帖子並僅附加值為foo或bar的標簽”。 這意味着查詢將返回所有帖子的集合,但過濾了標簽。 這種行為差異是由於doctrine必須使用數據庫層返回的數組創建對象。 使用JOIN進行MySQL查詢時,結果將是一個包含重復項的數組。 但是,在對象世界中,必須在單個Post對象中合並重復的帖子...
我相信您的查詢的解決方案是在進行連接時進行過濾:
SELECT p,t FROM MyBundle:Post p JOIN p.tags t WITH t.value IN ('foo', 'bar')
你可以理解WITH DQL子句,好像它在ON MySQL子句中添加了一個條件。 即上面的查詢類似於下面的MySQL查詢:
SELECT p.*, t.* FROM posts AS p JOIN posts_tags AS pt ON pt.post_id = p.id JOIN tags AS t ON pt.tag_id = t.id AND t.value IN ("foo", "bar")
注意不再有WHERE子句。 條件在JOIN條件子句中移動了......
希望這可以幫助 ;-)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.