采用左右值编码来存储无限分级树形结构

参考文档:

https://blog.csdn.net/comiunknown/article/details/1586020

python实现:

from app.cmdb.config import dbconfig, cmdbsql, modelconfig, balantsql
from app.cmdb.utils.dbutil import MysqlConnect

balant_connect = MysqlConnect(db_params=dbconfig.balant_db_params_sit)
# cmdb_connect = MysqlConnect(db_params=dbconfig.cmdb_db_params)

class CatalogTemplate(object):

    def __init__(self, tag_id, catalog_id):
        """
        :param tag_id: 基准节点
        :param catalog_id: 基准目录
        """
        self.tag_id = tag_id
        self.catalog_id = catalog_id
        (self.lft, self.rht) = self.get_lft_rht()

    def get_tag(self):
        """
        获取节点id
        :return: 0 或 id
        """
        try:
            catalog_tag_id = balant_connect.query_execute(
                    """select id from mon_catalog_tag where tag_id = %d and catalog_id = %d""" % (self.tag_id, self.catalog_id))
            if catalog_tag_id:
                return catalog_tag_id[0][0]
            else:
                return 0
        except:
            return 0

    def get_lft_rht(self):
        """
        获取该节点的左右id
        :return:列表[lft, rht]
        """
        try:
            if self.get_tag():
                result = balant_connect.query_execute("""select lft, rht from mon_catalog_tag
                where tag_id = %d and catalog_id = %d limit 1""" % (self.tag_id, self.catalog_id))
                return result[0]
            else:
                return 0, 0
        except Exception as e:
            raise Exception("记录不存在,info %s" % e)

    def get_layer(self):
        """
        获取节点层级
        :return: 层数
        """
        try:
            if self.get_tag():
                result = balant_connect.query_execute("""select count(*) from mon_catalog_tag where lft <= '%d' and rht >= 
    %d and catalog_id = %d""" % (self.lft, self.rht, self.catalog_id))
                return result[0][0]
            else:
                return 0
        except Exception as e:
            raise Exception("记录不存在,info %s" % e)

    def get_tree_list(self):
        """
        获取该节点及其子孙节点
        :return:节点列表
        """
        if self.get_tag():
            try:
                return balant_connect.query_execute("""select * from 
    (SELECT tag_id, lft, rht, %d as layer FROM mon_catalog_tag where catalog_id = %d ORDER BY lft) AS TreeList where lft between %d and %d order by lft 
    asc""" % (self.get_layer(), self.catalog_id, self.lft, self.rht))
            except Exception as e:
                raise Exception("记录不存在,info %s" % e)

    def add_sub_node(self, tag_name, catalog_name):
        """
        插入子节点, 只能添加末节点
        :param tag_name:待插入节点的名称
        :param catalog_name:待插入目录的名称
        :return: 无
        """
        tag_id = balant_connect.query_execute("""select id from mon_tag where name = '%s'""" % tag_name)
        catalog_id = balant_connect.query_execute("""select id from mon_catalog where name = '%s'""" % catalog_name)
        insert_tag_id = balant_connect.query_execute(
            """select id from mon_catalog_tag where tag_id = %d and catalog_id = %d""" % (tag_id[0][0], catalog_id[0][0]))
        if self.get_tag() and not insert_tag_id:
            rht = balant_connect.query_execute("""select rht from mon_catalog_tag where tag_id = %d""" % self.tag_id)
            balant_connect.dml_execute("""update mon_catalog_tag set rht=rht+2 where rht>=%d""" % rht[0][0])
            balant_connect.dml_execute("""update mon_catalog_tag set lft=lft+2 where lft>=%d""" % rht[0][0])
            balant_connect.dml_execute("""insert into mon_catalog_tag (parent_id, lft, rht, tag_id, catalog_id) 
values (%d,%d,%d,%d,%d)""" % (self.get_tag(), rht[0][0], int(rht[0][0])+1, tag_id[0][0], catalog_id[0][0]))
        else:
            print("插入节点错误,请检查参数和层级关系!")
            return

    def del_node(self, tag_name, catalog_name):
        """
        删除节点
        :param tag_name:待插入节点的名称
        :param catalog_name:待插入目录的名称
        :return: 无
        """
        tag_id = balant_connect.query_execute("""select id from mon_tag where name = '%s'""" % tag_name)
        catalog_id = balant_connect.query_execute("""select id from mon_catalog where name = '%s'""" % catalog_name)
        del_tag_id = balant_connect.query_execute(
            """select id from mon_catalog_tag where tag_id = %d and catalog_id = %d""" % (
            tag_id[0][0], catalog_id[0][0]))
        lft_rht = balant_connect.query_execute("""select lft, rht from mon_catalog_tag
        where tag_id = %d and catalog_id = %d limit 1""" % (tag_id[0][0], catalog_id[0][0]))
        lft_id = lft_rht[0][0]
        rht_id = lft_rht[0][1]
        if self.get_tag() and del_tag_id:
            balant_connect.dml_execute("""delete from mon_catalog_tag where lft>=%d and rht<=%d""" % (lft_id, rht_id))
            balant_connect.dml_execute("""update mon_catalog_tag set lft=lft-(%d-%d+1) where lft>%d""" % (rht_id, lft_id, lft_id))
            balant_connect.dml_execute("""update mon_catalog_tag set rht=rht-(%d-%d+1) where rht>%d""" % (rht_id, lft_id, rht_id))
        else:
            print("插入节点错误,请检查参数和层级关系!")
            return

    def move_node(self):
        pass

