เราจะมาทำความรู้จักและจัดการกับ Relational Database ใน Node JS Project ได้อย่างง่ายดายด้วยเครื่องมือ Sequelize จะมาช่วยทำเรื่องอะไรได้บ้างแหละรองรับภาษาอะไรวันนี้จะมาเล่าให้ฟังและถ้าเพื่อน ๆ สนใจลองค้นหาข้อมูลจากมันตามอินเตอร์เน็ตได้เลยเพราะคนก็มาใช้เยอะแล้วเหมือนกัน
Sequelize ?
มันคือ Object Relational Mapper ที่ใช้ js ซึ่งทำให้ง่ายต่อการทำงานกับฐานข้อมูล MySQL, MariaDB, SQLite, PostgreSQL และอีกมากมาย Object Relational Mapper ทำหน้าที่เช่นการจัดการบันทึกฐานข้อมูลโดยการแสดงข้อมูลเป็นวัตถุ
Database เริ่มจากออกแบบฐาน
ของนักฟุตบอลแบบง่าย ที่เราจะใช้กันวันนี้โดยมี Schema ดังนี้
CREATE TABLE `Team`
(
`tid` int NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL ,
`league` varchar(45) NOT NULL ,
PRIMARY KEY (`tid`)
);
CREATE TABLE `Player`
(
`pid` int NOT NULL AUTO_INCREMENT,
`tid` int NOT NULL ,
`name` varchar(45) NOT NULL ,
`age` int NOT NULL ,
`position` varchar(45) NOT NULL ,
PRIMARY KEY (`pid`),
KEY `fkIdx_112` (`tid`),
CONSTRAINT `FK_110` FOREIGN KEY `fkIdx_112` (`tid`) REFERENCES `Team` (`tid`)
);
จะทำ RESTfull API ที่ใช้สำหรับจัดการ Database ของนักฟุตบอลด้านบนกันนะครับ
Install กันก่อน
npm init
npm i express sequelize mysql2
สร้าง index.js
const express = require("express");
const app = express();
app.use(express.json());
app.get('/, async (req, res) => {
res.sendStatus(200);
});
app.listen(3000, () =>{
console.log("sever run on port " + 3000);
});
/db/model/player.js
// ด้านล่างเป็นการตั้งค่า attribute ของ table นะครับ
// ชื่อตัวแปรที่เราใช้เรียกแทน: { type: Sequelize.STRING(50), allowNull: false, field: ‘ชื่อของ attribute’ }
// สามารถใส่ option เพิ่มเติมได้นะครับเช่น primaryKey: true อะไรแบบนี้
// แล้วก็อันนี้สำคัญ ** ไม่จำเป็นต้องสร้าง attribute ที่เป็น FK จาก table อื่นนะครับ เพราะเราจะไปกำหนด relation กันใน file index
module.exports = ( sequelize , Sequelize ) => {
const player = sequelize.define(
'player', //<--- table name
{
pid: { type: Sequelize.INTEGER(11), primaryKey: true, autoIncrement: true, field: 'pid' },
name: { type: Sequelize.STRING(50), allowNull: false, field: 'name' },
age: { type: Sequelize.INTEGER(11), allowNull: false, field: 'age' },
position: { type: Sequelize.STRING(50), allowNull: false, field: 'position' },
},
{
tableName: 'player'
}
);
return player;
}
/db/model/team.js
module.exports = ( sequelize , Sequelize ) => {
const team = sequelize.define(
'team',
{
tid: { type: Sequelize.INTEGER(11), primaryKey: true, autoIncrement: true, field: 'tid' },
name: { type: Sequelize.STRING(50), allowNull: false, field: 'name' },
league: { type: Sequelize.STRING(50), allowNull: false, field: 'league' },
},
{
tableName: 'team'
}
);
return team;
}
/db/index.js
const { Sequelize } = require('sequelize');
//อันนี้เป็นส่วนที่ใช้ในการบอก Sequelize ว่าเราจะ connect ไปที่ไหน
const sequelize = new Sequelize(
'football', // นี่เป็นชื่อ DB ของเรานะครับ
'root', // user ที่ใช้สรการเข้าไปยัง db
'', // password
{
host: 'localhost', // host ของ db ที่เราสร้างเอาไว้
dialect: 'mysql', // 'mysql' | 'mariadb' | 'postgres' | 'mssql' พวกนี้ใช่ก็ใช้ได้นะจ๊ะ
define: {
timestamps: false //ส่วนตรงนี้ก็เป็นการตั้งค่าเพิ่มเติม
}
});
const db = {};
db.Sequelize = Sequelize;
db.sequelize = sequelize;
//ส่วนนี้เป็นการ import model ของ table ใน database เข้ามาเพื่อตั้งต่า relation นะครับ
db.player = require("./model/player")( sequelize , Sequelize );
db.team = require("./model/team")( sequelize , Sequelize );
//ส่วนนี้เป็นการตั้งต่า relation นะครับ โดยเป็นการบอกว่าใน 1 team มีได้หลาย player ง่ายๆ ก็คือ relation แบบ 1:M
db.team.hasMany(
db.player,
{
foreignKey: { name: 'tid', field: 'tid' }, //name ตรงสำคัญพยายามตั่งให้เป็นชื่อเดียวกับ FK ใน table ที่นำไปใช้นะครับ
}
);
//ส่วนนี้เป็นการตั้ง relation แบบกลับกันกับด้านบน จริงแล้วเราไม่ตั้งก็ได้นะครับแต่ผมแนะนำให้ตั้งเอาไว้ เพราะเวลาที่เราไม่ได้ใส่
//line นี้จะทำให้เราสามารถใช้ team ในการหา player ได้อย่างเดียวและไม่สามารถใช้ player หา team ได้
db.player.belongsTo(db.team, { foreignKey: 'tid' });
module.exports = db;
/index.js
const express = require("express");
const app = express();
app.use(express.json());
const db = require('./db/index.js');
const { player, team } = db
db.sequelize.sync();
app.get('/playerInfo', async (req, res) => {
info = await player.findAll();
res.json(info);
});
app.get('/playerInfo/:id', async (req, res) => {
id = req.params.id;
info = await player.findOne({
//attributes: ['name', ['tid','team'] , 'age'], สามารถเลือกเฉพาะ attributes ที่ต้องการได้ และ ['tid','team'] เขียนเป็น sql ก็จะได้ แบบนี้ครับ tid AS team
where: { pid: id }
});
if(!info){
res.sendStatus(500);
}else{
res.json(info);
}
});
app.post('/playerInfo', async (req, res) => {
data = req.body.data;
info = await player.create({
name: data.name,
age: data.age,
position: data.position,
tid: data.tid,
});
if(!info){
res.sendStatus(500);
}else{
res.status(200).json(info);
}
});
app.put('/playerInfo/:id', async (req, res) => {
id = req.params.id;
info = await player.update({ position: 'ST' },{
where: { pid: id }
});
if(!info){
res.sendStatus(500);
}else{
res.sendStatus(200);
}
});
app.delete('/playerInfo/:id', async (req, res) => {
id = req.params.id;
info = await player.destroy({
where: { pid: id }
});
if(!info){
res.sendStatus(500);
}else{
res.sendStatus(200);
}
});
app.use((_req, res) => {
res.sendStatus(501);
});
app.listen(3000, () =>{
console.log("sever run on port " + 3000);
});
Read Data จาก Database (ใส่ข้อมูลไว้บ้างแล้วนะครับ)
Create สร้าง Player
Update Data โดย จะเปลี่ยน Position ของ Player เป็น ST
Delete ข้อมูล
บทสรุป
บทความนี้ก็จะได้นำเสนอเบื้องต้นกับ Sequelize เอกสารประกอบเพิ่มเติม
อ้างอิง
ขอบคุณ Code ตัวอย่าง https://www.borntodev.com/2021/07/02/node-js-%E0%B8%81%E0%B8%B1%E0%B8%9A-sequelize-101/