REST 和多对多

REST and many to many

我的问题基于 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"
        },
        ...
    ]
}

当我只想向团队添加一名球员时,这迫使我更新球员资源。此外,当我使用玩家资源将玩家添加到团队时,相应的团队资源会自动更新。根据 How to handle many-to-many relationships in a RESTful API?

you don't want the alternate URL /players/5/teams/ to remain cached

在这种情况下,当我更新播放器 "John" 以从中删除团队 "Team 1" 时,teams/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" 或团队 "Team 1".

时,我们敞开心扉去合并冲突(和竞争条件)

关系的每一方都有自己的关系对象

GET /teams/1/players

产生类似

的东西
{
    "_links": [
        {
            "rel": "player",
            "href": "/players/john"
        },
        ...
    ]
}

GET /players/john/teams

类似

{
    "_links": [
        {
            "rel": "team",
            "href": "/teams/1"
        },
        ...
    ]
}

但是添加或删除一个可能仍会影响位于不同 URL(不共享根元素)的资源

我的问题

有没有解决我在这两个案例中提到的问题?

两种方法中哪一种是 'preferable' 或更纯粹的 REST?

我应该多认真对待 How to handle many-to-many relationships in a RESTful API? 中提到的约束:

you don't want the alternate URL /players/5/teams/ to remain cached

提前致谢!

您可以拥有以下内容

团队

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 补丁)(补丁 post 上的查询字符串...等虽然很少见,但有效)

PATCH /teams?player=john

[{
    "op": "add",
    "path": "/-",
    "value": {
        "href": "/team/dream"
    }
}]

获取 john 的团队

GET /teams?player=john

{
    "_links": {
    },
    "items": [
        {
            "href": "/teams/a-team"
        },
        {
            "href": "/teams/dream"
        }
    ]
}

John 离开了 A 队:

PATCH /teams?player=john

[{
    "op": "remove",
    "path": "/0"
}]