Какой лучший метод RESTful возвращает общее количество элементов в объекте?

Вопрос:

Я разрабатываю службу REST API для большого сайта социальных сетей Im, в который участвует. Пока что он работает отлично. Я могу выдавать GET, POST, PUT и DELETE запросы на URL-адреса объектов и влиять на мои данные. Однако эти данные выгружаются (ограничено 30 результатами за раз).

Однако какой лучший способ RESTful получить общее количество участников, через мой API?

В настоящее время я выдаю запросы к структуре URL-адреса, например:

  • /api/members – возвращает список участников (30 за раз, как указано выше)
  • /api/members/1 -Аффект одного члена, в зависимости от используемого метода запроса

Мой вопрос: как я мог бы использовать аналогичную структуру URL, чтобы получить общее количество участников в моем приложении? Очевидно, что запрос только поля id (аналогичный API-интерфейсу Facebooks) и подсчет результатов будет неэффективным, если только только половина результатов будет возвращена только.

Лучший ответ:

В то время как ответ на/API/пользователи выгружается и возвращает только 30 записей, ничего не мешает вам включить в ответ также общее количество записей и другую соответствующую информацию, такую ​​как размер страницы, номер страницы/смещение и т.д.

API StackOverflow – хороший пример того же проекта. Здесь документация для метода Users – https://api.stackexchange.com/docs/users

Ответ №1

Я предпочитаю использовать HTTP-заголовки для такого рода контекстуальной информации.

Для общего количества элементов я использую заголовок X-total-count.
Для ссылок на следующую, предыдущую страницу и т.д. Я использую http link header:
http://www.w3.org/wiki/LinkHeader

Github делает то же самое: https://developer.github.com/v3/#pagination

По-моему, он более чистый, так как он может использоваться также при возврате содержимого, которое не поддерживает гиперссылки (например, бинарные файлы, изображения).

Ответ №2

Альтернатива, если вам не нужны фактические элементы

Ответ Franci Penov – это, безусловно, лучший способ, чтобы вы всегда возвращали предметы вместе со всеми дополнительными метаданными о запрошенных вами сущностях. То, как это должно быть сделано.

но иногда возвращение всех данных не имеет смысла, потому что они могут вообще не нуждаться в них. Возможно, все, что вам нужно, это метаданные о запрошенном ресурсе. Как общее количество или количество страниц или что-то еще. В таком случае вы всегда можете запросить URL-запрос, чтобы ваша служба не возвращала элементы, а просто метаданные:

/api/members?metaonly=true
/api/members?includeitems=0

или что-то подобное…

Ответ №3

Вы можете вернуть счет как пользовательский HTTP-заголовок в ответ на запрос HEAD. Таким образом, если клиенту требуется только подсчет, вам не нужно возвращать фактический список, и нет необходимости в дополнительном URL-адресе.

(Или, если вы находитесь в контролируемой среде от конечной точки до конечной точки, вы можете использовать собственный HTTP-глагол, такой как COUNT.)

Ответ №4

В последнее время я занимаюсь некоторыми обширными исследованиями этого и других вопросов, связанных с поисковым вызовом REST, и подумал, что это конструктивно, чтобы добавить некоторые мои выводы здесь. Я немного расширяю вопрос, чтобы включить мысли о пейджинге, а также счет, поскольку они связаны друг с другом.

Заголовки

Метаданные подкачки включаются в ответ в виде заголовков ответов. Большим преимуществом такого подхода является то, что сама полезная нагрузка ответа – это просто запрос, который запрашивал фактический запрос данных. Более легкая обработка ответов для клиентов, которые не заинтересованы в информации поискового вызова.

Существует множество (стандартных и настраиваемых) заголовков, используемых в дикой природе, для возврата информации, связанной с поисковым вызовом, включая общее количество.

X-Total-Count

X-Total-Count: 234

Это используется в some API, который я нашел в дикой природы. Существуют также пакеты NPM для добавления поддержки этого заголовка, например. Loopback. Некоторые статьи рекомендуют также установить этот заголовок.

Он часто используется в сочетании с заголовком Link, что является довольно хорошим решением для поискового вызова, но не содержит общей информации о счете.

Ссылка

Link: </TheBook/chapter2>;
rel="previous"; title*=UTF-8'de'letztes%20Kapitel,
</TheBook/chapter4>;
rel="next"; title*=UTF-8'de'n%c3%a4chstes%20Kapitel

Я считаю, что, читая много на эту тему, общий консенсус заключается в том, чтобы использовать заголовок Link для предоставления пейджинговых ссылок на клиентов, использующих rel=next, rel=previous и т.д. Проблема заключается в том, что ему не хватает информации о количестве общих записей, поэтому многие API сочетают это с заголовком X-Total-Count.

Альтернативно, некоторые API и, например, JsonApi, используйте формат Link, но добавьте информацию в конверт ответа вместо заголовка. Это упрощает доступ к метаданным (и создает место для добавления общей информации о счете) за счет увеличения сложности доступа к фактическим данным (добавлением конверта).

Content-Range

Content-Range: items 0-49/234

