对于 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(…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...
NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...
使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)
前言: 双亲委派机制对于面试这块来说非常重要,在实际开发中也是经常遇见需要打破双亲委派的需求,今天我们一起来探索一下什么是双亲委派机制,在此之前我们先介绍一下类的加载器。 目录 编辑 前言: 类加载器 1. …...
「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案
在移动互联网营销竞争白热化的当下,推客小程序系统凭借其裂变传播、精准营销等特性,成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径,助力开发者打造具有市场竞争力的营销工具。 一、系统核心功能架构&…...
