Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

REST API 设计之 —— 多对多关系

  在 MySQL 中有 left join、right join、cross join 以及 group by。接口虽然不能直接暴露这些查询参数,但确实可以提供这类查询。这就涉及到联表查询问题。在联表查询中需要给多个表同时传入查询条件,并且还可能遇上多对多的关系表,所以这方面也有各种坑。
  假如数据库中有个多对多的关系。一个文章表,一个标签表,一个关系表。那么如果要查询「某篇文章所使用的标签」可能会有这样的查询语句:
select tags.*
from tags,articles_tags
where
  articles_tags.article_id=@article_id and
  articles_tags.tag_id=tags.id
  而要查询「某个标签被哪些文章所使用」可能又会有这样的查询 select articles.*
from articles,articles_tags
where
  articles_tags.tag_id=@tag_id and
  articles_tags.article_id=articles.id
  由于 API 一般没有联表查询的概念,这些需求通常都是配置好的。所以如果严格按照 SQL 的逻辑,就必须把关系表暴露,而且会产生两次查询,比如查询「某篇文章所使用的标签」可能需要先 GET /articles_tags?article_id=<article_id>   得到一组 tag_id 之后再继续查询 GET /tags?tag_id[]=...   这个逻辑本身虽然没问题,但在 Web API 中却非常不实用。因为两次查询实在是太麻烦了,所以在 API 设计时将查询相关的操作直接无视掉多对多关系,以一对多的关系来处理。这样就要方便许多。比如 GET /articles?tag_id=<tag_id>
GET /tags?article_id=<article_id>
  或者这样 GET /tag/<tag_id>/articles
GET /article/<article_id>/tags
  但这么做仅限于查询。对于添加和删除操作,就不能这么干,因为会产生奇怪的问题。比如这样 POST /article/<article_id>/tags
tag_id=<tag_id>
DELETE /tags/<tag_id>/article/<article_id>   这个逻辑就有点反人类了,因为它看着像是「一对多」的关系,但实际上却是「多对多」。如此设计可能导致 API 的使用者误操作。也许直接将关系表暴露出来逻辑会更清晰。 POST /articles_tags
article_id=<article_id>&tag_id=<tag_id>
DELETE /articles_tags?article_id=<article_id>&tag_id=<tag_id>   我最终还是没有完美解决这个设计问题。没有一种可量化的标准来决定到底以何种方式设计才更好。我个人是比较喜欢的做法是查询使用「一对多」的逻辑,添加和删除直接操作关系表,使用「多对多」的逻辑。不要问我为什么,就是这种感觉!
网名:
34.203.245.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^