Membuat Pagination Di Node JS Menggunakan Sequelize ORM
Seorang pengguna telah mengakses aplikasi Anda dan membuka halaman daftar produk untuk melihat apa yang Anda jual.
Yang belum mereka ketahui adalah Anda memiliki ratusan atau ribuan produk. Menampilkan semuanya kepada pengguna sekaligus akan menjadi terlalu banyak informasi, yang menyebabkan pengalaman pengguna yang buruk. Selanjutnya, ini menghasilkan beban yang tidak perlu pada aplikasi. Dan karena Anda adalah seorang insinyur yang membangun aplikasi yang dapat diskalakan dan berfokus pada pengguna, itu tidak cocok untuk Anda.
Bagaimana cara Anda memastikan pengguna dan aplikasi tidak kelebihan beban dengan semua produk?
Pagination
Ini mengacu pada memecah kumpulan data besar menjadi potongan-potongan kecil sehingga dapat dengan mudah diserap oleh aplikasi dan pengguna.
Ada dua jenis pagination:
Pagination Sisi Klien
Ini melibatkan aplikasi klien yang mengambil semua data. Ini kemudian akan memutuskan bagaimana menampilkan data yang telah diterimanya.
Ini menguntungkan untuk aplikasi yang memiliki kumpulan data kecil dan memerlukan pemuatan halaman selanjutnya yang cepat.
Pagination Sisi Server
Ini melibatkan aplikasi klien mengirimkan parameter seperti ukuran halaman, batas, offset, pemesanan dll ke server yang kemudian merespon dengan data yang sesuai dengan parameter.
Metode ini baik untuk aplikasi yang
- memiliki kumpulan data yang besar
- memiliki logika bisnis yang kompleks
- harus tahan terhadap perubahan yang terjadi bersamaan
- membutuhkan pemuatan halaman awal yang lebih cepat
- harus dapat diakses oleh mereka yang tidak menjalankan javascript
Node JS
Ini adalah lingkungan runtime Javascript yang digerakkan oleh peristiwa yang dibangun di atas chrome V8 yang dirancang untuk membangun aplikasi jaringan yang dapat diskalakan.
Saya tidak akan membahas detail tentang apa itu Node JS, bagaimana cara kerjanya, tetapi Anda bisa membaca lebih lanjut di artikel ini.
Sequelize ORM
ORM adalah singkatan dari Object Relational Mapper/Mapping. Menurut techopedia, itu adalah teknik pemrograman di mana deskriptor metadata digunakan untuk menghubungkan kode objek ke database relasional. Kode objek ditulis dalam bahasa pemrograman berorientasi objek (OOP).
Sequelize adalah ORM Node.js berbasis janji untuk Postgres, MySQL, MariaDB, SQLite, dan Microsoft SQL Server.
Anda dapat membaca lebih lanjut tentang pembuatan sekuel di dokumen resmi mereka.
Saya kira Anda sudah menyiapkan proyek Node JS, jadi saya akan langsung ke instalasi Sequelize ORM dan Mysql.
Menggunakan jalankan NPM:
npm install --save sequelize mysql2
Menggunakan Yarn:
yarn add sequelize mysql2
Buat folder utilitas. Folder ini akan menampung kode khusus yang akan diperlukan di banyak tempat di aplikasi Anda.
Di dalamnya buat file-file berikut
- database.js
- pagination.js
Di dalam file database.js rekatkan kode berikut:
import { Sequelize } from 'sequelize';
import { config } from '../config/local';
export const sequelize = new Sequelize(config.database, config.username, config.password, {
host: config.host,
dialect: 'mysql'
});
export const connect = async () => {
try {
await sequelize.authenticate();
console.log('Connected to database');
} catch (e) {
console.log('Failed to connect to database', e);
}
}
Sepotong kode di atas bertanggung jawab untuk menghubungkan ke Sequelize ke database pilihan kita, dalam hal ini mysql. Dibutuhkan nama database, username, password, host dan dialek (tipe database).
Metode koneksi dipanggil sekali saat memulai server:
import express from 'express';
import { json, urlencoded } from 'body-parser';
import { connect } from './utils/database';
export const app = express();
app.use(json());
app.use(urlencoded({ extended: true }));
export const start = async () => {
try {
await connect();
app.listen(4000, () => {
console.log('Server is listening on http://localhost:4000')
})
} catch (e) {
console.log(e);
}
}
Buat file javascript model produk bernama product.model.js. Di dalam file rekatkan kode berikut:
import { DataTypes, Model } from 'sequelize';
import { sequelize } from '../../utils/database';
class ProductModel extends Model {}
const Product = Product.init({
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: {
type: DataTypes.STRING,
allowNull: false,
validate: {
notNull: {
msg: 'Name can not be null'
}
}
},
slug: {
type: DataTypes.STRING,
unique: true,
allowNull: false,
validate: {
notNull: {
msg: 'Slug can not be null'
}
}
},
description: {
type: DataTypes.STRING,
allowNull: false,
validate: {
notNull: {
msg: 'Description can not be null'
}
}
},
active: {
type: DataTypes.INTEGER
}
}, {
sequelize,
timestamps: true,
createdAt: 'created_at',
updatedAt: 'updated_at',
modelName: 'products'
});
export default Product;
Buat file javascript pengontrol produk bernama product.controller.js. Di dalam file, rekatkan kode berikut untuk mengambil daftar produk dengan halaman:
import { Op } from 'sequelize';
import ProductModel from './product.model';
/*
* List products
*/
export const listProducts = async(req, res) => {
try {
// get the query params
const { q, page, limit, order_by, order_direction } = req.query;
let search = {};
let order = [];
// add the search term to the search object
if (q) {
search = {
where: {
name: {
[Op.like]: `%${q}%`
}
}
};
}
// add the order parameters to the order
if (order_by && order_direction) {
order.push([order_by, order_direction]);
}
// transform function that can be passed to the paginate method
const transform = (records) => {
return records.map(record => {
return {
id: record.id,
name: record.name,
date: moment(record.created_at).format('D-M-Y H:mm A')
}
});
}
// paginate method that takes in the model, page, limit, search object, order and transform
const products = await paginate(ProductModel, page, limit, search, order, transform);
return res.status(200).send({
success: true,
message: 'Fetched products',
data: products
})
} catch (error) {
console.log('Failed to fetch products', error);
return res.status(500).send({
success: false,
message: 'Failed to fetch products'
})
}
}
Kode di atas bertanggung jawab untuk mengambil produk. Dibutuhkan permintaan, mendapatkan parameter kueri seperti halaman, batas, pesanan, dan membuat objek pencarian dan pesanan.
Metode transformasi adalah fungsi peta yang memungkinkan Anda menentukan cara mengembalikan data ke aplikasi klien atau permintaan aplikasi.
Model Produk bersama dengan halaman, batas, urutan pencarian, dan transformasi kemudian diteruskan ke metode paginasi.
Ingat file paginate.js yang kita buat sebelumnya? Buka dan rekatkan kode berikut:
export const paginate = async (model, pageSize, pageLimit, search = {}, order = [], transform) => {
try {
const limit = parseInt(pageLimit, 10) || 10;
const page = parseInt(pageSize, 10) || 1;
// create an options object
let options = {
offset: getOffset(page, limit),
limit: limit,
};
// check if the search object is empty
if (Object.keys(search).length) {
options = {options, ...search};
}
// check if the order array is empty
if (order && order.length) {
options['order'] = order;
}
// take in the model, take in the options
let {count, rows} = await model.findAndCountAll(options);
// check if the transform is a function and is not null
if (transform && typeof transform === 'function') {
rows = transform(rows);
}
return {
previousPage: getPreviousPage(page),
currentPage: page,
nextPage: getNextPage(page, limit, count),
total: count,
limit: limit,
data: rows
}
} catch (error) {
console.log(error);
}
}
const getOffset = (page, limit) => {
return (page * limit) - limit;
}
const getNextPage = (page, limit, total) => {
if ((total/limit) > page) {
return page + 1;
}
return null
}
const getPreviousPage = (page) => {
if (page <= 1) {
return null
}
return page - 1;
}
Metode paginasi mengembalikan objek yang berisi halaman sebelumnya, halaman berikutnya, halaman saat ini, total, batas, dan baris.
Hal yang baik tentang metode paginasi ini adalah dibutuhkan model apa pun sehingga Anda tidak perlu menulis kode paginasi untuk setiap model yang Anda miliki.
Data yang dikembalikan saat menekan API produk terlihat seperti ini:
Lanjutkan untuk memulai server simpul Anda dan tekan permintaan API yang memanggil metode listProducts dari tukang pos (sebagai permintaan dapatkan) atau tempel di browser Anda. Lewati halaman, limit, dan order sebagai kueri seperti ini:
http:localhost:3000/your-products-api?page=1&limit=10&
order_by=created_at&order_direction=asc