def target_add_tag():
    """
    查询所有tag信息,更新tag表和目录表
    :return:
    """
    data_mw = dict()
    sql_cmdb = cmdbsql.cmdb_select_app_tag
    # result = cmdb_connect.query_execute(sql_cmdb, db_params=dbconfig.cmdb_db_params)
    result = [('ASURA-BAR', 'ASU_BAR_CNSZ17_WAS', 'IBM WAS 6.x', 'ASU_BAR_CNSZ17_WAS_01', '生产')]
    #  sysCode   | vclName              | soft        | hostname | env
    # [('ASURA-BAR', 'ASU_BAR_CNSZ17_WAS', 'IBM WAS 6.x', 'ASU_BAR_CNSZ17_WAS_01', '生产')]

    for i in result:
        cur = balant_connect.query_execute(balantsql.balant_select_tag % i[3])
        print(cur)
        # [(None, 'ASU_BAR_CNSZ17_WAS_01', 'middleware', 7092)]
        try:
            # 更新tag
            if cur[0][0] is None:
                balant_connect.dml_execute(balantsql.balant_update_tag % (i[0], i[0]))
                balant_connect.dml_execute(balantsql.balant_update_target_tag % (i[3], i[0], i[3], i[0]))
                balant_connect.dml_execute(balantsql.balant_update_tag % (i[1], i[1]))
                balant_connect.dml_execute(balantsql.balant_update_target_tag % (i[3], i[1], i[3], i[1]))
                balant_connect.dml_execute(balantsql.balant_update_tag % (i[4], i[4]))
                balant_connect.dml_execute(balantsql.balant_update_target_tag % (i[3], i[4], i[3], i[4]))
            elif i[0] not in cur[0][0]:  # 判断cmdb是否存在tag
                balant_connect.dml_execute(balantsql.balant_update_tag % (i[0], i[0]))
                balant_connect.dml_execute(balantsql.balant_update_target_tag % (i[3], i[0], i[3], i[0]))
            elif i[1] not in cur[0][0]:  # 判断cmdb是否存在tag
                balant_connect.dml_execute(balantsql.balant_update_tag % (i[1], i[1]))
                balant_connect.dml_execute(balantsql.balant_update_target_tag % (i[3], i[1], i[3], i[1]))
            elif i[4] not in cur[0][0]:  # 判断cmdb是否存在tag
                balant_connect.dml_execute(balantsql.balant_update_tag % (i[4], i[4]))
                balant_connect.dml_execute(balantsql.balant_update_target_tag % (i[3], i[4], i[3], i[4]))
            # 更新catalog
            sysCode_tag_id = balant_connect.query_execute("""select id from mon_tag where name = '%s'""" % i[0])
            catalog_id = balant_connect.query_execute("""select id from mon_catalog where name = '应用'""")
            catalog = CatalogTemplate(0, catalog_id[0][0])
            catalog.add_sub_node(i[0], "应用")
            catalog = CatalogTemplate(sysCode_tag_id[0][0], catalog_id[0][0])
            catalog.add_sub_node(i[1], "应用")
        except Exception as e:
            raise Exception("Error info: %s" % e)

    return data_mw

原文地址:http://blog.51cto.com/strongit/2116866

时间: 2024-10-10 00:12:47

采用左右值编码来存储无限分级树形结构的相关文章

采用左右值编码实现无限分级树形结构(转)

无限分级树形结构是在系统开发中很常见的,如下图 在之前实现这样的菜单一直是使用传统的方法,看数据表结构就一目了然 parent_id记录其直接父节点,组合树形结构的关键字段:parent_list记录其所有父节点,便于查询某个节点下所有子节点(一般使用MySQL的FIND_IN_SET函数),相对冗余.对于这种结构生成树形的关键算法:根据parent_id组合一个父子(直接关系)节点映射表,即 2 => array(3, 4), 3 => array(5),然后递归优先遍历每个节点的子节点.如

