8
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

NestJS TypeORM postgres で環境構築 with docker(DBのみ)

Last updated at Posted at 2021-03-29

#記事の内容
NestJS TypeORM postgresで環境構築します。
postgresはDocker上で起動します。

Dockerについては、完全初心者です。
ただ、dbをローカルに作るのが嫌でしたので導入してみました。

今回調べながらの環境構築なので
間違っている所やこうした方がいい所、等があった場合
教えていただけると嬉しいです。

環境構築を終えたら、
URLのアクセスからデータ操作までの流れを簡単に実装します。

ソースコードはこちら↓
https://github.com/tokio-k/docker-nest-postgres-sample

※Docker、yarnのインストールは前提で進めます。
※調べればすぐできると思うのでよろしくお願いします。

#プロジェクトの作成

###フォルダ作成
ターミナルで今回作成していくフォルダを作成し、そのフォルダに移動します。
(今回はdocker-nest-postgres-sampleというフォルダ)

terminal.
# フォルダ作成
mkdir docker-nest-postgres-sample
# 移動
cd docker-nest-postgres-sample

(terminal. の「.」は気にしないでください。普通にターミナルで実行しています。)

###NestJSのプロジェクトを作成
Nest用CLIを用いて作成していきます。
Nest用CLIをインストールします。(既にインストールしてある場合は飛ばしてください。)

terminal.
yarn global add @nestjs/cli

作成したフォルダの中に、Nestのプロジェクトを作成します。
簡単に雛形を作成できます。

terminal.
# Nestのプロジェクトを作成
nest new .

ライブラリのインストール

TypeORM関連やバリデーションのライブラリをインストールしておきます。
DBにはpostgresを使用します。

terminal.
#TypeORM関連
yarn add @nestjs/typeorm typeorm pg

#バリデーション
yarn add class-transformer class-validator

#Dockerでpostgresの環境構築

最初に作成したフォルダの中にdocker-compose.ymlを作成します。
srcフォルダやpackage.jsonと同じ階層です。

terminal.
touch docker-compose.yml

作成したdocker-compose.ymlの中に以下の記述をします。
データベース接続情報などは好きに書いてください。(environment)
本当は、環境変数や.envファイルに記述し、参照する様にするみたいです。
いつか書き換えればいいので、今は直接書きで。

docker-compose.yml
version: '3'

services:
  postgres:
    image: postgres:13.1
    container_name: postgres
    ports:
      - 5432:5432
    volumes:
      - ./postgres_data:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: root
      POSTGRES_PASSWORD: password
      POSTGRES_DB: test_db
      POSTGRES_INITDB_ARGS: '--encoding=UTF-8'
      TZ: 'Asia/Tokyo'
    restart: always

docker-composeに記載した内容で、
docker上にpostgresの環境を立ち上げます。

terminal.
docker-compose up -d

pgAdmin4などで確認してみると、データベースが作成されていることが確認できます。

#NestJSからTypeORMを使用

###ormconfig.jsonを作成

srcフォルダやpackage.jsonと同じ階層にormconfig.jsonを作成します。

terminal.
touch ormconfig.json

ormconfig.jsonを編集していきます。
データベース情報は、先程設定したものと合わせてください。

ormconfig.json
{
    "type": "postgres",
    "host": "localhost",
    "port": 5432,
    "username": "root",
    "password": "password",
    "database": "test_db",
    "entities": ["dist/entities/**/*.entity.js"],
    "migrations": ["dist/migrations/**/*.js"],
    "logging": true,
    "synchronize": false
}

###app.module.tsを編集
app.module.tsを編集します。
これで、TypeORMの機能を呼び出すことができる様になります。

app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TypeOrmModule } from '@nestjs/typeorm';//追加箇所

@Module({
  imports: [TypeOrmModule.forRoot()],//編集箇所
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

テーブル作成

テーブルを作成していきます。

###Entityの作成
Entityを作成します。
Entityでは、テーブルの構造を定義し、これを元にテーブルが作成されます。

srcフォルダの中にentitiesフォルダを作成します。
entitiesフォルダの中にitem.entity.tsを作成します。

item.entity.tsを編集していきます。

item.entity.ts
import {
  Entity,
  Column,
  PrimaryGeneratedColumn,
  CreateDateColumn,
  UpdateDateColumn,
} from 'typeorm';

@Entity()
export class Item {
  @PrimaryGeneratedColumn()
  readonly id: number;

  @Column()
  todo: string;

  @Column('boolean', { default: false })
  idDone: boolean;

  @CreateDateColumn()
  readonly createdAt?: Date;

  @UpdateDateColumn()
  readonly updatedAt?: Date;
}

id,todo,isDone,createdAt,updatedAtがそれぞれテーブルのカラムになります。

###マイグレーションファイルの作成/実行

マイグレーションファイルを作成していきます。

terminal.
# ビルド
yarn build

#マイグレーションファイルの作成
yarn typeorm migration:generate -d src/migrations -n create-item

マイグレーションファイルを実行していきます。

terminal.
# ビルド
yarn build

# マイグレーションファイルの実行 (DB作成)
yarn typeorm migration:run

pgAdmin4などで確認してみると、テーブルが作成されている事が確認できます。

#module,controller,serviceの作成

コマンドでそれぞれ作成していきます。

terminal.
# module作成
yarn nest g module item

# controller作成
yarn nest g controller item

# service作成
yarn nest g service item

コマンドで作成すると、読み込まれるように、app.module.tsやitem.module.tsに自動で追記されます。
app.module.tsを編集します。

item.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';//追加箇所
import { Item } from 'src/entities/item.entity';//追加箇所
import { ItemController } from './item.controller';
import { ItemService } from './item.service';

@Module({
  controllers: [ItemController],
  imports: [TypeOrmModule.forFeature([Item])],//編集箇所
  providers: [ItemService],
})
export class ItemModule {}

#DTOの作成

###DTOを作成します。
データのやり取りをするときにデータ構造を表す箱のようなものです。
ここでバリデーション(入力チェック)などができます。

item.dto.ts
import { IsNotEmpty, IsString } from 'class-validator';

export class CreateItemDTO {
  @IsNotEmpty()
  @IsString()
  todo: string;
}

todoを必須+文字列に制限しました。
データ追加をするときに、このクラスを使ってデータのやり取りをします。

###バリデーションを有効にする
src/main.tsを編集して、バリデーションを有効にします。

main.ts
import { ValidationPipe } from '@nestjs/common';//追加箇所
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(new ValidationPipe());//追加箇所
  await app.listen(3000);
}
bootstrap();

#APIの実装
Service,Controllerを実装していきます。

###Serviceの実装
Serviceを実装していきます。

item.service.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Item } from 'src/entities/item.entity';
import { InsertResult, Repository } from 'typeorm';
import { CreateItemDTO } from './item.dto';

@Injectable()
export class ItemService {
  constructor(
    @InjectRepository(Item)
    private readonly itemRepository: Repository<Item>,
  ) {}

  // 全データ検索
  async findAll(): Promise<Item[]> {
    return await this.itemRepository.find();
  }

  //データ追加
  async create(item: CreateItemDTO): Promise<InsertResult> {
    return await this.itemRepository.insert(item);
  }
}

constructorの部分でRepositoryをInjectionしています。
Repositoryに指示を出すことでテーブルのデータを変更できます。

###Controllerの実装

item.controller.ts
import { Body, Controller, Get, Post } from '@nestjs/common';
import { Item } from 'src/entities/item.entity';
import { InsertResult } from 'typeorm';
import { CreateItemDTO } from './item.dto';
import { ItemService } from './item.service';

@Controller('item')
export class ItemController {
  constructor(private readonly service: ItemService) {}

  // 全データ検索
  @Get()
  async getItemList(): Promise<Item[]> {
    return await this.service.findAll();
  }
  //データ追加
  @Post()
  async addItem(@Body() item: CreateItemDTO): Promise<InsertResult> {
    return await this.service.create(item);
  }
}

/itemにGetでアクセスがあった時に「getItemList()」
/itemにPostでアクセスがあった時に「addItem(item)」が呼び出されます。
addItem(item)の「item」が先程作成したCreateItemDTOの型には入ります。

constructorでは、先程作成したServiceがInjectionされています。

とりあえず、実装は完成

#動作確認

###実行
以下のコマンドで実行できます。

terminal.
yarn start dev

###新規データの追加 (addItemを呼び出す)

コマンドで以下を実行してデータを追加できます。

terminal.
curl http://localhost:3000/item -X POST -d "todo=test"

###ブラウザからアクセス (getItemListを呼び出す)
ブラウザから以下で検索すると、追加したデータが表示されます。
http://localhost:3000/item

これで、全検索と追加のAPIが作成することができました。

##参考記事
How To Set Up TypeORM With Postgres in NestJS
NestJSの始め方
NestJSで簡単なtudoリストを実装するチュートリアル
Mac に Docker Desktop をインストール

8
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?