文章发布在专栏NestJS最佳实践中

代码地址:github.com/slashspaces…

学习方针

  • 软删去与康复
  • 批量删去与批量康复

什么是软删去

软删去是一种广泛应用于业务应用程序的模式。它允许您将一些记载标记为已删去,而无需从数据库中真正删去。因此,能够在防止软删去的记载被选中的一起,旧记载仍然能够被引用。

经过软删去,咱们能够完成相似于回收站的功用,比如将文章软删去后放进回收站,后面也能够从回收站中康复。

TypeORM软删去及康复用法

  1. 在Entity中运用@DeleteDateColumn()装饰器

    @DeleteDateColumn()
    public deletedAt: Date;
    
  2. 软删去: 运用softRemove替代remove

    • 履行softRemovedeletedAtnull变为具体删去日期
  3. 康复: 运用restore办法康复数据

    • 履行restoredeletedAt由具体删去日期变为null
  4. 查询: 当咱们运用find()或相似办法查询时,TypeORM会主动取查询deletedAtNULL的记载,当然咱们也能够指定withDeleted字段来控制是否查询软删去数据

    const category = await this.categoriesRepository.findOne(id, {
        relations: ['posts'],
        withDeleted: true
    }
    

如下图所示, deletedAt一列为日期代表该条数据被软删去,为null则为正常数据

NestJS最佳实践--#7 软删除及恢复实现回收站功能

批量删去与康复DTO

由于各模块都会用到软删去及康复功用,因此咱们提取出DeleteDtoRestoreDtosrc/common/dtos 目录下,作为大局共用DTO

/**
 * 批量删去
 */
export class DeleteDto {
    @IsUUID(undefined, { each: true, message: 'ID格局过错' })
    @IsDefined({ each: true, message: 'ID有必要指定' })
    ids: string[] = [];
    // 是否为软删去
    @Transform(({ value }) => Boolean(value))
    @IsBoolean()
    @IsOptional()
    soft?: boolean;
}
/**
 * 批量康复
 */
export class RestoreDto {
    @IsUUID(undefined, { each: true, message: 'ID格局过错' })
    @IsDefined({ each: true, message: 'ID有必要指定' })
    ids: string[] = [];
}

软删去及数据康复

接下来咱们要完成文章模块的软删去及数据康复 首先给QueryPostDto加上soft字段用来判断是否查询软删去数据

@DtoValidation({ groups: ['query'] })
export class QueryPostDto extends PaginationDto {
    @IsUUID(undefined, { message: '分类ID格局过错' })
    @IsOptional()
    category?: string;
    @IsEnum(SelectSoftDeleteMode)
    @IsOptional()
    soft?: SelectSoftDeleteMode;
}
  • @IsEnum: 校验soft值是否为指定枚举值

接下来修改一下PostService

  • DeleteDto中soft为true代表软删去,要履行softRemove
  • DeleteDto中soft不设置或设为false,代表物理删去,要履行remove
@Injectable()
export class PostService {
    // ...
    async remove({ ids, soft }: DeleteDto) {
        const posts = await this.postsRepository.find({
            where: { id: In(ids) },
            withDeleted: false, // 过滤掉已删去的
        });
        if (soft) return this.postsRepository.softRemove(posts);
        return this.postsRepository.remove(posts);
    }
    async restore({ ids }: RestoreDto) {
        const posts = await this.postsRepository.find({
            where: { id: In(ids) },
            withDeleted: true,
        });
        // 过滤掉不在回收站中的数据
        const deletedIds = posts.filter((post) => !isNil(post.deletedAt)).map((post) => post.id);
        this.postsRepository.restore(deletedIds);
    }
    // ...
}

最后修改下PostController

@Controller('post')
export class PostController {
    // ...
    @Post('delete')
    remove(@Body() data: DeleteDto) {
        return this.postService.remove(data);
    }
    @Patch('restore')
    restore(@Body() data: RestoreDto) {
        return this.postService.restore(data);
    }
    // ...
}

这样咱们就完成了文章的批量删去,软删去与批量康复功用啦.至于分类和评论模块的软删去与康复,代码与文章模块相似, 只不过要注意下树形结构的级联操作,这里就不再赘述。