数据库存储 层次、树形结构 的标准做法

标准做法有3种: 1.最早的做法:节点id里包含完整路径(曾祖父id-爷id-父id-本id) 財务的会计科目编号就是这么做的 如今基本非常少使用了 2.递归做法:父id,本id(更早.完整的关系提供递归才干得到) 眼下比較普遍 优点是直观简单,增删方便 坏处是生成树须要递归 3.直接保存法:本id,根id,层次数,在根(子树)里的序号 好像没看到别人这么用的,我在自己的树形论坛离线阅读器里採用过 优点是避免了递归.生成树记录高效方便 坏处是增删节点.须要更新半个子树的节点记录 (曾公布在: h

树形结构的数据库表Schema设计-基于左右值编码

树形结构的数据库表Schema设计 程序设计过程中,我们常常用树形结构来表征某些数据的关联关系,如企业上下级部门.栏目结构.商品分类等等,通常而言,这些树状结构需要借助于数据库完 成持久化.然而目前的各种基于关系的数据库,都是以二维表的形式记录存储数据信息,因此是不能直接将Tree存入DBMS,设计合适的Schema及其对 应的CRUD算法是实现关系型数据库中存储树形结构的关键. 理想中树形结构应该具备如下特征:数据存储冗余度小.直观性强:检索遍历过程简单高效:节点增删改查CRUD操作高效.无意

无限分级和tree结构数据增删改【提供Demo下载】

无限分级 很多时候我们不确定等级关系的层级,这个时候就需要用到无限分级了. 说到无限分级,又要扯到递归调用了.(据说频繁递归是很耗性能的),在此我们需要先设计好表机构,用来存储无限分级的数据.当然,以下都是自己捣鼓的结果,非标准.谁有更好的设计望不吝啬赐教. 说来其实也简单,就是一个ID和父ID的关系. 以此类推,Id需要是唯一的,ParenId需要是Id列里面存在即可.这样我们就实现无限分级了,如果再加一列Sort排序就更完美了. jstree插件 官方地址:https://www.jstre

OC8-属性 KVC是键值编码

1.属性,是oc提供的一种快速的模式化的创建实例变量的方式. (1)属性是通过@property标记的, (2)属性会在背后,默默的帮我们做set和get方法 2.属性做的工作 (1)创建一个实例变量,名字是下划线加属性名, (2)帮我们自动get和setter 的方式,创建一组方法, 3.点语法,点语法是专门为了setter 和getter 方法配备的一种语法糖.会自动根据语法和语境调用是哪一种方法, (1) (.)其实就是转换成了getter 和setter 方法,p.hobby.lengt

【OC学习-31】利用KVC即键值编码来访问一些对象的属性,尽管这些属性是私有的

最简单的想法是我们创建一个对象,然后利用某些方法给这个对象赋值,然后再用某些方法调用这个值.当然这种描述很类似于字典的键值概念,确实今天学习的就是这样一种方法:KVC,Key-Value coding键值编码. (1)简单的KVC 创建一个Book类,在Book.h里写一个私有的实例变量name,然后再main.m里创建一个book1对象,再给这个book1对象的私有变量name赋值,然后再调用这个值.神奇的地方就在这里:这种方法根本不管这个实力变量是private还是public.呃,Book

IOS开发之旅-KVC【键值编码】

在日常开发中,读取修改对象的属性值时,通常是点调用对应的属性进行相关操作.另外一种方式是通过键值编码,简称KVC,在键值编码中主要使用以下方法 /* Given a key that identifies an attribute or to-one relationship, return the attribute value or the related object. Given a key that identifies a to-many relationship, return a

KVC-键值编码是一种间接地访问实例变量的方式

KVC 键值编码是一种间接的访问实例变量的方式[对象 setValue:@"A" forKey:@"name"]; 工作原理:    1.先查找该类有没有对应的setName: setter方法.如果有则调用setter方法给实例变量赋值,如果没有,转到第二步:    2.在查找带下划线的实例变量_name.如果有则给_name赋值,如果没有则转到第三步    3.最后查找和key值相同的实例变量name,如果有,则给name赋值,如果没有,转到第四步    4.调

Objective-C(十七、KVC键值编码及实例说明)——iOS开发基础

结合之前的学习笔记以及参考<Objective-C编程全解(第三版)>,对Objective-C知识点进行梳理总结.知识点一直在变,只是作为参考,以苹果官方文档为准~ 十七.键值编码 KVC 关于KVC的知识点将通过下列例子来展开说明: Person.h文件,Person类拥有name和age两个成员变量 @interface Person : NSObject { @private NSString *_name; NSInteger _age; } - (void)setAge:(NSIn