savostin
@savostin
Еще один программист

Какова должна быть вложенность возвращаемых данных в RESTful API?

Есть стандартная структура данных:
user_id
user_name
user_...

-----

group_id
group_user
group_name
group_...

-----

item_id
item_group
item_name
item_...


Допустим вызываем метод GET items (скажем top N по дате). Результат должен быть:
items : [
{id : 1, name : 'Name 1', group : 1},
{id : 2, name : 'Name 2', group : 1},
{id : 3, name : 'Name 3', group : 2},
{id : 4, name : 'Name 4', group : 3}
]
или
items : [
{id : 1, name : 'Name 1', group : 1, user: 1},
{id : 2, name : 'Name 2', group : 1, user: 1},
{id : 3, name : 'Name 3', group : 2, user: 1},
{id : 4, name : 'Name 4', group : 3, user: 2}
]
или
items : [
{id : 1, name : 'Name 1', group : {id : 1, name: 'Group 1', user: 1}},
{id : 2, name : 'Name 2', group : {id : 1, name: 'Group 1', user: 1}},
{id : 3, name : 'Name 3', group : {id : 2, name: 'Group 2', user: 1}},
{id : 4, name : 'Name 4', group : {id : 3, name: 'Group 3', user: 2}}
]
или
items : [
{id : 1, name : 'Name 1', group : {id : 1, name: 'Group 1', user: {id: 1, name: 'User 1'}}},
{id : 2, name : 'Name 2', group : {id : 1, name: 'Group 1', user: {id: 1, name: 'User 1'}}},
{id : 3, name : 'Name 3', group : {id : 2, name: 'Group 2', user: {id: 1, name: 'User 1'}}},
{id : 4, name : 'Name 4', group : {id : 3, name: 'Group 3', user: {id: 2, name: 'User 2'}}}
]
или
{ 
items : [
{id : 1, name : 'Name 1', group : 1},
{id : 2, name : 'Name 2', group : 1},
{id : 3, name : 'Name 3', group : 2},
{id : 4, name : 'Name 4', group : 3}
], 
groups : [
{id: 1, name: 'Group 1', user: 1},
{id: 2, name: 'Group 2', user: 1},
{id: 3, name: 'Group 3', user: 2}
], 
users : [
{id: 1, name: 'User 1'},
{id: 2, name: 'User 2'}
]
}


Первый способ наиболее аскетичный, универсальный, но в 99.9% случаях потребует от клиента отправить еще кучу запросов для нормального отображения информации (получить все groups и users по их id). Из плюсов - простота запросов на стороне сервера (все по PRIMARY KEY), никаких JOIN.
spoiler
Однако, в реальной жизни это далеко не так: например нужно исключить items "забаненных" users -> JOIN на groups и users.

Предпоследний способ наиболее полный, но информация сильно дублируется. Особенно не ясно что туда включать при наличии большого количества полей user_... и group_... Видел, что в некоторых API можно указать что именно получать, но имхо это как-то неудобно указывать в запросе кучу параметров. И откуда взять их состав, схема нужна?

Последний имхо самый оптимальный - в ответе есть все, что нужно для отображения именно этих items, данные не дублируются (во всяком случае в пределах этого запроса). А вот скажем с постраничным выводом будут вопросы: на "второй странице" опять вернутся уже (возможно) полученные users и groups, а возможно каких-то не было. Но все равно данных и дополнительных запросов будет значительно меньше, чем в остальных вариантах. И, если честно, я такого подхода нигде не видел. Это "нормально"?

Как вообще "правильно" возвращать связанные данные? Как понять что понадобится клиенту API?
  • Вопрос задан
  • 682 просмотра
Пригласить эксперта
Ответы на вопрос 3
@korotkin
Все, абсолютно все, на что есть ID грузить отдельно (общий запрос за метаданными на сервер при инициализации, включение нужных в объект в виде обобщенной таблицы.. .море вариантов). На фронте разберутся как собрать в кучу.
Иначе получите огромный оверхед на адаптацию данных и неочевидные наборы данных. Более того, в случае обновления данных в реальном времени вам придется перекапывать уже полученные объекты и что-нибудь пересчитывать (здесь как повезет).
Ответ написан
@four4
Исходить нужно из того, чтобы:
1. Программисту, использующему ваше API, было максимально понятно. Это главное.
2. Скорость важна, но это вторично после понятности.
Ответ написан
@springimport
Коротко: здравый смысл.
Я бы соблюдал баланс. В местах где явно понадобятся дополнительные данные можно заранее их включить. Однозначного ответа нет, к сожалению.

Вам точно понравится graphql. Он призван решить проблемы по типу вашей.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы