iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 22
0
Modern Web

Nest.js framework 30天初探系列 第 22

Nestjs framework 30天初探:Day22 MongoDB

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20171225/20107195OFWth6qmmI.png

  • Document-oriented,用文檔格式,不需要嚴格的結構。
  • High performance,高性能。
  • High availability,高可用,比如複製 (Replica set)。
  • Easy scalability,易擴展,比如Sharding。
  • Rich query language,豐富的查詢語言。
    (整理自知乎)

差點就Miss掉MongoDB,這次沿用Day21專案,基本上專案架構大同小異,SequelizeTypeORMMongoDB,都只是換湯不換藥的去改寫一些地方而已。這次使用很夯的Mongoose模組作為串接MongoDB的模組,我們將Day21專案換成Mongoose模組的API,並且灌好MongoDB,並啟動MongoDB,database名稱IronManNest,collection名稱:Users。

  1. 請先安裝本次需要的模組。
    cmd指令
npm install --save mongoose 
npm install --save-dev @types/mongoose
  1. 改寫databaseProviders。
    src/app/database.provider.ts
'use strict';

import * as mongoose from 'mongoose';

export const databaseProviders = [
    {
        provide: 'MongoDBConnection',
        useFactory: async (): Promise<mongoose.Connection> => {
            (mongoose as any).Promise = global.Promise;
            return await mongoose.connect('mongodb://localhost:27017/IronManNest', {
                useMongoClient: true
            })
        }
    }
]

先使用mongoose.connect()建立一下與MongoDB的連線,這會回傳MongooseThenable,再透過global.Promise 覆寫它,避免程式發出警告,實際上這也是一個非同步的Component。

  1. 在Users資料夾底下新增schemas資料夾,再新增users.schema.ts。
    src/app/Users/schemas/users.schema.ts
import * as mongoose from 'mongoose';

export const UsersSchema = new mongoose.Schema(
    {
        Name: String,
        Age: Number
    },
    { collection: 'Users', versionKey: false }, 
)
  1. 修改usersProviders。
    src/app/Users/users.providers.ts
'use strict';

import { Connection, connection } from 'mongoose';
import { UsersSchema } from './schemas/users.schema';

export const UsersProvider = [
    {
        provide: 'UsersRepository',
        useFactory: (connection: Connection) => connection.model('Users', UsersSchema),
        inject: ['MongoDBConnection']
    }
]
  1. 修改一下IUsers。
    src/app/Users/interfaces/IUsers.ts
'use strict';
import { Document } from 'mongoose';

export interface IUsers extends Document {
    readonly _id: number;
    readonly Name: string;
    readonly Age: number;
}
  1. 修改一下CreateUsersDTO。
    src/app/Users/DTO/createUses.dto.ts
import { ApiModelProperty } from '@nestjs/swagger';

export class CreateUsersDTO {

    @ApiModelProperty()
    readonly _id: number;

    @ApiModelProperty()
    readonly Name: string;

    @ApiModelProperty()
    readonly Age: number;
}
  1. 修改一下IUsersService。
    src/app/Users/interfaces/IUsers.service.ts
'use strict';

import { Users } from '../users.entity';
import { IUsers } from './IUsers';

export interface IUsersService {
    findAll(): Promise<Array<IUsers>>;
    findById(ID: number): Promise<IUsers | null>;
    findOne(options: Object): Promise<IUsers | null>;
    create(users: IUsers): Promise<IUsers>;
    update(ID: number, newValue: IUsers): Promise<IUsers | null>;
    delete(ID: number): Promise<number>;
}
  1. 修改一下UsersServices。
    src/app/Users/users.service.ts
'use strict';

import { Component, Inject } from '@nestjs/common';
import { IUsers, IUsersService } from './interfaces/index';
import { Model } from 'mongoose';
import { InjectRepository } from '@nestjs/typeorm';
import { CreateUsersDTO } from './DTO/createUsers.dto';

@Component()
export class UsersServices implements IUsersService{
    constructor( @Inject('UsersRepository') private readonly usersRepository: Model<IUsers>) { }

    public async findAll(): Promise<Array<IUsers>> {
        return await this.usersRepository.find().exec();
    }

    //findOne()可以加入各種option,以下示範常見的where
    //注意findOne() 找到一筆就會立即return data,不會繼續往下找。
    public async findOne(options: Object): Promise<IUsers | null> {
        return await this.usersRepository.findOne(options).exec();
    }

    //restful API很常用。
    public async findById(_id): Promise<IUsers | null> {
        return await this.usersRepository.findById(_id).exec();
    }

    public async create(users: CreateUsersDTO): Promise<IUsers> {
        return await this.usersRepository.create(users);
    }

    public async update(_id: number, newValue: IUsers): Promise<IUsers | null> {
        //先找出單筆資料
        let user = await this.usersRepository.findById(_id).exec();
        //該筆資料不存在
        if (!user._id) {
            console.error("user doesn't exist");
        }
        //呼叫user Model的方法
        await this.usersRepository.findByIdAndUpdate(_id, newValue).exec();
        return await this.usersRepository.findById(_id).exec();
    }

    public async delete(_id: number): Promise<number> {
        //成功會回傳1,失敗回傳0
        await this.usersRepository.findByIdAndRemove(_id).exec();
        let user = await this.usersRepository.findById(_id).exec();
        if (!user) {
            //刪除成功
            return 1;
        }
        else {
            //刪除失敗
            return 0;
        }
    }
}

Sequelize、TypeORM、Mongoose的API大致都長得很像,使用起來也差不多,學一套再學另一套還蠻快的。

  1. 修改一下UsersModule。
    src/app/Users/modules/users.module.ts
'use strict';

import { Module } from '@nestjs/common';
import { UsersServices } from '../users.service';
import { UsersProvider } from '../users.providers';
import { DatabaseModule } from '../../database.module';
import { UsersController } from './users.controller';

@Module({
    modules: [DatabaseModule],
    controllers: [UsersController],
    components: [
        UsersServices,
        ...UsersProvider
    ]
})
export class UsersModule { }

似乎一定要用擴展運算符把UsersProvider這陣列展開才不會噴錯

  1. 實際測試用Postman,測一下全部Restful API。
    新增資料
    對http://localhost:3000/users 做POST請求。
    https://ithelp.ithome.com.tw/upload/images/20171225/201071950RiZYFb2En.png

查詢全部資料
對http://localhost:3000/users 做GET請求。
https://ithelp.ithome.com.tw/upload/images/20171225/20107195lTB4uLHky5.png

查詢單筆資料
對http://localhost:3000/users/5a4115c23fb3a94ff4d7d614 做GET請求。
https://ithelp.ithome.com.tw/upload/images/20171225/20107195blWmujzWWY.png

修改單筆資料
對http://localhost:3000/users/5a4115c23fb3a94ff4d7d614 做PATCH請求。
https://ithelp.ithome.com.tw/upload/images/20171225/201071954r2xTMDVF8.png

刪除單筆資料
對http://localhost:3000/users/5a4115c23fb3a94ff4d7d614 做DELETE請求。
https://ithelp.ithome.com.tw/upload/images/20171225/201071955jBWwEcdWQ.png

對MongoDB的CRUD都正常運作了!

程式碼都在github


上一篇
Nestjs framework 30天初探:Day21 Passport(搭配JWT)
下一篇
Nestjs framework 30天初探:Day23 Redis
系列文
Nest.js framework 30天初探30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言