37 Menambahkan Sorting Dinamis ke Query: Panduan Praktis untuk Software Engineer
Salah satu fitur yang sering diminta pada aplikasi modern adalah kemampuan sorting data secara dinamis. Bukan hanya secara asc atau desc, tetapi juga berdasarkan kolom yang berbeda-beda sesuai kebutuhan user. Misalnya, data pelanggan ingin diurut berdasarkan nama, tanggal pendaftaran, atau total transaksi, baik naik maupun turun.
Memasukkan sorting dinamis ke dalam query mungkin terlihat sederhana di permukaan—tinggal manipulasi clause ORDER BY
pada query SQL. Namun, untuk membuatnya aman, scalable, dan tetap readable, seringkali kita perlu pendekatan yang lebih sistematis. Dalam artikel ini, kita akan menguraikan satu per satu cara menambahkan sorting dinamis, membahas anti-pattern yang perlu dihindari, membagikan contoh dengan code snippet (menggunakan Node.js & TypeORM), serta memberikan simulasi hasil sorting. Kalau kamu sering berkutat di domain backend, simak artikel ini sampai tuntas.
Mengapa Sorting Dinamis Penting?
Sorting dinamis meningkatkan usability aplikasi: user dapat menentukan sendiri bagaimana data ditampilkan sehingga insight lebih mudah diperoleh. Coba bayangkan sebuah dashboard seperti admin e-commerce tanpa sorting: merepotkan sekali, bukan? Fitur semacam ini meningkatkan customer satisfaction dan juga memberikan kesan profesional pada aplikasi kita.
Kapan Harus Menggunakan Sorting Dinamis?
- Saat data yang di-display cukup banyak dan beragam (misal tabel produk, order, user)
- Saat user membutuhkan fleksibilitas untuk mengganti urutan tampil data
- Pada API yang digunakan oleh beberapa klien (misal mobile dan web) dengan kebutuhan sort berbeda
- Pada admin panel dengan fitur kolom yang sortable
Permasalahan Praktis: SQL Injection dan Hardcoding
Menambahkan sorting dinamis secara naif bisa mengundang masalah keamanan, khususnya SQL Injection, jika kita langsung meng-inject nama kolom dan sort order ke query. Berikut contoh anti-pattern yang sangat harus dihindari:
// Anti-pattern: Sangat rentan SQL Injection!
const query = `
SELECT * FROM users
ORDER BY ${req.query.sortBy} ${req.query.order}
`;
Jika sortBy
diisi ’nama;DROP TABLE users;–’, aplikasi Anda bisa jadi korban.
Pattern yang Disarankan: Whitelisting Kolom dan Order
Solusi umum dan aman adalah dengan membatasi input user (whitelisting) serta melakukan escaping input sort.
Berikut adalah pola yang bisa Anda gunakan dengan Node.js & TypeORM:
// 1. Definisikan whitelist kolom yang boleh di-sort
const ALLOWED_SORT_FIELDS = ['name', 'created_at', 'total_orders'];
const ALLOWED_ORDERS = ['ASC', 'DESC'];
// 2. Ambil parameter dari request
const { sortBy = 'created_at', order = 'ASC' } = req.query;
// 3. Validasi input
const safeSortBy = ALLOWED_SORT_FIELDS.includes(sortBy) ? sortBy : 'created_at';
const safeOrder = ALLOWED_ORDERS.includes(order.toUpperCase()) ? order.toUpperCase() : 'ASC';
// 4. Query TypeORM
const users = await getRepository(User)
.createQueryBuilder('user')
.orderBy(`user.${safeSortBy}`, safeOrder)
.getMany();
Pada kode di atas, input user akan divalidasi dulu, sehingga query yang dihasilkan selalu aman.
Simulasi Query dan Hasil Sorting
Misalkan database kita berisi tabel users
seperti berikut:
id | name | created_at | total_orders |
---|---|---|---|
1 | Andi | 2024-06-01 10:00:00 | 16 |
2 | Budi | 2024-05-15 09:20:00 | 23 |
3 | Cici | 2024-06-17 12:45:00 | 5 |
Jika user memanggil /users?sortBy=total_orders&order=desc
, sistem akan menjalankan query berikut:
SELECT * FROM users ORDER BY total_orders DESC;
Hasilnya:
id | name | total_orders |
---|---|---|
2 | Budi | 23 |
1 | Andi | 16 |
3 | Cici | 5 |
Flowchart Proses Sorting Dinamis
Agar lebih jelas, berikut alur proses validasi dan eksekusi query (menggunakan mermaid):
flowchart TD A[Input sortBy dan order dari user] --> B{Validasi nama kolom} B -- Valid --> C[Validasi order] B -- Invalid --> D[Gunakan default (created_at)] C -- Valid --> E[Bangun query ORDER BY] C -- Invalid --> F[Gunakan default (ASC)] E --> G[Eksekusi query di DB] F --> G D --> C
Kasus Lebih Kompleks: REST API dengan Pagination & Sorting
Sorting dinamis biasanya dipadukan juga dengan paginasi. Berikut pola endpoint yang sering digunakan:
GET /users?sortBy=created_at&order=desc&page=2&limit=10
Contoh implementasinya:
const { sortBy = 'created_at', order = 'ASC', page = 1, limit = 10 } = req.query;
const safeSortBy = ALLOWED_SORT_FIELDS.includes(sortBy) ? sortBy : 'created_at';
const safeOrder = ALLOWED_ORDERS.includes(order.toUpperCase()) ? order.toUpperCase() : 'ASC';
const take = Math.max(Number(limit), 1);
const skip = (Math.max(Number(page), 1) - 1) * take;
const users = await getRepository(User)
.createQueryBuilder('user')
.orderBy(`user.${safeSortBy}`, safeOrder)
.skip(skip)
.take(take)
.getMany();
Sorting Dinamis di Level ORM: Studi Kasus Prisma & Eloquent
Prisma
Prisma menyediakan API yang cukup nyaman untuk sorting.
const ALLOWED_SORT_FIELDS = ['name', 'createdAt', 'totalOrders'];
// Perlu konversi camel case sesuai field Prisma
const safeSortBy = ALLOWED_SORT_FIELDS.includes(sortBy) ? sortBy : 'createdAt';
const safeOrder = ALLOWED_ORDERS.includes(order.toLowerCase()) ? order.toLowerCase() : 'asc';
const users = await prisma.user.findMany({
orderBy: { [safeSortBy]: safeOrder }
});
Eloquent (Laravel)
$allowedSortFields = ['name', 'created_at', 'total_orders'];
$sortBy = in_array($request->get('sortBy'), $allowedSortFields) ? $request->get('sortBy') : 'created_at';
$order = in_array(strtolower($request->get('order')), ['asc', 'desc']) ? $request->get('order') : 'asc';
$users = User::orderBy($sortBy, $order)->get();
Advanced: Sorting Berdasarkan Join Table
Kadang, user ingin sort berdasarkan kolom di table relasi/join. Contoh: jumlah order dari tabel orders untuk users. Pada TypeORM, ini bisa dilakukan dengan leftJoin
dan agregasi. Namun, pastikan whitelist tetap diterapkan!
Tabel Simulasi: Hasil Sorting Berdasarkan Kolom Berbeda
sortBy | order | Top 1 User |
---|---|---|
name | asc | Andi |
name | desc | Cici |
total_orders | desc | Budi |
created_at | asc | Budi |
Kesimpulan
Adding dynamic sorting ke dalam query bukan sekadar manipulasi string SQL. Ada pertimbangan security, maintainability, serta usability. Selalu gunakan whitelist untuk mencegah SQL Injection, dan sediakan default value. Jika query semakin kompleks, pertimbangkan untuk memakai abstraction/middleware untuk merapikan kode. Dengan pendekatan ini, aplikasi yang Anda buat akan lebih fleksibel, scalable, dan yang paling penting—aman dari potensi eksploitasi.
Selamat mencoba, dan jangan lupa refactor if needed!
Psst! Butuh snippet lain untuk sorting di framework spesifik? Tinggalkan di kolom komentar.
59. Integrasi gRPC dengan OAuth2
Artikel Terhangat
42 Membuat Unit Test Query di graphql-go
08 Aug 2025
64. Implementasi gRPC Health Server
08 Aug 2025
41 Pengenalan Unit Test untuk Resolver
08 Aug 2025
63. gRPC Health Checking Standar
08 Aug 2025
39 Skema Filter & Pagination: Best Practice
08 Aug 2025
61. Load Balancing di gRPC Client
08 Aug 2025

42 Membuat Unit Test Query di graphql-go

64. Implementasi gRPC Health Server

41 Pengenalan Unit Test untuk Resolver

63. gRPC Health Checking Standar

39 Skema Filter & Pagination: Best Practice
