Sequelize

안정태·2021년 5월 26일
0

Study

목록 보기
29/33
post-thumbnail

우리는 앞서 ORM이라는 것을 배웠다. 이 ORM을 구현하기 쉽게 해주는 라이브러리가 바로 Sequelize이다.

node.js에서 SQL문을 사용하지 않고 DB를 조작할 수 있게 해주는 라이브러리

Sequelize를 사용 시에는 항상 메소드가 비동기로 작동한다는걸 반드시 알아야 한다.

Getting Started

먼저 아래 명령어를 CLI에 실행시켜 Secquelize를 설치해준다.

npm install --save squelize
npm install --save-dev sequelize-cli
npx sequelize-cli init

위 명령어들은 순서대로

  • Sequelize 를 설치하는 명령어
  • Sequelize 를 CLI로 실행할 수 있게 설치하는 명령어
  • cli를 통해 ORM을 잘 사용할 수 있도록 bootstraping(프로젝트 초기 단계를 자동으로 설정할 수 있도록 도와주는 일)을 해주는 명령어

이 명령어들을 순서대로 실행해준다.

모든 명령어를 실행하면

config/config.json
models/
migrations/
seeders/

다음 4개의 파일 및 폴더들이 생성 된다.

이 후 데이터베이스와 연결을 해준다.

// 생성된 config/config.json 파일

{
  "development": {
    "username": "root",
    "password": null,
    "database": "database_development",
    "host": "127.0.0.1",
    "dialect": "mysql"
  },
  "test": {
    "username": "root",
    "password": null,
    "database": "database_test",
    "host": "127.0.0.1",
    "dialect": "mysql"
  },
  "production": {
    "username": "root",
    "password": null,
    "database": "database_production",
    "host": "127.0.0.1",
    "dialect": "mysql"
  }
}

여기에 각각 이름에 맞는 데이터 베이스를 생성해주고 passwordusername을 설정해준다.

Model Definition

이제 모든 준비는 끝났으니 제일먼저 모델을 정의해 보자.

const { Sequelize, DataTypes } = require('sequelize');
const sequelize = new Sequelize('sqlite::memory:');

const User = sequelize.define('User', {
  // 모델의 속성을 여기 정의해 준다.
  firstName: {
    type: DataTypes.STRING,
    allowNull: false //null 값 허용 X
  },
  lastName: {
    type: DataTypes.STRING
    // null 값 허용
  }
}, {
  // ...
});

// 둘은 같다.
console.log(User === sequelize.models.User); // true

다음과 같은 형식을 통해서 모델을 정의할 수 있다.
그리고 확장된 방식은 다음과 같다.

const { Sequelize, DataTypes, Model } = require('sequelize');
const sequelize = new Sequelize('sqlite::memory');

class User extends Model {} // User 클래스 생성 (Model을 상속)

User.init({
  // 모델 속성 정의
  firstName: {
    type: DataTypes.STRING,
    allowNull: false
  },
  lastName: {
    type: DataTypes.STRING
    // null 값 허용
  }
}, {
  // 다른 모델 옵션들
  sequelize, // 연결 인스턴스를 전달
  modelName: 'User' // 모델이름 정의
});

// 둘은 같다.
console.log(User === sequelize.models.User); // true

CLI를 통한 Model 정의

npx sequelize-cli model:generate --name User --attributes firstName:string,lastName:string,email:string

--name <모델이름 작성>
--attributes <속성 : 타입>, <속성 : 타입>, ...
형식으로 작성해준다.

Model Querying

INSERT

// Create a new user
const jane = await User.create({ firstName: "Jane", lastName: "Doe" });

SELECT

// Find all users
const users = await User.findAll();

Model.findAll({
  attributes: ['foo', 'bar']
});
// === SELECT foo, bar FROM Model

Model.findAll({
  attributes: ['foo', ['bar', 'baz'], 'qux']
});
// === SELECT foo, bar AS baz, qux FROM ...

Model.findAll({
  attributes: [
    'foo',
    [sequelize.fn('COUNT', sequelize.col('hats')), 'n_hats'],
    'bar'
  ]
});
// === SELECT foo, COUNT(hats) AS n_hats, bar FROM ...

WHERE절

const { Op } = require("sequelize");
Post.findAll({
  where: {
    authorId: {
      [Op.eq]: 2
    }
  }
});
// === SELECT * FROM post WHERE authorId = 2

