URI 命名层次结构建议

发布于 2024-10-04 14:29:49 字数 1671 浏览 9 评论 0原文

我正在尝试构建一个基于休息的服务,该服务具有广泛的体育数据覆盖范围(结果/赛程/球队/球员/联赛等)和相关统计数据。

目前,想出一个合适的 URI 层次结构让我陷入了困境。例如,我可以实现...

1) i) version/sports/league/season/entity

1) ii) version/entity/sports/league/season

1) iii) version/sports/entity/league/season

一个例子让事情变得更清晰(希望如此)...

进行一个查询,返回 2010 年在英超联赛中踢球的所有足球运动员/2011 赛季...

2) i) 1.1/football/premier_league/2010_2011/球员

2) ii) a) 1.1/球员/football//premier_league/2010_2011

但是并不是所有的运动(例如赛马——赛马和骑师、F1等)都真正有运动员,那么运动员应该追随这项运动吗?

2) ii) b) 1.1//horse_racing/gold_cup/2010

2) iii) a) 1.1/足球/球员/premier_league/2010_2011

2) iii) b) 1.1/horse_racing/horses/gold_cup/2010

下面是更多示例 URI...

1.1/players/football/premier_league/2010_2011/teams/{id}
返回球队赛季的球员?

1.1/球员/football/premier_league 回归英超联赛的球员?

1.1/结果/football/premier_league/2010_2011/teams/{id} 返回球队赛季的结果?

我还设想像...

1.1/football/premier_league/2010_2011/November/teams/{id}/results

这样的查询,其中月份作为参数来缩小结果集。

如果服务必须包括非体育实体,例如政治选举...就不会有玩家...

1.1/election/2012/parties/{id}/结果
返回政党

1.1/election/2012/parties/{id}/candidates 的结果 返回与政党有关的候选人

或 1.1/结果/election/2012/partys/{id} 返回政党

1.1/candidates/election/2012/parties/{id} 的结果 返回与政党相关的候选人

对于哪个层次结构更好有什么建议吗?我尝试过搜索这个网站和谷歌,但我发现的例子只涵盖了琐碎的情况。我想我赞成示例 2-iii。

提前致谢。

I'm trying to build a Rest based service that has broad data coverage of sports data (results/fixtures/teams/players/leagues etc.) and associated statistics.

Coming up with a suitable URI hierarchy has me going around in circles at the moment. For example I could implement...

1) i) version/sports/league/season/entity

1) ii) version/entity/sports/league/season

1) iii) version/sports/entity/league/season

An example makes things slightly clearer (hopefully)...

Take a query that is to return all football players that are playing in the premier league in the 2010/2011 season...

2) i) 1.1/football/premier_league/2010_2011/players

2) ii) a) 1.1/players/football//premier_league/2010_2011

But not all sports (e.g. horse racing - horse and jockey, F1 etc.) really have players, so should players come after the sport?

2) ii) b) 1.1/horses/horse_racing/gold_cup/2010

2) iii) a) 1.1/football/players/premier_league/2010_2011

2) iii) b) 1.1/horse_racing/horses/gold_cup/2010

More example URIs below...

1.1/players/football/premier_league/2010_2011/teams/{id}
returns players in team for season?

1.1/players/football/premier_league
returns players in the premier league?

1.1/results/football/premier_league/2010_2011/teams/{id}
returns results for team season ?

also I envisage queries like...

1.1/football/premier_league/2010_2011/November/teams/{id}/results

with the month acting as a parameter to narrow the result set.

If the service had to include non-sporting entities, say political elections...there would be no players...

1.1/election/2012/parties/{id}/results
returns results for the political party

1.1/election/2012/parties/{id}/candidates
returns the candidates associated with the party

or
1.1/results/election/2012/parties/{id}
returns results for the political party

1.1/candidates/election/2012/parties/{id}
returns the candidates associated with the party

Any advice on which hierarchy is better? I've tried searching this site and google, but the examples I've found have only covered trivial cases. I think I favour example 2-iii.

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

赠意 2024-10-11 14:29:49

我的建议是为您的实体创建包含所需最少信息的标识符。例如,

/sport/{unqiueId}
/player/{unqiueId}
/horse/{unqiueId}
/team/{unqiueId}
/league/{unqiueId}
/season/{unqiueId}
/result/{unqiueId}

请注意,我从 URL 中删除了版本,因为我坚信版本不属于 URL 的阵营。

一对一关系可以通过在响应中嵌入到实体的链接来处理:例如,

GET /player/234
=>
<Player Name="Kenny Dalglish">
   <Link rel="team" href="/team/732"/>
</Player>

一对多关系可以类似地处理,但它需要创建实体资源的子资源。

GET /team/732
=>
<team Name="Liverpool FC">
   <Link rel="players" href="/team/732/players"/>
</Player>

通常,您会发现此模式有用的各种场景:

/league/{unqiueId}/teams
/league/{unqiueId}/players
/season/{unqiueId}/teams
/league/{unqiueId}/seasons
/player/{unqiueId}/teams
/sport/{unqiueId}/teams
/sport/{unqiueId}/leagues
/sport/{unqiueId}/seasons

对于仅包含数据子集但属于常见查询的表示,可以使用查询字符串轻松创建它们并将其嵌入到结果中:

