如何用Prisma实现自关联分类的全层级完整级联树查询
Prisma实现递归自关联全量分类树的实现方案
首先明确核心结论:
- 你提到的递归全量eager loading需求,原生Prisma的静态
include语法本身不支持无限层级的递归关联拉取,你当前写的查询只会固定嵌套1层parent和children数据,无法一次返回完整的多分类层级树。 - 这类需求没有内置的开箱即用单API支持,目前两类生产环境常用的落地路径如下:
方案1:全量查询后内存组装树(最推荐,性能最优)
这类方案全程最多触发1-2次数据库查询,不会因为分类层级深度增加额外请求,是绝大多数业务场景的首选实现方式。
实现流程:
- 一次性查询全量平铺的分类数据,不需要任何关联嵌套
- 在应用内存里通过id和parentId的映射关系,把平铺列表组装成带嵌套children的树结构
示例代码:
// 第一步:拉取全量平铺分类,可根据业务需要加排序、过滤规则 const flatCategories = await db.category.findMany({ orderBy: { id: 'asc' } }) // 第二步:内存组装嵌套树 function buildCategoryTree(flatList: typeof flatCategories) { // 建立id到节点的映射,避免循环查找降低性能 const nodeMap = new Map<number, typeof flatList[number] & { children: any[] }>() const rootNodes: typeof flatList[number][] = [] // 给每个节点初始化空的children数组 flatList.forEach(category => { nodeMap.set(category.id, { ...category, children: [] }) }) // 遍历建立父子关联 nodeMap.forEach(node => { if (node.parentId) { const parentNode = nodeMap.get(node.parentId) parentNode?.children.push(node) } else { // parentId为空的节点就是分类树的根节点 rootNodes.push(node) } }) return rootNodes } const fullCategoryTree = buildCategoryTree(flatCategories)
方案优势:
- 不管分类有10层还是上百层,数据库请求次数始终是1次,性能远优于逐层级查库的实现
- 组装逻辑灵活,可随时调整子节点排序、过滤隐藏分类、自定义节点返回字段
- 无数据库版本依赖,MySQL、PostgreSQL、SQLite等所有Prisma支持的数据库都能兼容
方案2:原生查询执行递归CTE(单数据库查询)
如果你的数据库版本支持递归公用表表达式(CTE)(MySQL 8.0+、PostgreSQL全版本、SQL Server都支持),可以通过Prisma的$queryRaw接口直接执行递归查询,在数据库层完成层级遍历。
示例逻辑:
const flatTreeList = await db.$queryRaw` WITH RECURSIVE category_hierarchy AS ( -- 锚点层:查所有根节点 SELECT id, name, "parentId" FROM Category WHERE "parentId" IS NULL UNION ALL -- 递归层:关联找出所有层级的子节点 SELECT c.id, c.name, c."parentId" FROM Category c INNER JOIN category_hierarchy ch ON c."parentId" = ch.id ) SELECT * FROM category_hierarchy ` // 拿到的结果仍是平铺的层级列表,可以复用方案1的内存组装逻辑生成嵌套树结构
方案注意点:
- 不同数据库的递归CTE语法存在细微差异,需要根据实际使用的数据库做对应调整
- 递归查询需要设置深度上限,避免无限递归触发数据库的查询超时、内存溢出问题
- 相比方案1开发复杂度更高,但可以在数据库层直接完成权限过滤、数据裁剪,适合分类数据量特别大的场景
避坑提醒:不要写递归循环调用
db.category.findMany逐层级查子节点的逻辑,这种写法会随着分类层级深度线性增加数据库请求次数,属于典型的N+1查询问题,生产环境很容易拖慢接口甚至打挂数据库。
内容的提问来源于stack exchange,提问作者s-leg3ndz
相关产品推荐
相关产品推荐

