Sequelize #2 쿼리, 외래키 (for MySQL)

Explanation

두둥! 드디어 2020년 새해가 밝았습니다.
오늘은 새해 첫 날인 1월 1일! 원래는 어제 저녁에 여자친구와 해돋이를 보러 동해로 갈 계획이었지만.
여자친구가 없는 관계로, 이렇게 행복하게 집에서 포스팅을 하고 있습니다. (주륵..)
오늘은 Sequelize ORM을 사용한 Insert, Update 쿼리문과 외래키에 대해 알아보려 합니다~
역시 사용한 예제 코드는 아래의 깃허브에서 확인하실 수 있습니다.
https://github.com/falsy/blog-post-example/tree/master/sequelize-quick-start-2

이번 글은 지난 글의 내용을 전재로 이어서 진행됩니다.
/sequelize-1-%ec%8b%9c%ec%9e%91%ed%95%98%ea%b8%b0-for-mysql/

1. Insert Query

아마도 제 생각에는 지난 글 정도의 내용만 이해하셨다면 충분히 공식 홈페이지의 메뉴얼을 검색해서 진행하실 수 있을 거 같지만, 그래도 이왕 쓰기 시작한 김에 조금 더 적어보려 해요.
지난 글에서는 GET 위주 였는데요. 이번엔 POST, PUT API를 만들어볼까요?

// /router/index.js
const Router = require('koa-router');
const db = require('../db');

module.exports = () => {
  const router = new Router();
  const models = db.models;

  ...

  router.post('/add', async (ctx) => {
    const { name, content } = ctx.request.body;

    await models.boards.create({
      name,
      content
    }).catch(e => {
      console.log(e);
    });

    ctx.status = 204;
  });

  return router;
};

'koa-body' 패키지가 설치되어 있습니다

위와 같이 POST 라우트를 추가하였어요. body에 name과 content를 받아서 boards 테이블에 insert한 답니다.

정상적으로 잘 동작하는지 테스트 해봐야겠죠?