GET /league/891
=>
<league Name="Premiership">
   <link rel="leaderboard" href="/league/891/teams?startposition=1&endposition=10"/>
   <link rel="currentseason" href="/season/972"/>
   <link rel="lastseason" href="/season/842"/>
   <link rel="sport" href="/sport/1"/>
   <link rel="teams" href="/teams?league=891/>
</league>

这种类型的“api”的有趣特征之一”的问题是,客户端应用程序没有在客户端应用程序中构建关于如何构建 url 结构以发出请求的完整规则,而是采用不同的方法。客户端需要知道起始 URL 和 rel 属性值的含义。从那里,客户可以导航以获得它想要的东西。例如

,客户端不是基于服务器层次结构的硬编码知识构建请求,如下所示:

GET /Sport/Football/League/Premiership/Season/2011/Teams

相反,它导航到结果如下:

GET /
=>
<SportData>
  <Link rel="sport football" href="/sport/1"/>  <!-- Client finds this link -->
  <Link rel="sport horseracing" href="/sport/2"/>
  ...
</SportData>

GET /sport/1
=>
<Sport Name="Football">
  <Link rel="league premiership" href="/league/891"/>  <!-- Client finds this link -->
  ...
</Sport>

GET /league/891
=>
<League Name="Premiership">
  <Link rel="season 2011" href="/season/2334"/>  <!-- Client finds this link -->
  ...
</League>


GET /season/2334
=>
<Season Name="2011">
  <Link rel="teams" href="/season/2334/teams"/>  <!-- Client finds this link -->
  ...
</Season>

我意识到这看起来比第一个选项要多得多的工作,但是,它并不像看起来那么糟糕。使用缓存和书签可以大大减少往返次数。主要好处是您可以轻松更改服务公开的资源并在资源之间引入新的关系,而对客户端完全没有任何影响。

理想情况下,在基于 REST 的系统中,客户端和服务器之间的唯一耦合是根 URL 和来回发送的媒体类型。客户端不需要了解服务器的 URL 空间。

My advice would be to create identifiers for your entities that contain the minimum amount of information required. e.g.

/sport/{unqiueId}
/player/{unqiueId}
/horse/{unqiueId}
/team/{unqiueId}
/league/{unqiueId}
/season/{unqiueId}
/result/{unqiueId}

Note that I dropped version from the URL as I am firmly in the camp who believe versions don't belong in URLs.

One-to-one relationships can be handled by embedding links to entities in the response: e.g.

GET /player/234
=>
<Player Name="Kenny Dalglish">
   <Link rel="team" href="/team/732"/>
</Player>

One-to-Many relationships can be handled similarly but it requires creating a sub-resource of the entity resource.

GET /team/732
=>
<team Name="Liverpool FC">
   <Link rel="players" href="/team/732/players"/>
</Player>

Usually you will find all kind of scenarios where this pattern is useful:

/league/{unqiueId}/teams
/league/{unqiueId}/players
/season/{unqiueId}/teams
/league/{unqiueId}/seasons
/player/{unqiueId}/teams
/sport/{unqiueId}/teams
/sport/{unqiueId}/leagues
/sport/{unqiueId}/seasons

For representations that only contain subsets of data but are common queries they can easily be created using query strings and embedded into results:

GET /league/891
=>
<league Name="Premiership">
   <link rel="leaderboard" href="/league/891/teams?startposition=1&endposition=10"/>
   <link rel="currentseason" href="/season/972"/>
   <link rel="lastseason" href="/season/842"/>
   <link rel="sport" href="/sport/1"/>
   <link rel="teams" href="/teams?league=891/>
</league>

One of the interesting characteristics of this type of "api" is that instead of building a whole load of rules into your client application on how to build the url structure to make a request, the client application takes a different approach. The client needs to know the starting URL and the meaning of the rel attribute values. From there the client can just navigate to get what it wants. e.g.

Instead of the client building a request based on hardcoded knowledge of the server's hierarchy that looks like :

GET /Sport/Football/League/Premiership/Season/2011/Teams

instead it navigates it's way to the result like this:

GET /
=>
<SportData>
  <Link rel="sport football" href="/sport/1"/>  <!-- Client finds this link -->
  <Link rel="sport horseracing" href="/sport/2"/>
  ...
</SportData>

GET /sport/1
=>
<Sport Name="Football">
  <Link rel="league premiership" href="/league/891"/>  <!-- Client finds this link -->
  ...
</Sport>

GET /league/891
=>
<League Name="Premiership">
  <Link rel="season 2011" href="/season/2334"/>  <!-- Client finds this link -->
  ...
</League>


GET /season/2334
=>
<Season Name="2011">
  <Link rel="teams" href="/season/2334/teams"/>  <!-- Client finds this link -->
  ...
</Season>

I realize that this appears like a whole lot more work than the first option, however, it is not as bad as it looks. Using caching and bookmarks you can reduce the round trips considerably. The main benefit is that you can easily change the resources exposed by the service and introduce new relationships between resources without any effect on the client at all.

Ideally in a REST based system the only coupling between client and server is the root URL and the media-types that are sent back and forth. The client needs to know nothing about the URL space of the server.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文