Каков "правильный" способ создания отношений "многие ко многим" в Restful API
Я пытаюсь найти наилучшую практику для того, чтобы создать отношения "многие ко многим" в Restful API. Usecase действительно прост, но я не могу найти "правильный" способ сделать это.
В нашей модели у нас есть ребенок, которые связаны со многими отношениями к опекуну. В таблице отношений у нас есть 2 дополнительных параметра, типа (родитель, няня, чрезвычайная ситуация и т. д.) и активный (логический).
Вы можете только добавить опекун существующему ребенку, но существующий опекун может быть связан с другим ребенком.
Сегодня мы делаем это так
POST kids/{kidID}/guardians
{
"type": "parent"
"active": false
"guardian": {
"first_name": "foo"
"last_name": "bar"
}
}
Это создатьопекуна и добавить его к ребенку. Но с помощью этого метода мы не можем справиться с тем случаем, когда я хочу добавить существующего опекуна К ребенку. Вот ответы, которые я нашел, чтобы представить это, но я не знаю, какой из них является лучшим (и спокойным) способом (возможно, ни один из них они хорошие...):
Решение 1 - сохранить конечную точку как сегодня
Но поместите необязательное полеid в полеguardian . Если 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/
Даст вам всех опекунов, связанных с ребенком, но не этого
DELETE kids/{kidID}/guardians/{guardianID}
Воля удалите связь, а не опекуна .
Так что, как вы понимаете, я действительно заблудился и был бы признателен вам за помощь.С наилучшими пожеланиями,
2 ответа:
Нельзя ли создать третью категорию ресурсов для самого отношения, например "охранника", не подчиненного экземпляру других ресурсов? По-видимому, это рекомендуемый и обычный способ работы с отношениями n к n в базах данных.
Я думаю, что вы могли бы сделать это более спокойным, используя ссылки на каждый член отношения вместо числовых идентификаторов. И вы можете иметь поле типа " отношения "в представлениях детей и опекунов с URL+строкой запроса, необходимой для получения их конкретных" охранников", которые могут кому-то понадобиться.
GET /guards?kid="Johnny"
даст вам список отношений, которые вы могли бы использовать, чтобы получить все его опекуны.GET /guards?guard="Kelly"
, Вы можете догадаться./kids
и/guards
сохраняли бы данные только о самих ресурсах, и, вероятно, было бы проще поддерживать, чем если вы должны сохранить данные отношений как часть их.
Я пойду с ответом 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/ не будут представлять один и тот же вид ресурсов, но будут иметь одно и то же имя.