원래는 포스트맨(https://www.getpostman.com/)을 주로 사용하지만... 그러면 또 스크린샷을 찍어야하는 번거러움이 있으므로 컬(curl)로 대신합니다.
터미널에서 아래와 같이 입력합니다~

$ curl -d '{"name":"falsy", "content":"hello world"}' -H "Accept: application/json" -H "Content-Type: application/json" http://localhost:7777/add

컬(curl)에 대한 자세한 정보는 정광섭님의 글을 보면 좋아요!!
https://www.lesstif.com/pages/viewpage.action?pageId=14745703

우선 -d 옵션이 있으면 자동으로 POST로 설정이 되고 JSON 형태의 데이터를 보내고 Header에 'application/json'타입을 적어주고,
마지막으로는 만들었던 서버의 URI를 입력해주었었습니다.
그럼 이제 DB에 데이터가 잘 추가 되었는지 DB에 가서 확인을 해보면,

+----+-------+-------------+---------------------+
| id | name  | content     | created_at          |
+----+-------+-------------+---------------------+
|  1 | falsy | hello world | 2020-01-01 09:38:26 |
+----+-------+-------------+---------------------+

짜잔!

2. Multiple Insert Query

멀티플 인설트 쿼리... 이게 맞는 영어 인지 모르겠습니다. 타이틀을 한글로 시작할 걸 그랬습니다...

여하튼 여러개의 데이터를 한번에 인설트하는 방법은 아래와 같습니다~

// /router/index.js
const Router = require('koa-router');
const db = require('../db');

module.exports = () => {
  const router = new Router();
  const models = db.models;

  ...

  router.post("/addList", async ctx => {
    await models.boards
      .bulkCreate([
        {
          name: "blue",
          content: "hello"
        },
        {
          name: "red",
          content: "world"
        }
      ])
      .catch(e => {
        console.log(e);
      });
    ctx.status = 204;
  });

  return router;
};

위와 같이 'bulkCreate'라는 메서드의 인자값을 배열로 하여 여러 로우 데이터를 추가하실 수 있답니다.

$ curl -X POST http://localhost:7777/addList
+----+-------+-------------+---------------------+
| id | name  | content     | created_at          |
+----+-------+-------------+---------------------+
|  1 | falsy | hello world | 2020-01-01 09:38:26 |
|  2 | blue  | hello       | 2020-01-01 10:01:20 |
|  3 | red   | world       | 2020-01-01 10:01:20 |
+----+-------+-------------+---------------------+

짜잔!

3. Update Query

이제 마지막으로 업데이트는 아래와 같이 사용할 수 있답니다.

// /router/index.js
const Router = require('koa-router');
const db = require('../db');

module.exports = () => {
  const router = new Router();
  const models = db.models;

  ...

  router.put("/update", async ctx => {
    await models.boards
      .update(
        {
          content: "hi, world"
        },
        {
          where: {
            name: "falsy"
          }
        }
      )
      .catch(e => {
        console.log(e);
      });
    ctx.status = 204;
  });

  return router;
};

대략 update 메서드를 사용하고, 첫번째 인자로 바꿀 내용에 관한 속성을, 그리고 두번째 인자로 대상에 대한 속성을 입력할 수 있답니다.

$ curl -X PUT http://localhost:7777/update
+----+-------+-----------+---------------------+
| id | name  | content   | created_at          |
+----+-------+-----------+---------------------+
|  1 | falsy | hi, world | 2020-01-01 09:38:26 |
|  2 | blue  | hello     | 2020-01-01 10:01:20 |
|  3 | red   | world     | 2020-01-01 10:01:20 |
+----+-------+-----------+---------------------+

짜잔!

4. 외래키(foreign key)

외래키.
이름만 들어서는 아마도 외국에서 온 거 같습니다. 어려워 보입니다.
저도 잘 모릅니다.
대충, 두개의 테이블이 이어주는 거 같습니다.

대충, 조인문 쓰려면 필요한 줄 알았는데.
대충, 검색해보니 외래 키를 등록하지 않아도 조인 문을 쓸 수 있나봐요??
뭐든 괜찮아요. 전 조인문을 좋아하지 않으니까요.

일단 기존에 만들었던 'boards' 테이블과 연결해서 사용할 'likes' 라는 테이블을 만들어볼게요.

보니까 저번글에서 생략했던데..
이번엔 boards라는 모델값이 필요하니까 아래와 같이 만들었답니다.

const boardModel = require("./boards");
const likeModel = require("./likes");

module.exports = (Sequelize, sequelize) => {
  const boards = boardModel(Sequelize, sequelize);
  const likes = likeModel(Sequelize, sequelize, boards);

  return {
    boards,
    likes
  };
};

그리고 모델은 아래와 같이 만들었어요.

// /model/likes.js
module.exports = (Sequelize, sequelize, boardModel) => {
  const likes = sequelize.define("likes", {
    id: {
      type: Sequelize.INTEGER(11).UNSIGNED,
      primaryKey: true,
      autoIncrement: true,
      allowNull: false
    },
    board_id: {
      type: Sequelize.INTEGER(11).UNSIGNED,
      references: {
        model: boardModel,
        key: "id"
      },
      allowNull: false
    },
    count: {
      type: Sequelize.INTEGER(11).UNSIGNED,
      allowNull: false
    },
    created_at: {
      type: Sequelize.DATE,
      defaultValue: Sequelize.fn("now"),
      allowNull: false
    }
  });

  likes.sync();
  return likes;
};

딱 보면,
'board_id'라는 컬럼이 boards의 id값과 연결 된 포링키가 된거쥬!

// likes 테이블이 만들어지는 쿼리문
CREATE TABLE IF NOT EXISTS `likes` (`id` INTEGER(11) UNSIGNED NOT NULL auto_increment , `board_id` INTEGER(11) UNSIGNED NOT NULL, `count` INTEGER(11) UNSIGNED NOT NULL, `created_at` DATETIME NOT NULL DEFAULT now(), PRIMARY KEY (`id`), FOREIGN KEY (`board_id`) REFERENCES `boards` (`id`)) ENGINE=InnoDB;

끝