无限级分类的数据库设计

文章目录

      • 场景
      • 分析
      • 邻接列表模式
      • 物化路径模式
      • 闭包表

场景

  • 无限级分类是经常遇到的设计模式

分析

  • 无限级分类常用的模式 (每种模式都是根据需要选择)
    • 邻接列表模式
    • 物化路径模式
    • 闭包表模式

邻接列表模式

  • 表结构
    • node_id
    • parent_id
    • name
  • 优点
    • 操作简单
  • 缺点
    • 生成一棵树很难
  • 适合场景
    • 4层结构之内的分类

物化路径模式

  • 表结构
    • path
    • name
  • 缺点
    • 理论上不能实现真正的无限级别分类,因为path总有长度的限制
  • 优点
    • 查询后代 祖代 父级 子级 很方便, 很容易生成一棵树适合: 明确知道层级的树, eg: 生物科目, 国家行政区划
  • 查询
    • 后代
      • select * from path_tree where path like "/1/%
    • 子代
      • select * from path_tree where path regexp “/1/[0-9]*$”
    • 祖代
      • select * from path_tree where “/1/110000/110100/110101” like concat(path, ‘%’) and path <> “/1/110000/110100/110101”

闭包表

  • 表结构(需要两张表)

    • 节点表
      • name
      • id
    • 关系表
      • ancestor_id 祖代ID
      • descendant_id 后代ID
      • distance 祖代节点到后代节点的距离
  • 优点

    • 空间换时间 查询时非常快的
    • 获取特定$node下的一个树也很简单
      • 获取 n o d e 所 有 的 后 代 节 点 的 子 节 点 集 合 node所有的后代节点的子节点集合 nodecollection
      • 对$collection进行轮询转换操作就可以生成一棵树了
  • 查询

    • set $collect = 本节点以及节点的后代集合
    • 删除:
      • 删除祖先ID是$collect
      • 删除后代ID是$collect
      • 删除节点表中的$collect
    • 节点迁移:
      • 删除后代ID是 c o l l e c t 的 collect的 collectnode的祖代
      • 插入新的后代ID是 c o l l e c t 的 collect的 collectnode新的祖代
    • 添加
      • 在关系表中添加一条distance=0 的数据
        • 可以某些时候可以帮助更快的一棵树, SELECT * FROM book_closure_relationship where ancestor_id=3;如果没有到本身的节点,还要自己在做下附加
      • 如果插入的是全新的没有后代关系的新节点, 则插入新节点与祖代关系
      • 如果是在原本的树中插入一个新的层级节点,则重复上一步骤,然后进行节点迁移
		
        // 具体的整合过程类似邻接列表模式
        $list_permissions = \Ultraware\Roles\Models\Permission::all()->toArray();
        $list_permissions = array_column($list_permissions, null, 'id');
        $list_container = [];
        foreach ($list_permissions as $key => $permission) {
            $parent_id = $permission['parent_id'];

            // 如果是顶级的话  则不需要寻找父级
            if (!$parent_id) {
                $list_container[] = &$list_permissions[$key];
                continue;
            }

            // 给对应的父生成子级
            $list_permissions[$parent_id]['sons'][] = &$list_permissions[$key];
        }
        return $list_container;

你可能感兴趣的:(php)