Nest.jsでSequelizeを使ってみる

前回、[Nest.js を使ってみる](https://qiita.com/teracy55/items/83cae05eed027a510a7e)でNest.js環境を構築しました。

今回はNode.js向けのORMであるSequelizeを導入してみます。

# Sequelizeとは

Sequelize：http://docs.sequelizejs.com/


# Nest.jsにSequelizeを組み込む

[公式に手順](https://docs.nestjs.com/recipes/sql-sequelize)が載っているため、それに従います

なお、今回使用するDBはPostgresです。

## sequelize-typescriptのインストール

sequelize、sequelize-typescript、pg（postgres）、sequelizeの型定義パッケージをインストールします

```
$ npm install --save sequelize sequelize-typescript pg
$ npm install --save-dev @types/sequelize
```

## DB接続準備

公式だと接続情報はコードにべた書きですが、環境ごとにDBを切り替えられるように設定ファイルで外だしします。

```src/database/database.config.ts
export const config = {
    development: {
        host: process.env.POSTGRES_HOST,
        port: process.env.POSTGRES_PORT,
        database: process.env.POSTGRES_DB_NAME,
        username: process.env.POSTGRES_USER,
        password: process.env.POSTGRES_PASSWORD,
        dialect: 'postgres',
    },
    production: {
        // TODO 本番用
    }
}
```


```src/database/database.providers.ts
import { Sequelize } from 'sequelize-typescript';
import { Cat } from '../cats/cat.entity';
import { config } from 'src/config/database.config';

export const databaseProviders = [
    {
        provide: 'SEQUELIZE',
        useFactory: async () => {
            const sequelize = new Sequelize(
                config[process.env.NODE_ENV || 'development']
            );
            sequelize.addModels([Cat]);
            await sequelize.sync();
            return sequelize;
        },
    },
];
```

```database.module.ts
import { Module } from '@nestjs/common';
import { databaseProviders } from './database.providers';

@Module({
  providers: [...databaseProviders],
  exports: [...databaseProviders],
})
export class DatabaseModule {}
```

## Catsテーブルアクセス用ファイル作成

公式の手順に従って、Catsテーブルにアクセスするためのファイルを準備します。

```src/cats/cats.entity.ts
import { Table, Column, Model } from 'sequelize-typescript';

@Table
export class Cat extends Model<Cat> {
  @Column
  name: string;

  @Column
  age: number;

  @Column
  breed: string;
}
```

```src/cats/cats.providers.ts
import { Cat } from './cat.entity';

export const catsProviders = [
  {
    provide: 'CATS_REPOSITORY',
    useValue: Cat,
  },
];
```

```src/cats/cats.module.ts
import { Module } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';
import { catsProviders } from './cats.providers';
import { DatabaseModule } from '../database/database.module';

@Module({
  imports: [DatabaseModule],
  controllers: [CatsController],
  providers: [
    CatsService,
    ...catsProviders,
  ],
})
export class CatsModule {}
```

```src/cats/cats.service.ts
import { Injectable, Inject } from '@nestjs/common';
import { Cat } from './cat.entity';

@Injectable()
export class CatsService {
  constructor(
    @Inject('CATS_REPOSITORY') private readonly CATS_REPOSITORY: typeof Cat) {}

  async findAll(): Promise<Cat[]> {
    return await this.CATS_REPOSITORY.findAll<Cat>();
  }
}
```

```src/cats/cats.controller.ts
import { Controller, Get } from '@nestjs/common';
import { CatsService } from './cats.service';
import { Cat } from './cat.entity';

@Controller({
  path: 'cats'
})
export class CatsController {
  constructor(private readonly catsService: CatsService) {}

  @Get()
  getCats(): Promise<Cat[]> {
    return this.catsService.findAll();
  }
}
```

# 起動してみる

以下のようなdocker-compose.ymlを用意し、`docker-compose up`で起動してみます。

```docker-compose.yml
version: '2'
services:
  nestjs-web:
    image: node:latest
    container_name: nestjs-web
    ports:
      - "3000:3000"
    links:
      - nestjs-db
    working_dir: /develop
    command: [sh, -c, 'npm install --unsafe-perm && npm run start:dev']
    volumes:
      - "./:/develop:z"
    environment:
      - "POSTGRES_HOST=192.168.33.20"
      - "POSTGRES_PORT=15432"
      - "POSTGRES_DB_NAME=postgres"
      - "POSTGRES_USER=postgres"
      - "POSTGRES_PASSWORD=postgres"

  nestjs-db:
    image: postgres:latest
    container_name: nestjs-db
    ports:
      - "15432:5432"
    environment:
      - "POSTGRES_USER=postgres"
      - "POSTGRES_PASSWORD=postgres"
    volumes:
      - "/data/db:/var/lib/postgresql/data:z"

```

ちゃんとCatsテーブルのCREATE文が発行されてますね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325108/14fc6778-d9ee-75d7-7cd8-74217e341c9d.png)




# DBにデータを投入

[A5M2](https://a5m2.mmatsubara.com/)でDBにアクセスし、データを追加しておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325108/164ac34b-1ea1-eb62-1531-ca8722e2eed2.png)


# ブラウザでアクセス

http://192.168.33.20:3000/cats にアクセスします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325108/6bc262de-093a-bf6d-ce76-4309ba5519a8.png)

追加した情報が取れました！