当前位置: 首页 > 后端技术 > Node.js

Nestjs最佳实践教程:4排序、分页和过滤

时间:2023-04-03 20:28:00 Node.js

视频地址:https://www.bilibili.com/video...如有疑问,请扫描视频中的QQ群二维码进行交流。另外,我正在找工作,希望有一个远程工作匹配(不能去其他地方)。有有需要的老板可以看看我个人介绍:pincman.com/aboutLearning目标重载TreeRepository有自己的方法将树结构中的数据压平,并对Typeorm查询到的数据列表进行分页通过请求中的查询Query对数据进行过滤,如排序,过滤等实现发布和取消发布Typeorm模型事件的功能以及Subscriber(订阅者)的使用使用sanitize-html防止文章内容注入攻击预装依赖nestjs-typeorm-paginate实现paginationsanitize-html过滤html标签,防止注入攻击模块/内容&&\mkdir订阅者&&\touchdtos/query-category.dto.ts\dtos/query-post.dto.ts\subscribers/post.subscriber.ts\subscribers/index.ts\services/sanitize.service。ts\&&cd../../../和上一节一样,本节的新增和修改主要集中在ContentModulesrc/modules/content├──constants.ts├──content.module.ts├──controllers│├──category.controller.ts│├──comment.controller.ts│├──index.ts│└──post.controller.ts├──dtos│├──create-category.dto。ts│├──创客nt.dto.ts│├──create-post.dto.ts│├──index.ts│├──query-category.dto.ts│├──query-post.dto.ts│├──update-category.dto.ts│└──update-post.dto.ts├──entities│├──category.entity.ts│├──comment.entity.ts│├──index.ts│└──post.entity.ts├──repositories│├──category.repository.ts│├──comment.repository.ts│├──index.ts│└──post.repository.ts├──services│├──category.service.ts│├──comment.service.ts│├──index.ts│├──post.service.ts│└──sanitize.service.ts└──subscribers├──index.ts└──post.subscriber.ts应用编码部分新增了一个概念,即subscriber。详情请参考typeorm文档。当然你也可以在模型中使用事件处理函数,效果是一样的。ModelCategoryEntity代码:src/modules/content/entities/category.entity.ts增加排序字段增加level属性(虚字段),在展平树数据时添加当前item的levelPostEntity代码:src/modules/content/entities/post.entity.tstype字段的类型是用enum枚举设置的。首先,您需要定义一个枚举类型PostBodyType。您可以添加一个constants.ts文件来统一定义这些枚举和常量。添加publishedAt字段,控制发布时间和发布状态。添加type字段用于设置发布类型,customOrder字段用于自定义排序存储类CategoryRepository代码:src/modules/content/repositories/category.repository.ts因为CategoryRepository继承自TreeRepository,所以我们在typeorm源码中找到了这个类,覆盖了一些方法,这样我们就可以对树分类进行排序,覆盖方法如下如下。当然,更深入的重封装我们后面会讲到。暂时使用findRoots为根类别列表查询添加排序。创建后代查询生成器。而QueryPostDto用于查询分类和文章时的分页,过滤数据和设置排序类型等。在添加DTO之前,现在添加几个数据转义函数,将请求中的字符串改为需要的数据类型//src/core/helpers.ts//用于在请求验证导出函数中转义数字数据tNumber(value?:string|number):string|number|undefined//请求验证导出函数中用于转义boolean数据tBoolean(value?:string|boolean):string|boolean|undefined//请求验证时用于转义nullexport函数tNull(value?:string|null):string|空|undefined修改create-category.dto.ts和create-comment.dto.ts的parent字段的@Transform装饰器exportclassCreateCategoryDto{...@Transform(({value})=>tNull(value))parent?:string;}添加一个通用的DTO接口类型//src/core/types.ts//分页验证DTO接口exportinterfacePaginateDto{p年龄:数字;limit:number;}QueryCategoryDto代码:src/modules/content/dtos/query-category.dto.tspage属性设置当前页limit属性设置每页数据量orderBy用于设置排序类型isPublished根据发布状态过滤文章分类过滤出该分类下的文章及其后代。按时间降序PUBLISHED:按发布时间降序COMMENTCOUNT:按评论数降序CUSTOM:按自定义排序字段升序服务类SanitizeService代码:src/modules/content/services/sanitize.service.ts该服务类用于cleanhtmlsanitize方法用于HTML数据的防注入处理CategoryService代码:src/modules/content/services/category.service.ts添加一个helperfunction用于分页扁平树数据//src/core/helpers.tsexportfunctionmanualPaginate({page,limit}:PaginateDto,data:T[],):Pagination添加paginate(query:QueryCategoryDto)处理分页的方法asyncpaginate(query:QueryCategoryDto){//获取树数据consttree=awaitthis.findTrees();//展平树数据constlist=awaitthis.categoryRepository.toFlatTrees(tree);//调用手动分页函数进行分页返回manualPaginate(query,list);}PostService代码:src/modules/content/services/post.service.tsgetListQuery:查询构建器,用于构造过滤排序等功能,通过分类查询文章数据paginate:调用getListQuery生成查询,并将数据分页为nestjs-typeorm-paginateasyncpaginate(params:FindParams,options:IPaginationOptions)的分页参数{constquery=awaitthis.getListQuery(params);returnpaginate(query,options);}SubscriberPostSubscriber代码:src/modules/content/subscribers/post.subscriber.tsbeforeInsert(插入数据前的事件):如果在添加文章的同时发布了文章,设置当前时间作为发布时间beforeUpdate(更新数据前的事件):change发布状态会同时更新发布时间的值。如果文章更新为未发布状态,发布时间会设置为nullafterLoad(加载数据后的事件):对HTML类型的文章内容去标签,防止注入攻击。需要注意的一点需要在订阅者类的构造函数中注入Connection,获取链接构造函数(connection:Connection,protectedsanitizeService:SanitizeService,){connection.subscribers.push(this);}注册订阅者将订阅者注册为服务后,由于构造函数中注入了connection的连接对象,所以typeorm会自动加载到默认连接的subscribers配置中//src/modules/content/subscribers/post.subscriber。tsimport*作为潜艇scribeMapsfrom'./subscribers';constsubscribers=Object.values(SubscriberMaps);@Module({....providers:[...subscribers,...dtos,...services],})CategoryController代码:src/modules/content/controllers/category.controller.tslist:通过分页索引查找平面分类列表:设置url为@Get('tree')@Get()//分页查询asynclist(@Query(newValidationPipe({transform:true,forbidUnknownValues:true,validationError:{target:false},}),)查询:QueryCategoryDto,){returnthis.categoryService.paginate(query);}//查询树分类@Get('tree')asyncindex(){returnthis.categoryService.findTrees();}PostController代码:src/modules/content/controllers/post.controller.ts修改index方法进行分页查询//通过分页方式查询数据asyncindex(@Query(newValidationPipe({transform:true,forbidUnknownValues:true,validationError:{target:false},}),){page,limit,...params}:QueryPostDto,){returnthis.postService.paginate(params,{page,limit});}