nestjs-typeorm树形查询
背景
树形结构是一种常用的存储查询模型,比如后台菜单或评论列表,展开就是一棵树,对于数据库的表来讲,意味着自引用,即有一个外键字段关联本表的主键,该外键字段一般称为parent_id
,由该字段串联起整颗树的结构,在数据量不大的场景中,单纯一个parent_id
即可胜任树形数据的查询,只需对全表数据循环遍历组装,这种方案在前者后台菜单中比较常用
当数据超过一定量级,一次性load全部数据并循环遍历对于io和cpu都是很大的负担也不现实,此时一般增加辅助字段来提升查询性能(空间换时间),以及满足更多样性的查询需求。这里只介绍一种常用的方案-path
,类似于unix的文件夹层级,该字段存储从根节点到该节点的整条路径,比如100.120.200.
:代表这棵树根节点为100,该节点为200,该节点的父节点为120,最大的好处是比单纯的parent_id
更容易获取任意节点的所有子节点
很多orm都内置了树形模型方案,包括typeorm,具体可查看文档Tree Entities,而Materialized Path
就是上述path
方案的实现,开箱即用
问题
不同场景有不同的方案需求,我们限定当前的需求是评论列表,结合当前各大平台如知乎的交互方案,更细化的需求是二级评论列表(非完整树形),第一层为所有的一级评论,一级评论分页加载所有的子评论
继续看typeorm提供的查询方案,有几个相关的方法:findTrees
、findRoots
、findDescendants
、和findDescendantsTree
:
findTrees
:一次性返回所有的评论树findRoots
:一次性返回所有的根节点findDescendants
/findDescendantsTree
:返回一棵树