假设我有一个team
对象,它有一个name
属性,一个city
属性和一个players
属性,其中players
属性可能是许多玩家的数组.这在带有teams
表和players
表的SQL数据库中表示,其中每个玩家都有a name
和a team_id
.
基于这个简单的数据结构构建一个RESTful api,如果有一个明确的规则,我是否有疑问,如果返回对象应该/可以包含一个玩家列表,何时命中/teams/:id
?
我有一个观点,那就是需要向一个团队及其玩家展示他们的名字,所以:
1:应该/teams/:id
加入场景后面的两个表并返回完整的team
对象,带有一个player属性,这是一个名字和id的数组?
2:应该/teams/:id
加入场景后面的两个表并返回team
带有players属性的对象,这是一个只有id的数组,然后必须一个一个地查询到/players/:id
?
3:如果两个呼叫进行,一来/teams/:id
和一个/teams/:id/players
?
4:是否应该像这样使用查询字符串/teams/:id?fields=name,city,players
?
如果要做的是2或3,那么如何处理这种情况,团队中也可能有多个城市,导致数据库中的另一个cities
表保持规范化?是否应该创建一个新的端点/teams/:id/cities
.
在创建RESTful API时,DB中的规范化数据结构是否规定了API中的端点?
我建议类似的东西:
GET /teams { "id" : 12, "name" : "MyTeam" "players" : { "self" : "http://my.server/players?teamName=MyTeam" }, "city" : { "self" : "http://my.server/cities/MyCity" } } GET /cities GET /cities/{cityId} GET /players GET /players/{playerId}
然后,您可以使用URI进行调出以获得所需的其他任何相关资源。如果要灵活地嵌入值,可以使用?expand,例如:
GET /teams?expand=players { "id" : 12, "name" : "MyTeam" "players" : { "self" : "http://my.server/players?teamName=MyTeam", [ { "name" : "Mary", "number" : "12" }, { "name" : "Sally", "number" : "15" } ] }, "city" : { "self" : "http://my.server/cities/MyCity" } }
通常使用RESTful API,最好是用例指示API的端点,而不一定是数据结构.
如果你有时只需要团队,有时只需要一个团队的玩家,有时需要两个人,我会有3个不同的调用,可能是类似的东西/teams/:id
,/players/:teamid
和player-teams/:teamid
(或类似的东西).
您希望以这种方式执行此操作的原因是,它最大限度地减少了需要为任何给定页面进行的HTTP请求的数量.在所有典型的性能问题中,增加的HTTP请求数通常是最常见的性能命中之一,并且通常是最容易避免的之一.
话虽这么说,你也不想疯狂,因为你创建了一个过度膨胀的API.仔细考虑典型的用例并对其进行调用.不要只是为了它而实现你能想到的每一种可能的组合.记住你不需要它.