เปลียนจากเขียน sql มาใช้ Sequelize กันเถอะ

og:image

เราจะมาทำความรู้จักและจัดการกับ 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/