2

Я пытаюсь найти наилучшую практику для создания отношений «многие-ко-многим» в Restful API. Usecase действительно прост, но я не могу найти «right» способ сделать это.Что такое «правильный» способ создания отношений «многие ко многим» в Restful API

В нашей модели мы имеем Kid, которые связаны с много-ко-многим отношения к Хранителей. В таблице отношений у нас есть 2 дополнительных параметра: тип (родительский, няня, аварийный и т. Д.) И active (Boolean).

Вы можете только добавить Guardian, к существующим Kid, но существующий Гардиан может быть связь с другим Kid.

Сегодня мы делаем это как то

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

Это создает Guardian, и добавить его к Малышу. Но с помощью этого метода мы не сможем обрабатывать случай, когда я хочу добавить существующего 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 на Ressource по:

POST kids/{kidID}/kid-guardians/ 

Потому что это на самом деле не POST в «Гардиан» Ressource, но ребенок-опекун Ressource (отношения).Я не очень нравится, потому что со старым URI мы можем предположить, что более легко

GET kids/{kidID}/guardians/ 

Даст вам все Guardians, связанные с ребенком, но не то, что

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

Будет ли удалить а не Guardian.

Итак, как вы понимаете, я действительно потерян и буду благодарен вам за помощь.

С наилучшими пожеланиями,

ответ

1

не было бы возможно создать третью категорию ресурса для самого отношения, такие как «охранник», не подчинена к экземпляру других ресурсов? Представляется, что это рекомендуемый и обычный способ работы с n-n отношениями в базах данных.

GET /guards?kid="Johnny" предоставит вам список отношений, которые вы могли бы использовать для получения всех своих опекунов. GET /guards?guard="Kelly", вы можете догадаться. /kids и /guards будут хранить данные только о самих ресурсах и, вероятно, будет легче поддерживать, чем если бы вам приходилось хранить данные отношений как часть их.

Я думаю, что вы можете получить это более RESTful, используя ссылки на каждого члена отношений вместо числовых идентификаторов. И у вас может быть поле, подобное «отношениям» в представлениях детей и опекунов с URL + querystring, необходимыми для извлечения их конкретных «охранников», может кто-то в них нуждается.

+0

Благодарим вас за ответ. Я не поддерживал этот подход по нескольким причинам: ** 1 - ** Это звучит для меня скорее как мышление базы данных, чем REST. ** 2 - ** Является ли ** охранником ** EP действительно источником? Все CRUD не кажется мне полезным, мне действительно нужно GET guard/{guardID}? ** 3 - ** Не можем ли мы использовать ваш EP ** и ** kids/{kidID}/опекуны/для того, чтобы восстановить отношения. Еще раз спасибо за вашу помощь, возможно, это лучшее решение, и я совершенно не прав в отношении моей точки зрения RESTful – slaynerM

+0

** 1 ** - Я не эксперт ни в DB, ​​ни в REST, но это похоже на _modelling__ здесь , и если отношения являются чем-то важным для бизнес-модели, это действительно потенциальный ресурс в API. ** 2 ** - Если вы хотите получить данные о конкретных отношениях, и такие отношения могут прийти и уйти во времени, «GET/POST/PUT/DELETE/guard/{id}» имеет смысл, кажется, проще поддерживать и он даже может быть скрыт в клиентском приложении, за вашей идеей №3 (далее). ** 3 ** - Вы могли бы создать такой псевдоним, конечно, и одинаково «/ guardians/{id}/kids'. BTW Я не знаю, что означает «EP» :) Удача! –

0

Я пойду с Фабрисио 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}/" 
} 

«проблема» Я видел, с моими другими методами является то, что/дети/{kidID}/опекуны/а nd/guardians/не будут представлять один и тот же тип ресурсов, но имеют одно и то же имя.