在Restful API中创建多对多关系的“正确”方法是什么

时间:2016-10-31 20:15:25

标签: rest entity-relationship restful-architecture restful-url nested-resources

我尝试找到最佳实践,以便在Restful API中创建多对多关系。用例非常简单,但我无法真正找到“正确的”方式。

在我们的模型中,我们有 Kid Guardian 的多对多关系相关。在关系表中,我们有2个额外的参数, type (父,保姆,紧急等)和活动(布尔)。

您只能将 Guardian 添加到现有的 Kid ,但现有的 Guardian 可以与其他 Kid 链接>

今天,我们这样做

POST kids/{kidID}/guardians
{
    "type": "parent"
    "active": false 
    "guardian": {
        "first_name": "foo"
        "last_name": "bar"
    }
}

这会创建 Guardian 并将其添加到Kid。但是,通过这种方法,我们无法处理我想将现有 Guardian 添加到 Kid 的情况。在这里我找到的答案是为了表示这一点,但我不知道哪一个是最好的(和宁静的)方式(可能没有一个是好的......):

解决方案1 ​​ - 将端点保持为今天

但是将非强制性 id 字段添加到监护人。如果 id 为空,则API必须创建ressource,否则只需检索它并在需要时更新值。

POST kids/{kidID}/guardians/
{
    "type": "parent"
    "active": false 
    "guardian": {
        "id": "ab65f263-dd3d-bbc6-8b7b-57a3b4b26c21"
    }
}

解决方案2 - 在2次通话中断开此终点

# Create the Guardian
POST guardians/
{
    "first_name": "foo"
    "last_name": "bar"
}

# This method can only "link" the models
POST kids/{kidID}/guardians/
{
    "type": "parent"
    "active": false 
    "guardian_id": "ab65f263-dd3d-bbc6-8b7b-57a3b4b26c21"
}

[已编辑]解决方案2.5 - 使用PUT创建关系

和以前一样,你必须创建监护人,但为了添加你创建的关系

PUT kids/{kidID}/guardians/{guardianID}
{
    "type": "parent"
    "active": false 
}

子公司解决方案:在第二个选择中,我们可以通过以下方式更改资源的URI:

POST kids/{kidID}/kid-guardians/

因为它并没有真正发布一个“监护人”的资源,而是一个孩子 - 监护人的资源(关系)。我真的不喜欢它,因为使用旧URI我们可以更容易地假设

GET kids/{kidID}/guardians/

会给你所有与孩子相关的 Guardians ,但不是

DELETE kids/{kidID}/guardians/{guardianID}

将删除关系,而不是 Guardian

据你了解,我真的迷路了,非常感谢你的帮助。

致以最诚挚的问候,

2 个答案:

答案 0 :(得分:1)

不可能为关系本身创建第三类资源,例如“guard”,而不是从属于其他资源的实例?它似乎是处理数据库中n到n关系的推荐和常用方法。

GET /guards?kid="Johnny"会为您提供一系列关系,您可以使用这些关系来获取所有监护人。 GET /guards?guard="Kelly",你可以猜到。 /kids/guards只会保留有关资源本身的数据,并且可能比您必须将关系数据作为其中一部分更容易维护。

我认为通过使用指向关系的每个成员的链接而不是数字ID,您可以获得更多RESTful。并且您可以在孩子和监护人表示中使用“关系”这样的字段,并使用URL +查询字符串来检索他们需要的特定“警卫”。

答案 1 :(得分:1)

我将使用Fabricio Rocha回答,实现如下:

POST guardian-kids/
{
    "type": "parent",
    "guardian": {
        "id": "{guardianId}"
    },
    "kid":{
        "id": "{kidId}"
    }
}

如果你想找回守护孩子

GET guardian-kids/{GuardianKidId}
{
    "type": "parent",
    "guardian": {
        "id": "{guardianId}",
        "url": "guardians/{guardianId}/"
    },
    "kid": {
        "id": "{kidId}",
        "url": "kids/{kidId}/"
    },
    "url": "guardian-kids/{GuardianKidId}/"
}

我也制作了这两个终点(你只能获得那些)

GET kids/{kidId}/guardian-kids
{
    "type": "parent",
    "guardian": {
        "id": "{guardianId}",
        "url": "guardians/{guardianId}/"
    },
    "kid": {
        "id": "{kidId}",
        "url": "kids/{kidId}/"
    },
    "url": "guardian-kids/{GuardianKidId}/"
}

GET guardians/{guardianId}/guardian-kids
{
    "type": "parent",
    "guardian": {
        "id": "{guardianId}",
        "url": "guardians/{guardianId}/"
    },
    "kid": {
        "id": "{kidId}",
        "url": "kids/{kidId}/"
    },
    "url": "guardian-kids/{GuardianKidId}/"
}

"问题"我用其他方法看到/ kids / {kidID} / guardians /和/ guardians /不会代表相同类型的资源,但具有相同的名称。