tutorial

37 Menambahkan Sorting Dinamis ke Query

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:

idnamecreated_attotal_orders
1Andi2024-06-01 10:00:0016
2Budi2024-05-15 09:20:0023
3Cici2024-06-17 12:45:005

Jika user memanggil /users?sortBy=total_orders&order=desc, sistem akan menjalankan query berikut:

SELECT * FROM users ORDER BY total_orders DESC;

Hasilnya:

idnametotal_orders
2Budi23
1Andi16
3Cici5

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

sortByorderTop 1 User
nameascAndi
namedescCici
total_ordersdescBudi
created_atascBudi

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.

comments powered by Disqus

Topik Terhangat

programming
261
tutorial
128
tips-and-trick
43
jaringan
28
hardware
11
linux
4
kubernetes
1