Jest to bardziej ogólne przeformułowanie tego pytania (z wyeliminowaniem określonych części Railsów)
Nie jestem pewien, jak zaimplementować paginację na zasobie w aplikacji sieci Web RESTful. Zakładając, że mam zasób o nazwie products
, który z poniższych według Ciebie jest najlepszym podejściem i dlaczego:
1. Używanie tylko ciągów zapytań
na przykład. http://application/products?page=2&sort_by=date&sort_how=asc
Problem polega na tym, że nie mogę używać pełnego buforowania stron, a także adres URL nie jest bardzo czysty i łatwy do zapamiętania.
2. Używanie stron jako zasobów i ciągów zapytań do sortowania
na przykład. http://application/products/page/2?sort_by=date&sort_how=asc
W takim przypadku widzi się problem polegający na tym, że http://application/products/pages/1
nie jest to unikalny zasób, ponieważ użycie sort_by=price
może dać zupełnie inny wynik i nadal nie mogę używać buforowania stron.
3. Używanie stron jako zasobów i segmentu adresów URL do sortowania
na przykład. http://application/products/by-date/page/2
Osobiście nie widzę problemu z użyciem tej metody, ale ktoś ostrzegł mnie, że nie jest to dobra droga (nie podał powodu, więc jeśli wiesz, dlaczego nie jest to zalecane, daj mi znać)
Wszelkie sugestie, opinie, krytyki są mile widziane. Dzięki.
źródło
Odpowiedzi:
Myślę, że problem z wersją 3 jest bardziej problemem z punktu widzenia - czy widzisz stronę jako zasób czy produkty na stronie.
Jeśli widzisz stronę jako zasób, jest to doskonałe rozwiązanie, ponieważ zapytanie o stronę 2 zawsze da stronę 2.
Ale jeśli widzisz produkty na stronie jako zasób, masz problem z tym, że produkty na stronie 2 mogą się zmienić (stare produkty usunięte lub cokolwiek innego), w tym przypadku identyfikator URI nie zawsze zwraca te same zasoby.
Np. Klient przechowuje link do strony X listy produktów, przy następnym otwarciu tego łącza dany produkt może już nie znajdować się na stronie X.
źródło
Zgadzam się z Fionn, ale pójdę o krok dalej i powiem, że strona nie jest zasobem, jest własnością żądania. To sprawia, że wybrałem tylko ciąg zapytania opcji 1. Po prostu czuje się dobrze. Naprawdę podoba mi się struktura interfejsu API Twittera . Niezbyt proste, niezbyt skomplikowane, dobrze udokumentowane. Na dobre lub na złe to mój projekt „idź do”, kiedy jestem na płocie i robię coś w jedną stronę w drugą stronę.
źródło
HTTP ma świetny nagłówek Range, który nadaje się również do stronicowania. Możesz wysłać
mieć tylko pierwszą stronę. Może to zmusić Cię do ponownego przemyślenia, co to jest strona. Może klient chce innej gamy produktów. Nagłówek zakresu działa również w celu zadeklarowania zamówienia:
aby wszystkie produkty były nowsze niż ta data lub
aby wszystkie produkty były starsze niż ta data. „0” prawdopodobnie nie jest najlepszym rozwiązaniem, ale RFC wydaje się chcieć czegoś na początek zakresu. Mogą być wdrożone parsery HTTP, które nie analizowałyby jednostek = -range_end.
Jeśli nagłówki nie są (akceptowalną) opcją, uważam, że pierwsze rozwiązanie (wszystko w ciągu zapytania) jest sposobem na radzenie sobie ze stronami. Ale proszę znormalizować ciągi zapytań (pary sortowania (klucz = wartość) w kolejności alfabetycznej). Rozwiązuje to problem różnicowania „? A = 1 & b = x” i „? B = x & a = 1”.
źródło
range-unit = bytes-unit | other-range-unit
Może masz na myśliThe only range unit defined by HTTP/1.1 is "bytes". HTTP/1.1 implementations MAY ignore ranges specified using other units.
To nie jest to samo, co twoje oświadczenie.Opcja 1 wydaje się najlepsza, o ile aplikacja postrzega paginację jako technikę tworzenia odmiennego widoku tego samego zasobu.
Powiedziawszy to, schemat adresów URL jest stosunkowo nieznaczny. Jeśli projektujesz aplikację tak, aby działała w oparciu o hipertekst (ponieważ wszystkie aplikacje REST muszą być z definicji), wtedy twój klient nie będzie sam tworzył żadnych identyfikatorów URI. Zamiast tego Twoja aplikacja będzie podawać linki do klienta, a klient będzie ich śledził.
Jednym z rodzajów linków, które może dostarczyć klient, jest link do stronicowania.
Przyjemnym efektem ubocznym tego wszystkiego jest to, że nawet jeśli zmienisz zdanie na temat struktury URI paginacji i zaimplementujesz coś zupełnie innego w przyszłym tygodniu, Twoi klienci mogą kontynuować pracę bez żadnych modyfikacji.
źródło
Zawsze korzystałem ze stylu opcji 1. Buforowanie nie stanowiło problemu, ponieważ dane i tak często się zmieniają w moim przypadku. Jeśli zezwolisz na konfigurację rozmiaru strony, ponownie nie będzie można buforować danych.
Nie uważam adresu URL za trudny do zapamiętania lub nieczysty. Dla mnie jest to dobre wykorzystanie parametrów zapytania. Zasób jest wyraźnie listą produktów, a parametry zapytania mówią tylko, jak chcesz wyświetlić listę - posortowaną i na której stronie.
źródło
Dziwne, że nikt nie zauważył, że Opcja 3 ma parametry w określonej kolejności. http // aplikacja / produkty / data / malejąco / nazwa / rosnąco / strona / 2 i http // aplikacja / produkty / nazwa / rosnąco / data / malejąco / strona / 2
wskazują na ten sam zasób, ale mają zupełnie inne adresy URL.
Dla mnie opcja 1 wydaje się najbardziej akceptowalna, ponieważ wyraźnie oddziela „Co chcę” i „Jak chcę” (ma nawet znak zapytania między nimi lol). Buforowanie całej strony można wdrożyć przy użyciu pełnego adresu URL (wszystkie opcje i tak będą miały ten sam problem).
Przy podejściu Parameters-in-URL jedyną korzyścią jest czysty adres URL. Chociaż musisz wymyślić jakiś sposób na kodowanie parametrów i bezstratne ich dekodowanie. Oczywiście możesz przejść z URLencode / decode, ale to znowu sprawi, że adresy URL będą brzydkie :)
źródło
Wolę używać przesunięcia i ograniczenia parametrów zapytania.
offset : dla indeksu pozycji w kolekcji.
limit : do zliczenia przedmiotów.
Klient może po prostu aktualizować przesunięcie w następujący sposób
na następną stronę.
Ścieżka jest uważana za identyfikator zasobu. A strona nie jest zasobem, ale podzbiorem kolekcji zasobów. Ponieważ paginacja jest ogólnie żądaniem GET, parametry zapytania najlepiej nadają się do paginacji, a nie nagłówków.
Odniesienie: https://metamug.com/article/rest-api-developers-dilemma.html#Requesting-the-next-page
źródło
W poszukiwaniu najlepszych praktyk natknąłem się na tę stronę:
http://www.restapitutorial.com
Na stronie zasobów znajduje się link do pobrania pliku .pdf, który zawiera kompletne najlepsze praktyki REST sugerowane przez autora. W którym między innymi znajduje się sekcja na temat paginacji.
Autor sugeruje dodanie obsługi zarówno przy użyciu nagłówka Range, jak i parametrów ciągu zapytania.
Żądanie
Przykład nagłówka HTTP:
Przykład parametrów ciągu zapytania:
Gdzie przesunięcie jest początkowym numerem przedmiotu, a limit to maksymalna liczba przedmiotów do zwrotu.
Odpowiedź
Odpowiedź powinna zawierać nagłówek Content-Range wskazujący, ile elementów jest zwracanych i ile elementów istnieje jeszcze do odzyskania
Przykłady nagłówków HTTP:
W pliku pdf znajdują się inne sugestie dotyczące bardziej szczegółowych przypadków.
źródło
Obecnie używam schematu podobnego do tego w moich aplikacjach ASP.NET MVC:
na przykład
http://application/products/by-date/page/2
konkretnie jest to:
http://application/products/Date/Ascending/3
Jednak nie jestem zadowolony z włączenia w ten sposób informacji stronicowania i sortowania do trasy.
Lista przedmiotów (w tym przypadku produktów) jest zmienna. tj. następnym razem, gdy ktoś powróci do adresu URL zawierającego parametry stronicowania i sortowania, wyniki, które otrzymają, mogły ulec zmianie. Tak więc pomysł
http://application/products/Date/Ascending/3
na unikalny adres URL wskazujący określony, niezmienny zestaw produktów został utracony.źródło
Zgadzam się ze slf, że „strona” nie jest tak naprawdę zasobem. Z drugiej strony opcja 3 jest czystsza, łatwiejsza do odczytania, a użytkownik może ją łatwiej odgadnąć, a nawet wpisać w razie potrzeby. Jestem rozdarty pomiędzy opcjami 1 i 3, ale nie widzę żadnego powodu, aby nie używać opcji 3.
Ponadto, chociaż wyglądają ładnie, jednym z minusów używania ukrytych parametrów, jak ktoś wspomniał, zamiast ciągów zapytań lub segmentów adresów URL jest to, że użytkownik nie może utworzyć zakładki ani bezpośrednio przejść do konkretnej strony. W zależności od aplikacji może to być problem, ale może to być coś, o czym należy pamiętać.
źródło
Używałem wcześniej rozwiązania 3 (piszę DUŻO aplikacji django). I nie sądzę, żeby było w tym coś złego. Jest tak samo generowalny jak pozostałe dwa (w tym przypadku musisz wykonać masowe skrobanie itp.) I wygląda na czystszy. Ponadto użytkownicy mogą odgadnąć adresy URL (jeśli jest to aplikacja publiczna), a ludzie lubią być w stanie iść bezpośrednio tam, gdzie chcą, a odgadywanie adresów URL jest silniejsze.
źródło
Używam w moich projektach następujących adresów URL:
co oznacza - „podaj mi drugą stronę uporządkowaną rosnąco według pola 1, a następnie malejąco według pola 2”. Lub jeśli potrzebuję jeszcze większej elastyczności, używam:
źródło
Używam następujących wzorów, aby uzyskać rekord następnej strony. http: // application / products? lastRecordKey =? & pageSize = 20 & sort = ASC
RecordKey to kolumna tabeli, która zawiera wartość sekwencyjną w DB. Służy do pobierania tylko jednej strony danych z DB. pageSize służy do określenia liczby rekordów do pobrania. Sortuj służy do sortowania rekordu w kolejności rosnącej lub malejącej.
źródło