Nest 简介
Nest是一个NodeJS的服务端框架,与JAVA对照的话,其功能相当于SpringMVC(国产也有类似框架,如阿里开源的EggJS)。对于熟悉JAVA的开发者,Nest极易上手,Nest有着与SpringMVC如出一辙的分层架构和注解标签,以及依赖注入、控制反转、生命周期等实现,官网传送门。
NeDB简介
NeDB是一个NodeJS实现的轻量级、嵌入式、NoSQL数据库,可用作内存数据库,也可以持久化。使用简单、速度快,适合数据量小、业务简单的场景(https://www.npmjs.com/package/nedb)。
创建项目,添加依赖
创建Nest项目,添加NeDB依赖,并将初始化项目按业务模块调整。
创建Nest项目
创建项目nest-demo:
nest new nest-demo
安装NeDB:
cd nest-demo
npm i nedb -S
调整初始化项目
将初始化的项目结构按业务模块调整,调整后的结构如下(包含两个模块,book和library):
app.module.ts
import { Module } from '@nestjs/common';
import { BookModule } from './book/book.module';
import { LibraryModule } from './library/library.module';
@Module({
imports: [BookModule, LibraryModule],
controllers: [],
providers: [],
})
export class AppModule {}
整合NeDB,实现CRUD
book.entity.ts,book模型
export interface BookEntity {
_id: string;
name: string;
price: number;
author: string;
createdAt: number;
updatedAt: number;
}
book.controller.ts
import { Body, Controller, Get, Post } from '@nestjs/common';
import { BookService } from './book.service';
import { BookEntity } from './book.entity';
@Controller('book')
export class BookController {
constructor(private readonly bookService: BookService) {
this.bookService = bookService;
}
/**
* list all books
*/
@Get()
async list(): Promise> {
return this.bookService.list();
}
@Get(':id')
async detail(@Param('id') _id: string): Promise {
return this.bookService.detail(_id);
}
/**
* save new book
* @param book new book data
*/
@Post()
async save(@Body() book: BookEntity): Promise {
return this.bookService.save(book);
}
}
book.service.ts
import { Injectable } from '@nestjs/common';
import { BookEntity } from './book.entity';
const Nedb = require('nedb');
@Injectable()
export class BookService {
private readonly nedb;
constructor() {
this.nedb = new Nedb({
filename: './db/book.db',
autoload: true,
timestampData: true,
});
}
/**
* find all books
*/
async list(): Promise> {
return new Promise((resolve, reject) => {
this.nedb.find({}, (error, docs) => {
if (error) reject(error);
resolve(docs);
});
});
}
async detail(_id: string): Promise {
return new Promise((resolve, reject) => {
this.nedb.find({ _id }, (error, docs) => {
if (error) reject(error);
resolve(docs[0]);
});
});
}
/**
* save new book
* @param book new book
*/
async save(book: BookEntity): Promise {
return new Promise((resolve, reject) => {
this.nedb.insert(book, (error, doc) => {
if (error) reject(error);
resolve(doc);
});
});
}
}
重构代码,封装公共基础类,通过继承实现复用和扩展
业务与数据分离,repository处理数据
app.repository.ts,基础repository,实现CRUD操作
// eslint-disable-next-line @typescript-eslint/no-var-requires
const Nedb = require('nedb');
export class AppRepository {
protected readonly nedb;
constructor(dbName: string) {
this.nedb = new Nedb({
filename: dbName,
autoload: true,
timestampData: true,
});
}
/**
* find all
*/
async findAll(): Promise> {
return this.find({});
}
/**
* find by primary key
* @param _id primary key
*/
async findById(_id: string): Promise {
return new Promise((resolve, reject) => {
this.find({ _id })
.then(res => resolve(res[0]))
.catch(error => reject(error));
});
}
/**
* find by options
* @param options search options
*/
async find(options): Promise> {
return new Promise((resolve, reject) => {
this.nedb.find(options, (error, docs) => {
if (error) {
reject(error);
}
resolve(docs);
});
});
}
/**
* insert new data
* @param data new data
*/
async insert(data: T): Promise {
return new Promise((resolve, reject) => {
this.nedb.insert(data, (error, doc) => {
if (error) {
reject(error);
}
resolve(doc);
});
});
}
/**
* delete by id
* @param _id
*/
async deleteById(_id: string): Promise {
return new Promise((resolve, reject) => {
this.nedb.remove({ _id }, (error, removedNum) => {
if (error) {
reject(error);
}
resolve(removedNum);
});
});
}
}
book.repository.ts,实现复杂数据操作
import { Injectable } from '@nestjs/common';
import { AppRepository } from '../app.repository';
import { BookEntity } from './book.entity';
@Injectable()
export class BookRepository extends AppRepository{
constructor() {
super('./db/book.db');
}
//其他复杂数据操作
// ... ...
}
重写service,封装基础service类并将repository作为依赖引入
app.service.ts,service基类,依赖repository基类
import { AppRepository } from './app.repository';
export class AppService {
constructor(private readonly appRepository: AppRepository) {
this.appRepository = appRepository;
}
/**
* list all
*/
async list(): Promise> {
return this.appRepository.findAll();
}
/**
* get detail
* @param _id
*/
async detail(_id: string): Promise {
return this.appRepository.findById(_id);
}
/**
* save new data
* @param data
*/
async save(data: T): Promise {
return this.appRepository.insert(data);
}
/**
* delete by id
* @param _id
*/
async delete(_id: string): Promise {
return this.appRepository.deleteById(_id);
}
}
重写book.service.ts,依赖book.repository.ts
import { Injectable } from '@nestjs/common';
import { AppService } from '../app.service';
import { BookEntity } from './book.entity';
import { BookRepository } from './book.repository';
@Injectable()
export class BookService extends AppService{
constructor(private readonly bookRepository: BookRepository) {
super(bookRepository);
this.bookRepository = bookRepository;
}
// 除CRUD外复杂业务逻辑
// ... ...
}
同理,重写controller,封装controller基类
app.controller.ts
import { AppService } from './app.service';
import { Body, Delete, Get, Param, Post } from '@nestjs/common';
export class AppController {
constructor(private readonly appService: AppService) {
this.appService = appService;
}
@Get()
async list(): Promise> {
return this.appService.list();
}
@Get(':id')
async detail(@Param('id') _id: string): Promise {
return this.appService.detail(_id);
}
@Post()
async save(@Body() data: T): Promise {
return this.appService.save(data);
}
@Delete(':id')
async delete(@Param('id') id: string): Promise {
return this.appService.delete(id);
}
}
重写book.controller.ts,继承controller基类
import { Controller } from '@nestjs/common';
import { AppController } from '../app.controller';
import { BookEntity } from './book.entity';
import { BookService } from './book.service';
@Controller('book')
export class BookController extends AppController{
constructor(private readonly bookService: BookService) {
super(bookService);
this.bookService = bookService;
}
// 其他复杂逻辑
// ... ...
}
book.module.ts,将book.repository引入
import { Module } from '@nestjs/common';
import { BookController } from './book.controller';
import { BookService } from './book.service';
import { BookRepository } from './book.repository';
@Module({
imports: [],
controllers: [BookController],
providers: [BookService, BookRepository],
})
export class BookModule {}
至此,book模块调整完成,terminal执行
npm run start
启动服务便可通过http://127.0.0.1:300/book访问相关API。
library模块实现,只需继承app.controller.ts,app.service.ts和app.repository.ts基类便可完成CRUD功能
library.module.ts
import { Module } from '@nestjs/common';
import { LibraryController } from './library.controller';
import { LibraryService } from './library.service';
import { LibraryRepository } from './library.repository';
@Module({
imports: [],
controllers: [LibraryController],
providers: [LibraryService, LibraryRepository],
})
export class LibraryModule {}
library.controller.ts
import { Controller, Injectable } from '@nestjs/common';
import { AppController } from '../app.controller';
import { LibraryEntity } from './library.entity';
import { LibraryService } from './library.service';
@Controller('library')
export class LibraryController extends AppController {
constructor(private readonly libraryService: LibraryService) {
super(libraryService);
this.libraryService = libraryService;
}
// other code ...
}
library.service.ts
import { Injectable } from '@nestjs/common';
import { AppService } from '../app.service';
import { LibraryEntity } from './library.entity';
import { LibraryRepository } from './library.repository';
@Injectable()
export class LibraryService extends AppService {
constructor(private readonly libraryRepository: LibraryRepository) {
super(libraryRepository);
this.libraryRepository = libraryRepository;
}
// other code ...
}
library.repository.ts
import { AppRepository } from '../app.repository';
import { LibraryEntity } from './library.entity';
import { Injectable } from '@nestjs/common';
@Injectable()
export class LibraryRepository extends AppRepository {
constructor() {
super('./db/library.db');
}
// other code ...
}
启动服务,访问http://127.0.0.1/library即可调用library CRUD API。
工程源码请访问https://github.com/louie-001/nestjs-nedb-demo.git