Продвижение статьи в блоге под названием Заголовок диапазона, я выбираю вас (для разбивки на страницы)!. Автор делает большой аргумент в пользу использования заголовков Range и Content-Range для разбивки на страницы. Когда мы внимательно прочитаем RFC в этих заголовках, мы обнаруживаем, что расширение их значения за пределами диапазонов байтов фактически ожидалось RFC и явно разрешено. При использовании в контексте items вместо bytes заголовок Range фактически дает нам способ как запросить определенный диапазон элементов, так и указать, к какому диапазону итогового результата относятся элементы ответа. Этот заголовок также дает отличный способ показать общее количество. И это истинный стандарт, который в основном отображает “один к одному” на пейджинг. Это также используется в дикой природе.

Конверт

Многие API-интерфейсы, в том числе из нашего любимого веб-сайта Q & используют конверт, обертку вокруг данных, которые используются для добавления метаинформации о данных. Кроме того, OData и JsonApi стандарты используют конверт ответа.

Большой недостаток этого (imho) заключается в том, что обработка данных ответа становится более сложной, поскольку фактические данные должны быть найдены где-то в конверте. Также есть много разных форматов для этого конверта, и вы должны использовать правильный. Это говорит о том, что отклики ответа от OData и JsonApi сильно отличаются друг от друга, смешивая OData в метаданных в нескольких точках ответа.

Отдельная конечная точка

Я думаю, что это было достаточно полно рассмотрено в других ответах. Я не расследовал это, потому что согласен с комментариями, что это путает, поскольку у вас теперь есть несколько типов конечных точек. Я думаю, что это красиво, если каждая конечная точка представляет собой (набор) ресурсов (ов).

Дальнейшие мысли

Мы не только должны сообщать метаинформацию поискового вызова, связанную с ответом, но также разрешать клиенту запрашивать конкретные страницы/диапазоны. Интересно также взглянуть на этот аспект, чтобы в итоге получить согласованное решение. Здесь также можно использовать заголовки (заголовок Range кажется очень подходящим) или другие механизмы, такие как параметры запроса. Некоторые люди выступают за обработку страниц результатов в виде отдельных ресурсов, что может иметь смысл в некоторых случаях использования (например, /books/231/pages/52). В итоге я выбрал дикий диапазон часто используемых параметров запроса, таких как pagesize, page[size] и limit etc в дополнение к поддержке заголовка Range (и как параметр запроса также).

Ответ №5

Я бы рекомендовал добавлять заголовки для них, например:

HTTP/1.1 200

Pagination-Count: 100
Pagination-Page: 5
Pagination-Limit: 20
Content-Type: application/json

[
{
"id": 10,
"name": "shirt",
"color": "red",
"price": "$23"
},
{
"id": 11,
"name": "shirt",
"color": "blue",
"price": "$25"
}
]

Подробнее см.

https://github.com/adnan-kamili/rest-api-response-format

Для файла swagger:

https://github.com/adnan-kamili/swagger-response-template

Ответ №6

Как насчет новой конечной точки > /api/members/count, которая просто вызывает Member.Count() и возвращает результат

Ответ №7

Кажется проще всего добавить

GET
/api/members/count

и вернуть общее количество членов

Ответ №8

Иногда фреймворки (например, $resource/AngularJS) требуют массива в качестве результата запроса, и вы не можете иметь такой ответ, как {count:10,items:[...]}, в этом случае я храню “count” в responseHeaders.

Р. S. Фактически вы можете сделать это с помощью $resource/AngularJS, но для этого нужны некоторые настройки.

Ответ №9

При запросе разбитых на страницы данных вы знаете (с помощью значения параметра размера страницы или значения размера страницы по умолчанию) размер страницы, поэтому вы знаете, получили ли вы все данные в ответ или нет. Когда в ответе меньше данных, чем размер страницы, вы получаете целые данные. Когда возвращается полная страница, вам нужно снова спросить о другой странице.

Я предпочитаю иметь отдельную конечную точку для count (или такую ​​же конечную точку с параметром countOnly). Поскольку вы можете подготовить конечного пользователя к длительному/трудоемкому процессу, показывая правильно подготовленную панель прогресса.

Если вы хотите вернуть данные в каждом ответе, должно быть указано значение pageSize, а также смещение смещения. Честно говоря, лучшим способом является повторение фильтров запросов. Но ответ стал очень сложным. Поэтому я предпочитаю выделенную конечную точку для возврата счетчика.

<data>
<originalRequest>
<filter/>
<filter/>
</originalReqeust>
<totalRecordCount/>
<pageSize/>
<offset/>
<list>
<item/>
<item/>
</list>
</data>

Couleage my, предпочитаю параметр countOnly для существующей конечной точки. Таким образом, при указании ответ содержит только метаданные.

конечная точка? = Значение фильтра

<data>
<count/>
<list>
<item/>
...
</list>
</data>

конечная точка фильтра = значение &? CountOnly = истина

<data>
<count/>
<!-- empty list -->
<list/>
</data>

Оцените статью
TechArks.Ru
Добавить комментарий