Вопрос API REST о том, как обращаться с коллекциями настолько эффективно, насколько это возможно, но все еще соответствует принципам REST

Im довольно новый для REST, но насколько я понял, я понимаю, что следующий URL-адрес соответствует принципам REST. Где ресурсы распределяются следующим образом:

/user/<username>/library/book/<id>/tags
          ^         ^           ^   ^
          |---------|-----------|---|- user resource with username as a variable
                    |-----------|---|- many to one collection (books)
                                |---|- book id 
                                    |- many to one collection (tags)


GET /user/dave/library/book             //retrieves a list of books id's
GET /user/dave/library/book/1           //retrieves info on book id=1
GET /user/dave/library/book/1/tags      //retrieves tags collection (book id=1)

Однако как можно оптимизировать этот пример API? Скажем, например, у меня есть 10K книг в моей библиотеке, и я хочу получить детали каждой книги в своей библиотеке. должен ли я действительно заставить http-вызов /library/book/<id> для каждого идентификатора, указанного в /library/book? Или я должен включить несколько идентификаторов в качестве параметров? /library/book/<id1>,<id2>... и делать то же самое, что и массовое извлечение со 100 id за раз?

Что говорят принципы REST об этой ситуации? и каковы ваши мнения?

Еще раз спасибо.

Ответ 1

Это строго вопрос дизайна.

Я мог бы определить ресурс bookc и использовать его так:

GET /user/dave/library/book?bookList=...

как вы далее указываете аргумент bookList, это действительно вопрос того, какое использование вы планируете использовать для этого ресурса. У вас может быть, например:

GET /user/dave/library/book?bookList=1-10
GET /user/dave/library/book?bookList=1,2,5,20-25

или вы можете просто просмотреть все книги:

GET /user/dave/library/book?page=7&pagesize=50

Но, на мой взгляд, особенно форма с длинным списком "случайных" идентификаторов кажется довольно непригодной. Возможно, я бы вместо этого определил параметр filter, чтобы указать:

GET /user/dave/library/book?filter=key,value&filter=key,value

Что касается вашего вопроса об ограничении длины URL-адреса HTTP, стандарт не устанавливает никаких параметров. Но браузер может меняться... посмотрите на это S.O. тема

Чтобы быть более строго RESTful, параметр запроса может быть указан через HTTP-заголовки, но общая идея, которую я хотел передать, не изменяется.

Надеюсь, это вам подходит...

Ответ 2

Выше выглядит хорошо, но я бы изменил на множественные имена, он читает лучше:


/users/{username}/books/{bookId}

То, что я не понимаю, является прецедентом передачи списка идентификаторов, разделенных запятыми. Вопрос в том, как вы добираетесь до идентификаторов? Я думаю, что за списком идентификаторов есть семантика, т.е. Они представляют собой результат фильтра. Поэтому вместо прохождения идентификаторов я бы поискал api. Упрощенный пример:


/users/dave/books?puchasedAfter=2011-01-01
 

Если вы хотите перебирать свою коллекцию книг в 10K, используйте параметры поискового вызова.

Ответ 3

Это только мое мнение:

GET /user/dave/library/book/IDList      //retrieves a list of books id's
or
GET /user/dave/library/bookID           //retrieves a list of books id's

GET /user/dave/library/book             //retrieves a list of books
GET /user/dave/library/book/1           //retrieves info on book id=1
GET /user/dave/library/book/1-3         //retrieves info on book id>=1 and id <=3
GET /user/dave/library/book/1/tags      //retrieves tags collection (book id=1)

Ответ 4

Вы можете использовать paginator

Некоторый успокоительный API работает с paginator для огромных ресурсов, таких как:

http://example.org/api/books?page=2

Сервер обеспечивает, например, 100 записей (в данном случае книг) на страницу. И вы можете сортировать книги, используя sortby в своем запросе на получение. С вышеуказанным запросом вы получите книги 101-200 (если их так много в базе данных). Ответ может рассказать вам что-то о количестве книг и количестве страниц, что является следующей страницей и предыдущей страницей, но затем вы больше переходите к HATEOAS.

В противном случае, если вы хотите получить определенный id, я бы сделал это следующим образом:

http://example.org/books?id=[]2&id=[]5&id=[]7&id=[]21

Запрос get с массивом id (id = [2,5,7,21]), который возвращает книги с соответствующими идентификаторами