这是一个假设的问题,因为我试图了解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坚持我选择根实体
在标签上选择的最佳方法是什么,但将唯一的帖子作为完整对象取回?
答案 0 :(得分:0)
如果我理解了这个问题,你想要的是选择所有至少有一个标签的帖子,这些标签的值在一个定义的集合中(“foo”,“bar”,...)并忽略所有其他帖子。< / p>
从(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条件子句......
希望这会有所帮助; - )