新手求指教,查询一对多/多对多关系,映射到编程语言的对象,常规操作是怎样的?

2018-06-14 15:06:41 +08:00
 changrui0608
比如最简单的模型吧,博客有文章 post 和标签 tag,是多对多关系;
数据库 schema 设计中,一般通过 id 的互相引用;
编程语言中,通常表现为一个 Post 对象,有一个 Tags 数组属性,里边是多个 Tag 的内容;

问题就是,不用 ORM 纯手写 SQL 的话,怎么做到一次查询数据库,转换到 Post 对象,并填充 Tags 属性的?

看过一些 ORM 的实际 SQL 日志,一般会是用 LEFT JOIN,但 LEFT JOIN 的话,比如一个 Post 有多个 Tag,那么查询结果中一个含有 N 个 Tag 的 Post 就会重复出现 N 次。

虽然是可以手动编程排除重复 Post 并依次处理 Tag,但是感觉极为蛋疼,复杂度也不低,所以想请教下,这种情况下的常规操作是怎样的?
3177 次点击
所在节点    MySQL
9 条回复
alexsunxl
2018-06-14 16:14:27 +08:00
典型的想得太多, 做得太少, 哈哈哈
别纠结这些了, 最后还是看场景看业务看历史
这种东西没有最佳实践的,只能说相对较合适,
至于怎么是合适,那还是多积累吧
changrui0608
2018-06-14 16:28:07 +08:00
@alexsunxl
兄弟,我不是做的太少,我是做到这儿了不知道怎么办才来问的,你这话就和没说一样啊...
Stevenv
2018-06-14 17:01:19 +08:00
你可以换种方式,多查几次。别想着一条 SQL 查出来。。以前我也是想一条查出来,结果发现是为难自己
DavidNineRoc
2018-06-14 17:25:55 +08:00
看了一下 lv 的 SQL

## 先查询 posts 表
select * from posts where xxxx
## 连接查询关联关系
SELECT
`tags`.*,
`post_tag`.`post_id` AS `pivot_post_id`,
`post_tag`.`tag_id` AS `pivot_tag_id`
FROM
`tags`
INNER JOIN `post_tag` ON `tags`.`id` = `post_tag`.`tag_id`
WHERE
`post_tag`.`post_id` IN (## 这里是 posts 表查询的数据 ## )
##
然后将第二次查询的数据按照 pivot_post_id 分组,循环一遍 posts 查询出的数据,直接按 pivot_post_id 组设置为单个 posts 的属性。
AlphaTr
2018-06-14 17:41:41 +08:00
关系型数据库一次查询返回就会出现「 N 个 Tag 的 Post 就会重复出现 N 次」这种情况。一种方式就是你说的,手动编程排重;另一种方式就是多次查询。或者可以直接上非关系型数据库;
changrui0608
2018-06-14 18:13:33 +08:00
@DavidNineRoc 多谢,查了一下午似乎是这种方法最合适,顺便 lv 全程是什么
cxbig
2018-06-14 18:17:39 +08:00
关键词:ORM eager loading
抓 SQL 看看人家怎么处理的就明白了
Foolt
2018-06-14 18:17:50 +08:00
MySQL 去重关键字 DISTINCT 了解一下
DavidNineRoc
2018-06-15 08:48:18 +08:00
@changrui0608 laravel

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/463098

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX