Prechádzať zdrojové kódy

修改数据模型的neo4j操作,以适应neo4j 5.0版本版本的变化。
用elementId作为访问唯一标识,以适应neo4j 5.0版本版本的变化。

maxiaolong 1 mesiac pred
rodič
commit
3fff75e6a7
2 zmenil súbory, kde vykonal 197 pridanie a 149 odobranie
  1. 14 7
      app/api/data_model/routes.py
  2. 183 142
      app/core/data_model/model.py

+ 14 - 7
app/api/data_model/routes.py

@@ -127,13 +127,17 @@ def data_model_detail():
     try:
         # 传入请求参数
         receiver = request.get_json()
-        id = int(receiver.get('id'))
+        # 直接使用字符串ID,不做类型转换
+        id = receiver.get('id')
+        print(f"Received elementId from frontend: {id}")
 
         response_data = model_functions.handle_id_model(id)
         res = success(response_data, "success")
         return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
 
     except Exception as e:
+        import traceback
+        traceback.print_exc()
         res = failed({}, {"error": f"{e}"})
         return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
 
@@ -144,12 +148,13 @@ def data_model_delete():
     try:
         # 传入请求参数
         receiver = request.get_json()
-        id = receiver['id']
+        id = receiver.get('id')
+        print(f"Deleting data model with elementId: {id}")
 
         # 首先删除数据模型节点
         from app.services.neo4j_driver import neo4j_driver
         query = """
-        MATCH (n:data_model) where id(n) = $nodeId
+        MATCH (n:data_model) where elementId(n) = $nodeId
         detach delete n
         """
         with neo4j_driver.get_session() as session:
@@ -159,6 +164,8 @@ def data_model_delete():
         return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
 
     except Exception as e:
+        import traceback
+        traceback.print_exc()
         res = failed({}, {"error": f"{e}"})
         return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
 
@@ -229,7 +236,7 @@ def data_model_list_graph():
         where_clause = ""
 
         if nodeid is not None:
-            where_clause = "MATCH (n)-[:label]->(la) WHERE id(la) = $nodeId"
+            where_clause = "MATCH (n)-[:label]->(la) WHERE elementId(la) = $nodeId"
             params['nodeId'] = nodeid
 
         from app.services.neo4j_driver import neo4j_driver
@@ -238,9 +245,9 @@ def data_model_list_graph():
         OPTIONAL MATCH (n)-[:child]->(child)
         {where_clause}
         WITH 
-            collect(DISTINCT {{id: toString(id(n)), text: n.name, type: split(labels(n)[0], '_')[1]}}) AS nodes,
-            collect(DISTINCT {{id: toString(id(child)), text: child.name, type: split(labels(child)[0], '_')[1]}}) AS nodes2,
-            collect(DISTINCT {{from: toString(id(n)), to: toString(id(child)), text: '下级'}}) AS lines
+            collect(DISTINCT {{id: toString(elementId(n)), text: n.name, type: split(labels(n)[0], '_')[1]}}) AS nodes,
+            collect(DISTINCT {{id: toString(elementId(child)), text: child.name, type: split(labels(child)[0], '_')[1]}}) AS nodes2,
+            collect(DISTINCT {{from: toString(elementId(n)), to: toString(elementId(child)), text: '下级'}}) AS lines
         RETURN nodes + nodes2 AS nodes, lines AS lines
         """
 

+ 183 - 142
app/core/data_model/model.py

@@ -31,14 +31,17 @@ def calculate_model_level(id):
     根据child关系计算数据模型当前的level并自动保存
     
     Args:
-        id: 数据模型的节点ID
+        id: 数据模型的节点ID(字符串)
         
     Returns:
         None
     """
+    # 确保id是字符串类型
+    node_id = str(id) if id is not None else None
+    
     cql = """
     MATCH (start_node:data_model)
-    WHERE id(start_node) = $nodeId
+    WHERE elementId(start_node) = $nodeId
     CALL {
         WITH start_node
         OPTIONAL MATCH path = (start_node)-[:child*]->(end_node)
@@ -49,18 +52,18 @@ def calculate_model_level(id):
     """
     
     with connect_graph().session() as session:
-        result = session.run(cql, nodeId=id)
+        result = session.run(cql, nodeId=node_id)
         record = result.single()
         data = record["max_level"] if record and "max_level" in record else 0
         
         # 更新level属性
         update_query = """
             MATCH (n:data_model)
-            WHERE id(n) = $nodeId
+            WHERE elementId(n) = $nodeId
             SET n.level = $level
             RETURN n
             """
-        session.run(update_query, nodeId=id, level=data)
+        session.run(update_query, nodeId=node_id, level=data)
 
 
 # 处理数据模型血缘关系
@@ -349,7 +352,7 @@ def type_cql_query():
     """
     query = """
     MATCH (n:data_model)
-    WHERE id(n) = $nodeId
+    WHERE elementId(n) = $nodeId
     // 获取元数据节点, 数据模型
     WITH n
     OPTIONAL MATCH (n)-[:connection]->(a:meta_node)
@@ -357,30 +360,42 @@ def type_cql_query():
     OPTIONAL MATCH (n)-[:clean_model]-(d:data_standard)-[:clean_model]->(a) 
     // 获取数据标签
     OPTIONAL MATCH (n)-[:label]->(la:data_label)
-    OPTIONAL MATCH (child) where id(child) = n.childernId 
-    OPTIONAL MATCH (ma) where id(ma) = a.master_data 
-    WITH n, a, d, la, n.childrenId AS childrenIds,ma
-    // 遍历 childrenIds 并获取对应的子节点
-    UNWIND childrenIds AS child_id
-    OPTIONAL MATCH (child) WHERE id(child) = child_id
-    // 收集子节点信息
-    WITH n, a, d, la, collect(DISTINCT {id: id(child), name: child.name}) AS childrenId,ma
+    // 获取子节点关系
+    OPTIONAL MATCH (n)-[:child]->(child_node:data_model)
+    // 收集元数据信息,注意ma变量未定义,需要修复
+    OPTIONAL MATCH (a)-[:master_data]->(ma:master_data)
+    WITH n, a, d, la, collect(DISTINCT {id: elementId(child_node), name: child_node.name}) AS childrenId, ma
     // 收集元数据信息并排序
-    WITH a, d, la, n, childrenId, ma
-    WITH n, collect(DISTINCT {id: id(a), name: a.name, en_name: a.en_name,
-                             data_type: a.data_type, master_data: {id: id(ma), name: ma.name},
-                             data_standard: {id: id(d), name: d.name}}) AS meta_ids,
-            properties(n) AS properties, {id: id(la), name: la.name} AS tag, childrenId
-   // 对 meta_ids 进行排序
+    WITH n, collect(DISTINCT {
+        id: elementId(a), 
+        name: COALESCE(a.name, ""), 
+        en_name: COALESCE(a.en_name, ""),
+        data_type: COALESCE(a.data_type, ""), 
+        master_data: CASE 
+            WHEN ma IS NOT NULL THEN {id: elementId(ma), name: COALESCE(ma.name, "")}
+            ELSE NULL 
+        END,
+        data_standard: CASE 
+            WHEN d IS NOT NULL THEN {id: elementId(d), name: COALESCE(d.name, "")}
+            ELSE NULL 
+        END
+    }) AS meta_ids,
+    properties(n) AS properties, 
+    CASE 
+        WHEN la IS NOT NULL THEN {id: elementId(la), name: COALESCE(la.name, "")}
+        ELSE NULL 
+    END AS tag, 
+    childrenId
+    // 对 meta_ids 进行排序
     UNWIND meta_ids AS meta_id
     WITH n, tag, properties, childrenId, meta_id
     ORDER BY meta_id.id
     WITH n, tag, properties, childrenId, collect(meta_id) AS sorted_meta_ids
     // 构建结果集
-    WITH [{data_resource: null, resource_id: null, meta_ids: sorted_meta_ids}]AS resources, 
-         id(n) as nodeid, tag, properties, n, childrenId
+    WITH [{data_resource: null, resource_id: null, meta_ids: sorted_meta_ids}] AS resources, 
+         elementId(n) as nodeid, tag, properties, n, childrenId
     UNWIND resources as resource
-    WITH nodeid, collect(resource) as results, tag, properties, n,childrenId
+    WITH nodeid, collect(resource) as results, tag, properties, n, childrenId
     // 合并结果集
     RETURN results, tag, properties, childrenId
     """
@@ -388,14 +403,13 @@ def type_cql_query():
     return query
 
 
-
 # 数据模型编辑接口
 def handle_id_model(id):
     """
     获取数据模型详情
     
     Args:
-        id: 数据模型ID (字符串或整数)
+        id: 数据模型ID (字符串)
         
     Returns:
         数据模型详情
@@ -403,69 +417,77 @@ def handle_id_model(id):
     # 获取数据模型的名称,元数据名称,对应选中的数据资源名称
     query = type_cql_query()
 
-    # 确保id参数为合适的类型
-    try:
-        # 尝试将id转换为适当的类型
-        node_id = str(id) if isinstance(id, str) else id
-    except:
-        node_id = id  # 如果转换失败,保持原样
+    # 确保id参数为字符串类型并进行日志输出
+    node_id = str(id) if id is not None else None
+    print(f"Querying data model with elementId: {node_id}")
 
     with connect_graph().session() as session:
-        result = session.run(query, nodeId=node_id)
-        data_ = result.data()
-
-        res_list = []
-        properties = {}
-
-        for record in data_:
-            if 'results' in record:
-                res_list = record['results']
-            if 'properties' in record:
-                properties = record['properties']
-            if 'tag' in record:
-                properties['tag'] = record['tag']
-            if 'childrenId' in record:
-                properties['childrenId'] = record['childrenId']
-            
-            # 处理id值,确保是字符串格式
-            if 'id' in properties and properties['id'] is not None:
-                properties['id'] = str(properties['id'])
+        try:
+            result = session.run(query, nodeId=node_id)
+            data_ = result.data()
+            print(f"Query result: {data_}")
+
+            if not data_:
+                print(f"No data found for elementId: {node_id}")
+                return {"data_model": {}}
+
+            res_list = []
+            properties = {}
+
+            for record in data_:
+                if 'results' in record:
+                    res_list = record['results']
+                if 'properties' in record:
+                    properties = record['properties']
+                if 'tag' in record and record['tag'] is not None:
+                    properties['tag'] = record['tag']
+                if 'childrenId' in record and record['childrenId'] is not None:
+                    properties['childrenId'] = record['childrenId']
                 
-            # 处理tag中的id
-            if 'tag' in properties and properties['tag'] is not None and 'id' in properties['tag']:
-                properties['tag']['id'] = str(properties['tag']['id'])
+                # 处理id值,确保是字符串格式
+                if 'id' in properties and properties['id'] is not None:
+                    properties['id'] = str(properties['id'])
+                    
+                # 处理tag中的id
+                if 'tag' in properties and properties['tag'] is not None and 'id' in properties['tag']:
+                    properties['tag']['id'] = str(properties['tag']['id'])
+                    
+                # 处理childrenId列表中的id
+                if 'childrenId' in properties and properties['childrenId']:
+                    for child in properties['childrenId']:
+                        if 'id' in child:
+                            child['id'] = str(child['id'])
                 
-            # 处理childrenId列表中的id
-            if 'childrenId' in properties and properties['childrenId']:
-                for child in properties['childrenId']:
-                    if 'id' in child:
-                        child['id'] = str(child['id'])
-            
-            properties.pop('id_list', None)
-            if 'tag' not in properties:
-                properties['tag'] = None
-            if 'describe' not in properties:
-                properties['describe'] = None
-
-        # 处理结果中的id值为字符串
-        if res_list:
-            for res in res_list:
-                if 'resource_id' in res and res['resource_id'] is not None:
-                    res['resource_id'] = str(res['resource_id'])
-                if 'meta_ids' in res:
-                    for meta in res['meta_ids']:
-                        if 'id' in meta:
-                            meta['id'] = str(meta['id'])
-                        if 'data_standard' in meta and meta['data_standard'] and 'id' in meta['data_standard']:
-                            meta['data_standard']['id'] = str(meta['data_standard']['id'])
-                        if 'master_data' in meta and meta['master_data'] and 'id' in meta['master_data']:
-                            meta['master_data']['id'] = str(meta['master_data']['id'])
-
-        res_dict = {"resource_selected": res_list}
-        merged_dict = {**res_dict, **properties}
-        response_data = {"data_model": merged_dict}
-
-        return response_data
+                properties.pop('id_list', None)
+                if 'tag' not in properties:
+                    properties['tag'] = None
+                if 'describe' not in properties:
+                    properties['describe'] = None
+
+            # 处理结果中的id值为字符串
+            if res_list:
+                for res in res_list:
+                    if 'resource_id' in res and res['resource_id'] is not None:
+                        res['resource_id'] = str(res['resource_id'])
+                    if 'meta_ids' in res:
+                        for meta in res['meta_ids']:
+                            if 'id' in meta:
+                                meta['id'] = str(meta['id'])
+                            if 'data_standard' in meta and meta['data_standard'] and 'id' in meta['data_standard']:
+                                meta['data_standard']['id'] = str(meta['data_standard']['id'])
+                            if 'master_data' in meta and meta['master_data'] and 'id' in meta['master_data']:
+                                meta['master_data']['id'] = str(meta['master_data']['id'])
+
+            res_dict = {"resource_selected": res_list}
+            merged_dict = {**res_dict, **properties}
+            response_data = {"data_model": merged_dict}
+
+            return response_data
+        except Exception as e:
+            print(f"Error in handle_id_model: {str(e)}")
+            import traceback
+            traceback.print_exc()
+            return {"data_model": {}}
 
 
 # 数据模型详情
@@ -584,8 +606,8 @@ def model_list(skip_count, page_size, en_name_filter=None, name_filter=None,
     
     if tag:
         match_clause = "MATCH (n:data_model)-[:label]->(t:data_label)"
-        where_clause.append("id(t) = $tag")
-        params['tag'] = int(tag)
+        where_clause.append("elementId(t) = $tag")
+        params['tag'] = str(tag)
     
     if name_filter:
         where_clause.append("n.name =~ $name_filter")
@@ -635,7 +657,7 @@ def model_list(skip_count, page_size, en_name_filter=None, name_filter=None,
         WITH n, t
         OPTIONAL MATCH (n)-[:component]->(m:meta_node)
         RETURN 
-            id(n) as id, 
+            elementId(n) as id, 
             n.name as name, 
             n.en_name as en_name, 
             n.category as category, 
@@ -643,7 +665,7 @@ def model_list(skip_count, page_size, en_name_filter=None, name_filter=None,
             n.time as time,
             n.level as level,
             t.name as tag_name,
-            id(t) as tag_id,
+            elementId(t) as tag_id,
             count(m) as component_count
         ORDER BY n.time DESC
         SKIP $skip
@@ -653,6 +675,13 @@ def model_list(skip_count, page_size, en_name_filter=None, name_filter=None,
         result = session.run(data_query, **params)
         data = result.data()
         
+        # 确保结果中的ID是字符串格式
+        for item in data:
+            if 'id' in item:
+                item['id'] = str(item['id'])
+            if 'tag_id' in item and item['tag_id'] is not None:
+                item['tag_id'] = str(item['tag_id'])
+        
     return data, count
 
 
@@ -745,16 +774,19 @@ def model_kinship_graph(nodeid, meta=False):
     获取数据模型血缘图谱
     
     Args:
-        nodeid: 节点ID
+        nodeid: 节点ID(字符串)
         meta: 是否返回元数据
         
     Returns:
         图谱数据
     """
+    # 确保nodeid是字符串类型
+    node_id = str(nodeid) if nodeid is not None else None
+    
     if meta:
         query = """
         MATCH p = (n:data_model)-[r:component|resource*..3]-(m) 
-        WHERE id(n) = $nodeId
+        WHERE elementId(n) = $nodeId
         WITH p, relationships(p) as rels
         RETURN p
         limit 300
@@ -762,7 +794,7 @@ def model_kinship_graph(nodeid, meta=False):
     else:
         query = """
         MATCH p = (n:data_model)-[r:resource*..3]-(m) 
-        WHERE id(n) = $nodeId and labels(m) <> ['meta_node']
+        WHERE elementId(n) = $nodeId and labels(m) <> ['meta_node']
         WITH p, relationships(p) as rels
         RETURN p
         limit 300
@@ -774,7 +806,7 @@ def model_kinship_graph(nodeid, meta=False):
         return {"nodes": [], "edges": []}
         
     with driver.session() as session:
-        result = session.run(query, nodeId=nodeid)
+        result = session.run(query, nodeId=node_id)
         
         nodes = set()
         relationships = set()
@@ -784,28 +816,29 @@ def model_kinship_graph(nodeid, meta=False):
             path = record["p"]
             
             for node in path.nodes:
-                if hasattr(node, 'id') and node.id not in nodes:
-                    node_id = str(node.id)
+                node_id_str = str(node.element_id) if hasattr(node, 'element_id') else str(node.id)
+                if node_id_str not in nodes:
                     node_type = list(node.labels)[0].split('_')[1]
                     node_data = {
-                        "id": node_id,
+                        "id": node_id_str,
                         "text": node.get("name", ""),
                         "type": node_type
                     }
                     
-                    nodes.add(node.id)
-                    nodes_by_id[node.id] = node_data
+                    nodes.add(node_id_str)
+                    nodes_by_id[node_id_str] = node_data
             
             for rel in path.relationships:
-                if hasattr(rel.start_node, 'id') and hasattr(rel.end_node, 'id'):
-                    relationship_id = f"{rel.start_node.id}-{rel.end_node.id}"
-                    if relationship_id not in relationships:
-                        relationship_data = {
-                            "from": str(rel.start_node.id),
-                            "to": str(rel.end_node.id),
-                            "text": type(rel).__name__
-                        }
-                        relationships.add(relationship_id)
+                start_id = str(rel.start_node.element_id) if hasattr(rel.start_node, 'element_id') else str(rel.start_node.id)
+                end_id = str(rel.end_node.element_id) if hasattr(rel.end_node, 'element_id') else str(rel.end_node.id)
+                relationship_id = f"{start_id}-{end_id}"
+                if relationship_id not in relationships:
+                    relationship_data = {
+                        "from": start_id,
+                        "to": end_id,
+                        "text": type(rel).__name__
+                    }
+                    relationships.add(relationship_id)
         
         # 转换为所需格式
         return {
@@ -821,16 +854,19 @@ def model_impact_graph(nodeid, meta=False):
     获取数据模型影响图谱
     
     Args:
-        nodeid: 节点ID
+        nodeid: 节点ID(字符串)
         meta: 是否返回元数据
         
     Returns:
         图谱数据
     """
+    # 确保nodeid是字符串类型
+    node_id = str(nodeid) if nodeid is not None else None
+    
     if meta:
         query = """
         MATCH p = (n:data_model)-[r:use*..3]-(m) 
-        WHERE id(n) = $nodeId
+        WHERE elementId(n) = $nodeId
         WITH p, relationships(p) as rels
         RETURN p
         limit 300
@@ -838,7 +874,7 @@ def model_impact_graph(nodeid, meta=False):
     else:
         query = """
         MATCH p = (n:data_model)-[r:use*..3]-(m) 
-        WHERE id(n) = $nodeId
+        WHERE elementId(n) = $nodeId
         WITH p, relationships(p) as rels
         RETURN p
         limit 300
@@ -850,7 +886,7 @@ def model_impact_graph(nodeid, meta=False):
         return {"nodes": [], "edges": []}
         
     with driver.session() as session:
-        result = session.run(query, nodeId=nodeid)
+        result = session.run(query, nodeId=node_id)
         
         nodes = set()
         relationships = set()
@@ -860,28 +896,29 @@ def model_impact_graph(nodeid, meta=False):
             path = record["p"]
             
             for node in path.nodes:
-                if hasattr(node, 'id') and node.id not in nodes:
-                    node_id = str(node.id)
+                node_id_str = str(node.element_id) if hasattr(node, 'element_id') else str(node.id)
+                if node_id_str not in nodes:
                     node_type = list(node.labels)[0].split('_')[1]
                     node_data = {
-                        "id": node_id,
+                        "id": node_id_str,
                         "text": node.get("name", ""),
                         "type": node_type
                     }
                     
-                    nodes.add(node.id)
-                    nodes_by_id[node.id] = node_data
+                    nodes.add(node_id_str)
+                    nodes_by_id[node_id_str] = node_data
             
             for rel in path.relationships:
-                if hasattr(rel.start_node, 'id') and hasattr(rel.end_node, 'id'):
-                    relationship_id = f"{rel.start_node.id}-{rel.end_node.id}"
-                    if relationship_id not in relationships:
-                        relationship_data = {
-                            "from": str(rel.start_node.id),
-                            "to": str(rel.end_node.id),
-                            "text": type(rel).__name__
-                        }
-                        relationships.add(relationship_id)
+                start_id = str(rel.start_node.element_id) if hasattr(rel.start_node, 'element_id') else str(rel.start_node.id)
+                end_id = str(rel.end_node.element_id) if hasattr(rel.end_node, 'element_id') else str(rel.end_node.id)
+                relationship_id = f"{start_id}-{end_id}"
+                if relationship_id not in relationships:
+                    relationship_data = {
+                        "from": start_id,
+                        "to": end_id,
+                        "text": type(rel).__name__
+                    }
+                    relationships.add(relationship_id)
         
         # 转换为所需格式
         return {
@@ -897,16 +934,19 @@ def model_all_graph(nodeid, meta=False):
     获取数据模型全部图谱
     
     Args:
-        nodeid: 节点ID
+        nodeid: 节点ID(字符串)
         meta: 是否返回元数据
         
     Returns:
         图谱数据
     """
+    # 确保nodeid是字符串类型
+    node_id = str(nodeid) if nodeid is not None else None
+    
     if meta:
         query = """
         MATCH p = (n:data_model)-[r*..3]-(m) 
-        WHERE id(n) = $nodeId
+        WHERE elementId(n) = $nodeId
         WITH p, relationships(p) as rels
         RETURN p
         limit 300
@@ -914,7 +954,7 @@ def model_all_graph(nodeid, meta=False):
     else:
         query = """
         MATCH p = (n:data_model)-[r*..3]-(m) 
-        WHERE id(n) = $nodeId and labels(m) <> ['meta_node']
+        WHERE elementId(n) = $nodeId and labels(m) <> ['meta_node']
         WITH p, relationships(p) as rels
         RETURN p
         limit 300
@@ -926,7 +966,7 @@ def model_all_graph(nodeid, meta=False):
         return {"nodes": [], "edges": []}
         
     with driver.session() as session:
-        result = session.run(query, nodeId=nodeid)
+        result = session.run(query, nodeId=node_id)
         
         nodes = set()
         relationships = set()
@@ -936,28 +976,29 @@ def model_all_graph(nodeid, meta=False):
             path = record["p"]
             
             for node in path.nodes:
-                if hasattr(node, 'id') and node.id not in nodes:
-                    node_id = str(node.id)
+                node_id_str = str(node.element_id) if hasattr(node, 'element_id') else str(node.id)
+                if node_id_str not in nodes:
                     node_type = list(node.labels)[0].split('_')[1]
                     node_data = {
-                        "id": node_id,
+                        "id": node_id_str,
                         "text": node.get("name", ""),
                         "type": node_type
                     }
                     
-                    nodes.add(node.id)
-                    nodes_by_id[node.id] = node_data
+                    nodes.add(node_id_str)
+                    nodes_by_id[node_id_str] = node_data
             
             for rel in path.relationships:
-                if hasattr(rel.start_node, 'id') and hasattr(rel.end_node, 'id'):
-                    relationship_id = f"{rel.start_node.id}-{rel.end_node.id}"
-                    if relationship_id not in relationships:
-                        relationship_data = {
-                            "from": str(rel.start_node.id),
-                            "to": str(rel.end_node.id),
-                            "text": type(rel).__name__
-                        }
-                        relationships.add(relationship_id)
+                start_id = str(rel.start_node.element_id) if hasattr(rel.start_node, 'element_id') else str(rel.start_node.id)
+                end_id = str(rel.end_node.element_id) if hasattr(rel.end_node, 'element_id') else str(rel.end_node.id)
+                relationship_id = f"{start_id}-{end_id}"
+                if relationship_id not in relationships:
+                    relationship_data = {
+                        "from": start_id,
+                        "to": end_id,
+                        "text": type(rel).__name__
+                    }
+                    relationships.add(relationship_id)
         
         # 转换为所需格式
         return {