简体   繁体   English

如何查询相关实体但返回根实体?

[英]How to query on related entities but return root entities?

This is a hypothetical question, because I'm trying to get my head around Doctrine ORM and having a hard time replicating what I'd do in plain SQL. 这是一个假设的问题,因为我试图了解Doctrine ORM,并且很难复制我在纯SQL中所做的事情。

Suppose I have a simple ManytoMany relationship between tags and posts. 假设我在标签和帖子之间有一个简单的ManytoMany关系。 They would map so that Post::tags is the owning side and Tag::posts is the reverse mapping. 他们会映射,以便Post::tags是拥有者, Tag::posts是反向映射。

I understand that with Doctrine's DQL I can select posts containing their tags, or tags referencing their posts with the following 2 queries 我理解,使用Doctrine的DQL,我可以选择包含其标签的帖子,或使用以下2个查询引用其帖子的标签

(1) SELECT p, t FROM MyBundle:Post p JOIN p.tags t WHERE p.id = :id (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 (2) SELECT t, p FROM MyBundle:Tag t JOIN t.posts p WHERE t.id = :id

But when I want to fetch posts by a number of tags, I have to choose between these: 但是,当我想通过多个标签获取帖子时,我必须在以下选项中进行选择:

(3) SELECT p, t FROM MyBundle:Post p JOIN p.tags t WHERE t.value IN ('foo','bar') (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') (4) SELECT t, p FROM MyBundle:Tag t JOIN t.posts p WHERE t.value IN ('foo','bar')

Both of these seem wrong. 这两个似乎都错了。

With (3) I imagine the DB would scan the whole posts table before reducing the set to those tagged 使用(3)我想数据库会在将设置减少到标记之前扫描整个帖子表

With (4) I get a collection of tag objects back which is the inverse of what I'm after. 随着(4)我得到一个标签对象的集合,这是我所追求的反过来。

I tried the following, because logically it seemed to mirror what I'd do in SQL: 我尝试了以下内容,因为从逻辑上讲它似乎反映了我在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

It doesn't work because Doctrine insists I select the root entity 它不起作用,因为Doctrine坚持我选择根实体

What's the best way to select on tags but get back unique posts as full objects? 选择标签的最佳方法是什么,但将独特的帖子作为完整对象取回?

If I understood well the question, what you want is select all posts that have at least one tag whose value is in a defined set ("foo", "bar", ...) and ignore all other posts. 如果我理解了这个问题,你想要的是选择所有至少有一个标签的帖子,这些标签的值在一个定义的集合中(“foo”,“bar”,...)并忽略所有其他帖子。

Let start from (3): 让我们从(3)开始:

SELECT p, t FROM MyBundle:Post p JOIN p.tags t WHERE t.value IN ('foo','bar')

In MySQL this means approximately: "Select all posts having a tag whose value is either foo or bar". 在MySQL中,这意味着:“选择所有具有值为foo或bar的标记的帖子”。

However in DQL this means "Select all Posts and attach only tags whose values is either foo or or bar". 但是在DQL中,这意味着“选择所有帖子并仅附加值为foo或bar的标签”。 Meaning that the query will return the set of all posts, but with tags filtered. 这意味着查询将返回所有帖子的集合,但过滤了标签。 This difference of behavior is due to the fact that doctrine has to create objects with the array returned by the Database Layer. 这种行为差异是由于doctrine必须使用数据库层返回的数组创建对象。 When you make a MySQL query with JOINs, the results will be an array with duplicates. 使用JOIN进行MySQL查询时,结果将是一个包含重复项的数组。 However, in the object world, duplicate posts have to be merged in a single Post object... 但是,在对象世界中,必须在单个Post对象中合并重复的帖子...

I believe the solution to your query is to filter when the join is made: 我相信您的查询的解决方案是在进行连接时进行过滤:

SELECT p,t FROM MyBundle:Post p JOIN p.tags t WITH t.value IN ('foo', 'bar')

you can understand the WITH DQL clause as if it added a condition in the ON MySQL clause. 你可以理解WITH DQL子句,好像它在ON MySQL子句中添加了一个条件。 Ie the above query is similar to MySQL query below: 即上面的查询类似于下面的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")

Remark that there is no more WHERE clause. 注意不再有WHERE子句。 The condition moved in the JOIN condition clause... 条件在JOIN条件子句中移动了......

Hope this helps ;-) 希望这可以帮助 ;-)

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

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