Ini adalah reformulasi yang lebih umum dari pertanyaan ini (dengan menghilangkan bagian-bagian spesifik Rails)
Saya tidak yakin bagaimana menerapkan pagination pada sumber daya dalam aplikasi web yang tenang. Dengan asumsi bahwa saya memiliki sumber daya yang disebut products
, menurut Anda yang manakah di bawah ini yang merupakan pendekatan terbaik, dan mengapa:
1. Hanya menggunakan string kueri
misalnya. http://application/products?page=2&sort_by=date&sort_how=asc
Masalahnya di sini adalah bahwa saya tidak dapat menggunakan caching halaman penuh dan juga URL tidak sangat bersih dan mudah diingat.
2. Menggunakan halaman sebagai sumber daya dan string kueri untuk menyortir
misalnya. http://application/products/page/2?sort_by=date&sort_how=asc
Dalam hal ini, masalah yang dilihat adalah bahwa http://application/products/pages/1
itu bukan sumber daya yang unik karena menggunakan sort_by=price
dapat menghasilkan hasil yang sama sekali berbeda dan saya masih tidak dapat menggunakan caching halaman.
3. Menggunakan halaman sebagai sumber daya dan segmen URL untuk menyortir
misalnya. http://application/products/by-date/page/2
Saya pribadi tidak melihat masalah dalam menggunakan metode ini, tetapi seseorang memperingatkan saya bahwa ini bukan cara yang baik untuk pergi (dia tidak memberikan alasan, jadi jika Anda tahu mengapa itu tidak disarankan, beri tahu saya)
Setiap saran, opini, kritik lebih dari diterima. Terima kasih.
sumber
Jawaban:
Saya pikir masalah dengan versi 3 lebih merupakan masalah "sudut pandang" - apakah Anda melihat halaman sebagai sumber daya atau produk di halaman.
Jika Anda melihat halaman sebagai sumber daya itu adalah solusi yang sangat baik, karena permintaan untuk halaman 2 akan selalu menghasilkan halaman 2.
Tetapi jika Anda melihat produk pada halaman sebagai sumber daya Anda memiliki masalah bahwa produk pada halaman 2 dapat berubah (produk lama dihapus, atau apa pun), dalam hal ini URI tidak selalu mengembalikan sumber daya yang sama.
Misalnya, Pelanggan menyimpan tautan ke daftar produk halaman X, saat berikutnya tautan dibuka produk yang dimaksud mungkin tidak lagi ada di halaman X.
sumber
Saya setuju dengan Fionn, tetapi saya akan melangkah lebih jauh dan mengatakan bahwa bagi saya Page bukanlah sumber daya, itu adalah properti dari permintaan. Itu membuat saya memilih opsi 1 string kueri saja. Rasanya benar. Saya sangat suka bagaimana Twitter API terstruktur dengan tenang. Tidak terlalu sederhana, tidak terlalu rumit, didokumentasikan dengan baik. Lebih baik atau lebih buruk itu desain "pergi ke" saya ketika saya berada di pagar melakukan sesuatu satu arah versus yang lain.
sumber
HTTP memiliki Range header yang bagus yang juga cocok untuk pagination. Anda dapat mengirim
hanya memiliki halaman pertama. Itu mungkin memaksa Anda untuk memikirkan kembali apa itu halaman. Mungkin klien menginginkan rentang item yang berbeda. Header rentang juga berfungsi untuk mendeklarasikan pesanan:
untuk mendapatkan semua produk yang lebih baru dari tanggal itu atau
untuk mendapatkan semua produk yang lebih tua dari tanggal itu. '0' mungkin bukan solusi terbaik, tetapi RFC tampaknya menginginkan sesuatu untuk rentang awal. Mungkin ada parser HTTP yang digunakan yang tidak akan menguraikan unit = -range_end.
Jika tajuk bukan pilihan (dapat diterima), saya rasa solusi pertama (semua dalam string kueri) adalah cara untuk menangani halaman. Tapi tolong, normalisasikan string kueri (sort (key = value) berpasangan dalam urutan alfabet). Ini memecahkan masalah diferensiasi "? A = 1 & b = x" dan "? B = x & a = 1".
sumber
range-unit = bytes-unit | other-range-unit
Mungkin yang Anda maksudkanThe only range unit defined by HTTP/1.1 is "bytes". HTTP/1.1 implementations MAY ignore ranges specified using other units.
itu tidak sama dengan pernyataan Anda.Opsi 1 tampaknya yang terbaik, sejauh aplikasi Anda memandang pagination sebagai teknik untuk menghasilkan tampilan yang berbeda dari sumber daya yang sama.
Karena itu, skema URL relatif tidak signifikan. Jika Anda mendesain aplikasi Anda untuk menjadi hypertext-driven (karena semua aplikasi REST harus berdasarkan definisi), maka klien Anda tidak akan membuat URI sendiri. Sebaliknya, aplikasi Anda akan memberikan tautan ke klien dan klien akan mengikuti mereka.
Salah satu jenis tautan yang dapat disediakan oleh klien Anda adalah tautan pagination.
Efek samping yang menyenangkan dari semua ini adalah bahwa bahkan jika Anda berubah pikiran tentang struktur URI pagination dan menerapkan sesuatu yang sama sekali berbeda minggu depan, klien Anda dapat terus bekerja tanpa modifikasi apa pun.
sumber
Saya selalu menggunakan gaya opsi 1. Caching tidak menjadi masalah karena data sering berubah dalam kasus saya. Jika Anda membiarkan ukuran halaman dapat dikonfigurasi maka sekali lagi data tidak bisa di-cache.
Saya tidak menemukan url sulit untuk diingat atau tidak bersih. Bagi saya ini adalah penggunaan parameter query yang bagus. Sumber daya jelas daftar produk dan params pertanyaan hanya memberitahu bagaimana Anda ingin daftar ditampilkan - diurutkan dan halaman mana.
sumber
Aneh bahwa tidak ada yang menunjukkan bahwa Opsi 3 memiliki parameter dalam urutan tertentu. http // aplikasi / produk / Tanggal / Turun / Nama / Naik / halaman / 2 dan http // aplikasi / produk / Nama / Naik / Tanggal / Turun / halaman / 2
menunjuk ke sumber yang sama, tetapi memiliki url yang sama sekali berbeda.
Bagi saya Opsi 1 tampaknya yang paling dapat diterima, karena ia dengan jelas memisahkan "Apa yang saya inginkan" dan "Bagaimana saya ingin" itu (Itu bahkan memiliki tanda tanya di antara mereka lol). Caching satu halaman penuh dapat diimplementasikan menggunakan URL lengkap (toh semua opsi akan mengalami masalah yang sama).
Dengan pendekatan Parameter-in-URL, satu-satunya manfaat adalah URL bersih. Meskipun Anda harus datang dengan beberapa cara untuk menyandikan parameter dan mendekode lossless mereka. Tentu saja Anda bisa menggunakan URLencode / decode, tetapi itu akan membuat url jelek lagi :)
sumber
Saya lebih suka menggunakan parameter kueri offset dan batas.
offset : untuk indeks item dalam koleksi.
limit : untuk jumlah item.
Klien dapat terus memperbarui offset sebagai berikut
untuk halaman selanjutnya.
Path dianggap sebagai pengidentifikasi sumber daya. Dan sebuah halaman bukanlah sumber tetapi subset dari koleksi sumber daya. Karena pagination pada umumnya adalah permintaan GET, parameter kueri paling cocok untuk pagination daripada header.
Referensi: https://metamug.com/article/rest-api-developers-dilemma.html#Requesting-the-next-page
sumber
Mencari praktik terbaik saya menemukan situs ini:
http://www.restapitutorial.com
Di halaman sumber daya ada tautan untuk mengunduh .pdf yang berisi praktik terbaik lengkap REST yang disarankan oleh penulis. Di mana antara lain ada bagian tentang pagination.
Penulis menyarankan untuk menambahkan dukungan untuk keduanya menggunakan header Range dan menggunakan parameter string-string.
Permintaan
Contoh tajuk HTTP:
Contoh parameter string-string:
Di mana offset adalah nomor item awal dan batas adalah jumlah item maksimum yang akan dikembalikan.
Tanggapan
Respons harus mencakup tajuk Kisaran Konten yang menunjukkan berapa banyak item yang dikembalikan dan berapa jumlah total item yang belum diambil
Contoh tajuk HTTP:
Dalam .pdf ada beberapa saran lain untuk kasus yang lebih spesifik.
sumber
Saat ini saya menggunakan skema yang mirip dengan ini di aplikasi ASP.NET MVC saya:
misalnya
http://application/products/by-date/page/2
khususnya itu:
http://application/products/Date/Ascending/3
Namun, saya tidak benar-benar senang dengan memasukkan halaman dan menyortir informasi dalam rute dengan cara ini.
Daftar item (produk dalam hal ini) bisa berubah. yaitu saat berikutnya seseorang kembali ke url yang mencakup parameter paging dan sortir, hasil yang didapat mungkin telah berubah. Jadi gagasan
http://application/products/Date/Ascending/3
sebagai url unik yang menunjuk ke rangkaian produk yang ditentukan dan tidak berubah hilang.sumber
Saya cenderung setuju dengan slf bahwa "halaman" sebenarnya bukan sumber. Di sisi lain, opsi 3 lebih bersih, lebih mudah dibaca, dan dapat lebih mudah ditebak oleh pengguna dan bahkan diketikkan jika perlu. Saya terpecah antara opsi 1 dan 3, tetapi tidak melihat alasan untuk tidak menggunakan opsi 3.
Selain itu, walaupun terlihat bagus, satu kelemahan menggunakan parameter tersembunyi, seperti yang disebutkan seseorang, alih-alih string kueri atau segmen URL adalah bahwa pengguna tidak dapat membookmark atau menautkan langsung ke halaman tertentu. Itu mungkin atau mungkin bukan masalah tergantung pada aplikasi, tetapi hanya sesuatu yang harus diperhatikan.
sumber
Saya telah menggunakan solusi 3 sebelumnya (saya menulis BANYAK aplikasi Django). Dan saya tidak berpikir ada yang salah dengan itu. Ini sama mudahnya dengan dua lainnya (jika Anda perlu melakukan pengikisan massal atau sejenisnya) dan terlihat lebih bersih. Plus, pengguna Anda dapat menebak url (jika ini adalah aplikasi yang menghadap publik), dan orang-orang suka dapat langsung menuju ke tempat yang mereka inginkan, dan menebak-nebak url terasa memberdayakan.
sumber
Saya menggunakan dalam url proyek saya url berikut:
yang berarti - "beri saya halaman halaman kedua memerintahkan naik dengan field1 dan kemudian turun dengan field2". Atau jika saya membutuhkan lebih banyak fleksibilitas saya gunakan:
sumber
Saya menggunakan dalam pola berikut untuk mendapatkan catatan halaman berikutnya. http: // aplikasi / produk? lastRecordKey =? & pageSize = 20 & sort = ASC
RecordKey adalah kolom tabel yang menyimpan nilai sekuensial dalam DB. Ini digunakan untuk mengambil hanya satu data halaman sekaligus dari DB. pageSize digunakan untuk menentukan berapa banyak rekaman yang harus diambil. sort digunakan untuk mengurutkan record dalam urutan menaik atau menurun.
sumber