对于 NestJS + TypeORM 查询构造器分页功能的简单二次封装
NestJS 作为 Node.js 领域备受欢迎的框架,其与 TypeORM 的结合为开发者提供了强大的 ORM 能力,简化了数据库操作。然而,在处理分页查询时,直接在每个服务方法中重复编写分页逻辑既不高效也容易出错。为此,我们可以通过创建一个通用的分页处理函数,将分页逻辑从业务逻辑中抽离出来,达到代码复用和模块化的目的。
本文将介绍如何对 TypeORM 的查询构造器(QueryBuilder)进行简单的二次封装,以便于我们在 API 层快速实现分页功能,同时保持代码的整洁与可维护性。我们将通过一个具体示例来演示这一过程,即通过封装一个分页查询方法,来查询用户列表并进行相应的数据处理。
我们的目标是设计一个函数setQueryBuilderPagination,它接受一个查询构造器实例、分页参数以及一个可选的回调函数作为参数,返回一个包含分页信息的对象。这个函数将负责处理查询构造器的分页逻辑,如设置每页数量、跳过行数等,同时也支持通过回调函数对查询结果进行后处理。
功能实现
export interface IBackendPaginatedQueryParams {currentPage: number;pageSize: number;
}interface IBackendPaginatedList {currentPage: number;totalPages: number;total: number;pageSize: number;records: any[];
}/*** 为查询构造器设置分页功能。* @async* @template T 泛型类型,继承自 ObjectLiteral。* @param {SelectQueryBuilder<T>} queryBuilder 查询构造器实例。* @param {IBackendPaginatedQueryParams} paginationQueryParams 分页查询参数。* @param {((records: T[]) => T[])?} [callback] 可选的回调函数,用于处理记录数据。* @returns {Promise<IBackendPaginatedList>} 包含当前页、总页数、总数和记录数据的分页信息对象。*/
export const setQueryBuilderPagination = async <T extends ObjectLiteral>(queryBuilder: SelectQueryBuilder<T>,paginationQueryParams: IBackendPaginatedQueryParams,callback?: (records: Record<string, any>[]) => Record<string, any>[]
): Promise<IBackendPaginatedList> => {const { pageSize, currentPage } = paginationQueryParams;queryBuilder.take(pageSize).skip((currentPage - 1) * pageSize);const [recordsRaw, total] = await queryBuilder.getManyAndCount();const records = callback ? callback(recordsRaw) : recordsRaw;return {currentPage: Number(currentPage),totalPages: Math.ceil(total / pageSize),total: Number(total),pageSize: Number(pageSize),records,};
};
核心逻辑讲解
首先,封装的核心在于如何处理分页参数。在setQueryBuilderPagination函数中,我们接收两个主要参数:查询构造器实例queryBuilder和分页查询参数paginationQueryParams。分页参数包括每页显示的记录数pageSize和当前请求的页码currentPage。函数内部首先读取这两个参数,然后利用它们设置查询构造器的分页行为:通过.take(pageSize)限制查询结果的数量,通过.skip((currentPage - 1) * pageSize)确定从哪条记录开始获取数据。这样就完成了基本的分页设置。
数据获取与计数
紧接着,通过调用.getManyAndCount()方法,我们一步完成数据的获取及总记录数的统计。这一步骤至关重要,因为它既高效地获取了当前页面的数据,又提供了计算总页数所需的信息。返回的结果是一个数组,其中第一个元素是查询结果,第二个元素是总记录数。
后处理回调
为了增强灵活性,我们引入了一个可选的回调函数callback,它允许在返回最终结果前对原始查询数据进行进一步加工。例如,我们可以利用这个回调来格式化数据、添加额外属性或进行数据筛选。在示例中,processQueryRecords函数就是一个典型的后处理示例,它遍历查询结果,为每个用户添加一个roleIds属性,该属性包含了用户所有角色的 ID。
返回分页信息对象
最后,我们将分页后的数据整理成统一格式返回给调用者。这个格式通常包含当前页码、总页数、总记录数、每页大小以及具体的记录数据。这样的返回结构对于前端分页展示非常友好,易于解析和处理。
应用实例:用户列表查询
接下来,我们将展示如何在实际业务场景中应用此封装函数。假设我们有一个需求,要查询用户列表,同时需要对查询结果中的角色进行处理,提取每个用户的角色 ID 数组。
export class UserService {constructor(private roleService: RoleService,@InjectRepository(User) private readonly userRepository: Repository<User>) {}async findList(filterDto: UserFilterDto,queryParams: IBackendPaginatedQueryParams) {const queryBuilder = this.userRepository.createQueryBuilder("user").select(["user.id","user.userName","user.email","user.createdTime","user.updatedTime","user.status","user.remark",]).leftJoinAndSelect("user.roles", "roles");const processQueryRecords = (records: Record<string, any>[]) => {return records.map((item: Record<string, any>) => {item.roleIds = item.roles.map((item) => item.id);return item;});};return await setQueryBuilderPagination<User>(queryBuilder,queryParams,processQueryRecords);}
}
相关文章:
对于 NestJS + TypeORM 查询构造器分页功能的简单二次封装
NestJS 作为 Node.js 领域备受欢迎的框架,其与 TypeORM 的结合为开发者提供了强大的 ORM 能力,简化了数据库操作。然而,在处理分页查询时,直接在每个服务方法中重复编写分页逻辑既不高效也容易出错。为此,我们可以通过…...
Kafka消息队列出现消息堆积如何解决
Kafka消息队列出现消息堆积,通常是由于消息生产速度远大于消费速度,可能由消费者处理能力不足、网络问题、Kafka配置不合理等原因导致。以下从多个方面介绍应对消息堆积的方法: 消费者端优化 提升消费并行度 增加消费者实例数量:…...
LeetCode hot100-100
287. 寻找重复数 给定一个包含 n 1 个整数的数组 nums ,其数字都在 [1, n] 范围内(包括 1 和 n),可知至少存在一个重复的整数。假设 nums 只有 一个重复的整数 ,返回 这个重复的数 。你设计的解决方案必须 不修改 数组…...
Vue.js:现代前端开发的灵活框架
大家好!我是 [数擎 AI],一位热爱探索新技术的前端开发者,在这里分享前端和 Web3D、AI 技术的干货与实战经验。如果你对技术有热情,欢迎关注我的文章,我们一起成长、进步! 开发领域:前端开发 | A…...
CUDNN详解
文章目录 CUDNN详解一、引言二、cuDNN的基本使用1、初始化cuDNN句柄2、创建和设置描述符 三、执行卷积操作1、设置卷积参数2、选择卷积算法3、执行卷积 四、使用示例五、总结 CUDNN详解 一、引言 cuDNN(CUDA Deep Neural Network library)是NVIDIA为深度…...
下载并安装MySQL
在Linux系统上下载并安装数据库(以MySQL为例)的步骤如下: 一、下载MySQL 访问MySQL官网 打开浏览器,访问MySQL的官方网站:https://www.mysql.com/。 进入下载页面 在MySQL官网首页,找到并点击“Downloads…...
Linux ffmpeg 基础用法
简介 FFmpeg 是一个强大的开源多媒体框架,用于处理视频、音频和其他多媒体文件和流。它允许转换、录制、编辑、流媒体等等。 安装 Debian/Ubuntu sudo apt update sudo apt install ffmpegRed Hat/CentOS sudo dnf install ffmpegmacOS (via Homebrew) brew i…...
【C++入门】详解(中)
目录 💕1.函数的重载 💕2.引用的定义 💕3.引用的一些常见问题 💕4.引用——权限的放大/缩小/平移 💕5. 不存在的空引用 💕6.引用作为函数参数的速度之快(代码体现) Ǵ…...
深度学习的加速器:Horovod,让分布式训练更简单高效!
什么是 Horovod? Horovod 是 Uber 开发的一个专注于深度学习分布式训练的开源框架,旨在简化和加速多 GPU、多节点环境下的训练过程。它以轻量级、易用、高性能著称,特别适合需要快速部署分布式训练的场景。Horovod 的名字来源于俄罗斯传统舞…...
计算机的错误计算(二百零八)
摘要 用两个大模型计算 arccot(0.9911588354432518e10) . 保留16位有效数字。两个的输出均是错误的。代码的输出格式亦均出错。 本节题目为一读者来信提议(不知该题目有何玄机?)。 例1. 计算 arccot(0.9911588354432518e10) . 保留16位有…...
海康机器人IPO,又近了一步
导语 大家好,我是社长,老K。专注分享智能制造和智能仓储物流等内容。欢迎大家到本文底部评论区留言。 海康机器人的IPO之路,一路跌宕起伏,让无数投资者和业内人士关注。这不仅仅是一家企业的上市之旅,更是中国智能制造…...
【环境搭建】Metersphere v2.x 容器部署教程踩坑总结
前言 Metersphere部署过程中遇到的问题有点多,原因是其容器的架构蛮复杂的,比较容易踩坑,所以记录一下。 介绍 MeterSphere 是开源持续测试平台,遵循 GPL v3 开源许可协议,涵盖测试管理、接口测试、UI 测试和性能测…...
系统看门狗配置--以ubuntu为例
linux系统配置看门狗 以 ubuntu 系统配置看门狗为例 配置看门狗使用的脚本文件,需要使用管理员权限来执行: 配置是:系统每 30S 喂一次狗,超过 60S 不进行投喂,就会自动重启。 1. 系统脚本内容: #!/bin/b…...
阅读笔记——《A survey of protocol fuzzing》
【参考文献】Zhang X, Zhang C, Li X, et al. A survey of protocol fuzzing[J]. ACM Computing Surveys, 2024, 57(2): 1-36.【注】本文仅为作者个人学习笔记,如有冒犯,请联系作者删除。 目录 1、Introduction 2、Background 2.1、Communication Pro…...
C# 语法中级
总目录 C# 语法总目录 C# 语法中级 lambda 表达式1. 捕获外部变量2. 捕获迭代变量 匿名类型匿名方法异常相关1. 枚举器2. 可枚举对象3. 迭代器3. 迭代器语义4. yield break 语句5. 组合序列 可空类型1. Nullable< T > 结构体 lambda 表达式 编译器在内部将lambda表达式编…...
STORM:从多时间点2D图像中快速重建动态3D场景的技术突破
随着计算机视觉和机器学习技术的迅猛发展,我们已经能够利用AI来解决许多复杂的问题。然而,在处理大规模室外动态3D场景重建时,现有的方法往往面临着诸多挑战,如需要大量人工标注数据、处理速度慢以及难以准确捕捉移动物体等。为了解决这些问题,研究者们开发了STORM(Spati…...
excel前缀和(递增求和)
方法一:https://www.zhihu.com/zvideo/1382164996659515392?utm_id0 假设输入数据在B2:B10,选中单元格C2,输入SUM(B2:B2,然后选中其中的B2,按F4(或者直接输入SUM(B$2:B2),回车确认&…...
【AI日记】25.01.11 Weights Biases | AI 笔记 notion
【AI论文解读】【AI知识点】【AI小项目】【AI战略思考】【AI日记】【读书与思考】 AI kaggle 比赛:Forecasting Sticker Sales笔记:我的 AI 笔记主要记在两个地方 有道云笔记:数学公式和符号比较多的笔记notion:没什么数学公式的…...
P8772 [蓝桥杯 2022 省 A] 求和
题目描述 给定 𝑛 个整数 𝑎1,𝑎2,⋯ ,𝑎𝑛 求它们两两相乘再相加的和,即 𝑆𝑎1⋅𝑎2𝑎1⋅𝑎3⋯𝑎1⋅𝑎𝑛&…...
【Oracle篇】深入了解执行计划中的访问路径(含表级别、B树索引、位图索引、簇表四大类访问路径)
💫《博主介绍》:✨又是一天没白过,我是奈斯,从事IT领域✨ 💫《擅长领域》:✌️擅长阿里云AnalyticDB for MySQL(分布式数据仓库)、Oracle、MySQL、Linux、prometheus监控;并对SQLserver、NoSQL(…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...
关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...
AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
佰力博科技与您探讨热释电测量的几种方法
热释电的测量主要涉及热释电系数的测定,这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中,积分电荷法最为常用,其原理是通过测量在电容器上积累的热释电电荷,从而确定热释电系数…...
springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...
算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...
