我的问题基于How to handle many-to-many relationships in a RESTful API?,但我想继续接受已接受的答案。
假设我们在球员和球队之间有多对多的关系(就像上面提到的问题一样)。
据我了解,有几种方法可以使用REST资源对此进行建模:
有效负载包含对相关资源的引用
GET /players/john
产量
{
"name": "John",
"_links": [
{
"rel": "team",
"href": "/teams/1"
},
{
"rel": "team",
"href": "/teams/4"
}
]
}
和
GET /teams/1
产量
{
"name": "Team 1",
"_links": [
{
"rel": "player",
"href": "/players/john"
},
...
]
}
当我只想向玩家添加玩家时,这迫使我更新玩家资源。此外,当我使用播放器资源向玩家添加玩家时,相应的团队资源会自动更新。根据{{3}}:
您不希望备用网址/玩家/ 5 /球队/保持缓存
在这种情况下,当我更新播放器" John"时,团队/ 1可能会保持缓存状态。删除团队"团队1"从它!
该关系被建模为另一种资源
GET /teams/1
产量
{
"name": "Team 1",
}
和
GET /players/john
产量
{
"name": "John",
}
最后,
GET /relationships
产量
[
{
"_links": [
{
"rel": "player",
"href": "/players/john"
},
{
"rel": "team",
"href": "/teams/1"
}
]
},
...
]
这样,我可以创建和删除关系,而不会影响播放器资源和团队资源。但是当我删除/ players / john时,是否应该自动删除匹配关系?如果是这种情况,则违反与上述相同的规则。如果不是这种情况,我们需要手动删除这些关系,这是很多工作,我不想让我的API的消费者负担。
此外,如果我们想要更新团队某个玩家" John"在,我们需要删除一些关系并添加其他关系。当其他人正在编辑玩家时,我们将自己开放合并冲突(和竞争条件)" John"或团队"团队1"。
关系的每一方都有自己的关系对象
GET /teams/1/players
产生类似
的东西{
"_links": [
{
"rel": "player",
"href": "/players/john"
},
...
]
}
和
GET /players/john/teams
类似
{
"_links": [
{
"rel": "team",
"href": "/teams/1"
},
...
]
}
但添加或删除一个可能仍然会影响位于不同URL(不共享根元素)的资源
我的问题
在这两种情况下,我提到的问题是否存在?
这两种方法中哪一种更可取?'或更纯粹的REST?
我应该认真对待How to handle many-to-many relationships in a RESTful API?中提到的约束:
您不希望备用网址/玩家/ 5 /球队/保持缓存
提前谢谢!
答案 0 :(得分:1)
您可以拥有以下
队
GET /teams/dream
{
"_links": {
"self": {
"href": "/teams/dream"
}
"players": {
"href": "/players?team=dream"
}
},
"name": "Dream"
}
播放器
GET /player/john
{
"_links": {
"self": {
"href": "/player/john"
},
"teams": {
"href": "/teams?player=john"
},
},
"name": "John",
}
John的团队
GET /teams?player=john
{
"_links": {
},
"items": [
{
"href": "/teams/a-team"
}
],
}
将john添加到梦之队,(例如使用json补丁)(补丁帖子上的查询字符串......等虽然很少见,但是有效)
PATCH /teams?player=john
[{
"op": "add",
"path": "/-",
"value": {
"href": "/team/dream"
}
}]
获得约翰的团队
GET /teams?player=john
{
"_links": {
},
"items": [
{
"href": "/teams/a-team"
},
{
"href": "/teams/dream"
}
]
}
约翰离开了一个团队:
PATCH /teams?player=john
[{
"op": "remove",
"path": "/0"
}]