Bagian 5. Membuat API REST: pagination, pengurutan manual, dan pemfilteranPada
artikel sebelumnya, Anda selesai membangun fungsionalitas inti API CRUD.
Dan sekarang, ketika permintaan HTTP GET dikeluarkan pada rute karyawan, semua baris tabel dikembalikan. Ini mungkin tidak terlalu penting dengan hanya 107 baris dalam tabel HR.EMPLOYEES, tetapi bayangkan apa yang akan terjadi jika tabel tersebut berisi ribuan atau jutaan baris. Klien seperti aplikasi seluler dan web biasanya hanya menampilkan sebagian kecil dari baris yang tersedia di database, dan kemudian memilih lebih banyak baris bila perlu - mungkin ketika pengguna menggulir ke bawah atau mengklik tombol "Berikutnya" pada beberapa kontrol istirahat ke halaman di antarmuka pengguna.
Untuk ini, REST APIs harus mendukung alat pagination untuk hasil yang dikembalikan. Setelah pagination didukung, kemampuan penyortiran menjadi perlu, karena data biasanya harus disortir sebelum pagination diterapkan. Selain itu, alat pemfilteran data sangat penting untuk kinerja. Mengapa mengirim data dari database, melalui lapisan perantara dan sepenuhnya ke klien, jika ini tidak perlu?
Saya akan menggunakan parameter string kueri URL sehingga klien dapat menentukan bagaimana hasil harus paginasi, diurutkan dan difilter. Seperti biasa dalam pemrograman, implementasi dapat bervariasi tergantung pada kebutuhan Anda, tujuan kinerja, dll. Dalam posting ini saya akan memberi tahu Anda tentang pendekatan manual untuk menambahkan fungsi-fungsi ini ke API.
PaginationParameter string kueri yang akan saya gunakan untuk paginasi: lewati dan batasi. Parameter lewati akan digunakan untuk melewati jumlah baris yang ditentukan, sementara batas akan membatasi jumlah baris yang dikembalikan. Saya akan menggunakan nilai default 30 untuk batas jika klien tidak memberikan nilai.
Mulai dengan memperbarui logika pengontrol untuk mengekstrak nilai dari string kueri dan meneruskannya ke API database. Buka file
controllers / employee.js dan tambahkan baris kode berikut ke fungsi get setelah baris yang mem-parsing parameter req.params.id.
Sekarang Anda perlu memperbarui logika database untuk mengambil nilai-nilai ini ke dalam akun dan memperbarui query SQL yang sesuai. Dalam SQL, klausa offset digunakan untuk melewati baris, dan klausa ambil digunakan untuk membatasi jumlah baris yang dikembalikan oleh kueri. Seperti biasa, nilai tidak akan ditambahkan langsung ke kueri - sebagai gantinya, nilai itu akan ditambahkan sebagai variabel terikat untuk alasan kinerja dan keamanan. Buka
db_apis / employee.js dan tambahkan kode berikut setelah blok if di fungsi find, yang menambahkan klausa where ke permintaan.
Ini semua yang perlu Anda lakukan untuk melakukan paginasi! Luncurkan API, dan kemudian jalankan beberapa perintah URL di terminal lain untuk mengujinya. Berikut ini beberapa contoh yang dapat Anda gunakan:
# use default limit (30) curl "http://localhost:3000/api/employees" # set limit to 5 curl "http://localhost:3000/api/employees?limit=5" # use default limit and set skip to 5 curl "http://localhost:3000/api/employees?skip=5" # set both skip and limit to 5 curl "http://localhost:3000/api/employees?skip=5&limit=5"
MenyortirMinimal, pelanggan harus dapat menentukan kolom untuk mengurutkan dan memesan (naik atau turun). Cara termudah untuk melakukan ini adalah dengan menentukan parameter kueri (saya akan menggunakan sort), yang memungkinkan Anda meneruskan string seperti 'last_name: asc' atau 'payroll: desc'. Satu-satunya cara untuk menjamin urutan hasil yang dikembalikan dari query SQL adalah dengan memasukkan urutan dengan klausa. Untuk alasan ini, alangkah baiknya jika definisi pesanan default didefinisikan untuk memastikan konsistensi ketika klien tidak menentukannya.
Kembali ke
controllers / employee.js dan tambahkan baris kode berikut ke fungsi get setelah baris yang mem-parsing parameter req.query.limit.
Kemudian buka
db_apis / employee.js dan tambahkan baris berikut di bawah baris yang menyatakan dan menginisialisasi baseQuery.
sortableColumns adalah daftar putih kolom yang dapat digunakan pelanggan untuk mengurutkan. Kemudian, di dalam fungsi find, tambahkan blok if berikut ini, yang menambahkan urutan dengan klausa. Ini harus dilakukan setelah menambahkan klausa mana, tetapi sebelum mengimbangi dan mengambil klausa.
Bagian pertama dari blok if memeriksa apakah klien melewati nilai sortir. Jika tidak, maka urutan default dengan klausa ditambahkan ke kueri SQL, yang mengurutkan berdasarkan nama belakang dalam urutan naik. Jika nilai sortir ditentukan, maka itu pertama-tama dipecah menjadi kolom dan nilai pesanan, dan setiap nilai diperiksa sebelum menambahkan urutan oleh ke kueri.
Sekarang Anda dapat menjalankan beberapa perintah URL untuk memvalidasinya. Berikut ini beberapa contoh untuk dicoba:
# use default sort (last_name asc) curl "http://localhost:3000/api/employees" # sort by id and use default direction (asc) curl "http://localhost:3000/api/employees?sort=id" # sort by hire_date desc curl "http://localhost:3000/api/employees?sort=hire_date:desc" # use sort with limit and skip together curl "http://localhost:3000/api/employees?limit=5&skip=5&sort=salary:desc" # should throw an error because first_name is not whitelisted curl "http://localhost:3000/api/employees?sort=first_name:desc" # should throw an error because 'other' is not a valid order curl "http://localhost:3000/api/employees?sort=last_name:other"
Dua contoh terakhir harus membuang pengecualian, karena berisi nilai yang tidak dibuat untuk daftar putih. Ini menggunakan penangan kesalahan standar Express, sehingga kesalahan dikembalikan sebagai halaman web HTML.
PenyaringanKemampuan untuk memfilter data adalah fitur penting yang harus disediakan oleh semua REST API. Seperti penyortiran, implementasinya mungkin sederhana atau kompleks tergantung pada apa yang ingin Anda dukung. Pendekatan termudah adalah menambahkan dukungan untuk filter pertandingan penuh (misalnya, last_name = Doe). Implementasi yang lebih kompleks dapat menambahkan dukungan untuk operator dasar (misalnya, <,>, instr, dll.) Dan operator logis kompleks (misalnya, dan / atau) yang dapat mengelompokkan beberapa filter secara bersamaan.
Dalam posting ini saya akan mencoba menyederhanakan situasi dan menambahkan dukungan filter hanya untuk dua kolom: department_id dan manager_id. Untuk setiap kolom, saya akan mengaktifkan parameter terkait dalam string kueri. Logika database yang menambahkan klausa di mana ketika permintaan GET dikirim ke titik akhir dengan satu karyawan perlu diperbarui untuk mempertimbangkan filter baru ini.
Buka
controllers / employee.js dan tambahkan baris berikut di bawah baris yang mem-parsing nilai req.query.sort dalam fungsi get.
Kemudian edit
db_apis / employee.js untuk menambahkan kalimat 1 = 1 ke permintaan dasar, seperti yang ditunjukkan di bawah ini.
const baseQuery = `select employee_id "id", first_name "first_name", last_name "last_name", email "email", phone_number "phone_number", hire_date "hire_date", job_id "job_id", salary "salary", commission_pct "commission_pct", manager_id "manager_id", department_id "department_id" from employees where 1 = 1`;
Tentu saja, 1 = 1 akan selalu benar, sehingga pengoptimal akan mengabaikannya. Namun, metode ini akan menyederhanakan penambahan predikat tambahan di masa depan.
Dalam fungsi find, ganti blok if, yang menambahkan klausa where ketika meneruskan context.id, dengan baris berikut.
Seperti yang Anda lihat, masing-masing jika blok hanya menambahkan nilai yang diteruskan ke objek mengikat, dan kemudian menambahkan predikat yang sesuai ke klausa mana. Simpan perubahan dan mulai ulang API. Kemudian gunakan perintah URL ini untuk memverifikasi ini:
# filter where department_id = 90 (returns 3 employees) curl "http://localhost:3000/api/employees?department_id=90" # filter where manager_id = 100 (returns 14 employees) curl "http://localhost:3000/api/employees?manager_id=100" # filter where department_id = 90 and manager_id = 100 (returns 2 employees) curl "http://localhost:3000/api/employees?department_id=90&manager_id=100"
Itu saja - API sekarang mendukung pagination, sorting dan filtering! Pendekatan manual menyediakan banyak kontrol, tetapi membutuhkan banyak kode. Fungsi pencarian sekarang memiliki 58 baris dan hanya mendukung kemampuan penyortiran dan penyaringan terbatas. Anda mungkin mempertimbangkan untuk menggunakan modul, seperti
pembuat kueri
Knex.js , untuk menyederhanakan operasi ini.