Post.findAll({
  where: {
    authorId: 12
    status: 'active'
  }
});
// === SELECT * FROM post WHERE authorId = 12 AND status = 'active';

// AND 사용법
const { Op } = require("sequelize");
Post.findAll({
  where: {
    [Op.and]: [
      { authorId: 12 },
      { status: 'active' }
    ]
  }
});
// === SELECT * FROM post WHERE authorId = 12 AND status = 'active';

// OR 사용법
const { Op } = require("sequelize");
Post.findAll({
  where: {
    [Op.or]: [
      { authorId: 12 },
      { authorId: 13 }
    ]
  }
});
// === SELECT * FROM post WHERE authorId = 12 OR authorId = 13;

Operators

const { Op } = require("sequelize");
Post.findAll({
  where: {
    [Op.and]: [{ a: 5 }, { b: 6 }],            // (a = 5) AND (b = 6)
    [Op.or]: [{ a: 5 }, { b: 6 }],             // (a = 5) OR (b = 6)
    someAttribute: {
      // Basics
      [Op.eq]: 3,                              // = 3
      [Op.ne]: 20,                             // != 20
      [Op.is]: null,                           // IS NULL
      [Op.not]: true,                          // IS NOT TRUE
      [Op.or]: [5, 6],                         // (someAttribute = 5) OR (someAttribute = 6)

      // Using dialect specific column identifiers (PG in the following example):
      [Op.col]: 'user.organization_id',        // = "user"."organization_id"

      // Number comparisons
      [Op.gt]: 6,                              // > 6
      [Op.gte]: 6,                             // >= 6
      [Op.lt]: 10,                             // < 10
      [Op.lte]: 10,                            // <= 10
      [Op.between]: [6, 10],                   // BETWEEN 6 AND 10
      [Op.notBetween]: [11, 15],               // NOT BETWEEN 11 AND 15

      // Other operators

      [Op.all]: sequelize.literal('SELECT 1'), // > ALL (SELECT 1)

      [Op.in]: [1, 2],                         // IN [1, 2]
      [Op.notIn]: [1, 2],                      // NOT IN [1, 2]

      [Op.like]: '%hat',                       // LIKE '%hat'
      [Op.notLike]: '%hat',                    // NOT LIKE '%hat'
      [Op.startsWith]: 'hat',                  // LIKE 'hat%'
      [Op.endsWith]: 'hat',                    // LIKE '%hat'
      [Op.substring]: 'hat',                   // LIKE '%hat%'
      [Op.iLike]: '%hat',                      // ILIKE '%hat' (case insensitive) (PG only)
      [Op.notILike]: '%hat',                   // NOT ILIKE '%hat'  (PG only)
      [Op.regexp]: '^[h|a|t]',                 // REGEXP/~ '^[h|a|t]' (MySQL/PG only)
      [Op.notRegexp]: '^[h|a|t]',              // NOT REGEXP/!~ '^[h|a|t]' (MySQL/PG only)
      [Op.iRegexp]: '^[h|a|t]',                // ~* '^[h|a|t]' (PG only)
      [Op.notIRegexp]: '^[h|a|t]',             // !~* '^[h|a|t]' (PG only)

      [Op.any]: [2, 3],                        // ANY ARRAY[2, 3]::INTEGER (PG only)

      // In Postgres, Op.like/Op.iLike/Op.notLike can be combined to Op.any:
      [Op.like]: { [Op.any]: ['cat', 'hat'] }  // LIKE ANY ARRAY['cat', 'hat']

      // There are more postgres-only range operators, see below
    }
  }
});

UPDATE

// 성이 없는 사람들의 성을 'doe'로 설정
await User.update({ lastName: "Doe" }, {
  where: {
    lastName: null
  }
});

DELETE

// 이름이 'Jane'인 모든 것들을 삭제
await User.destroy({
  where: {
    firstName: "Jane"
  }
});

// 전부 삭제
await User.destroy({
  truncate: true
});

Grouping

Project.findAll({ group: 'name' });
// === 'GROUP BY name'

findByPk

// 기본키가 123인 인스턴스를 찾는다.
const project = await Project.findByPk(123);
if (project === null) {
  console.log('Not found!');
} else {
  console.log(project instanceof Project); 
  // Its primary key is 123
}

findOne

const project = await Project.findOne({ where: { title: 'My Title' } });
if (project === null) {
  console.log('Not found!');
} else {
  console.log(project instanceof Project); // true
  console.log(project.title); // 'My Title'
}
profile
코딩하는 펭귄

0개의 댓글