Ver código fonte

修改数据模型的neo4j操作,以适应neo4j 5.0版本版本的变化。

maxiaolong 1 mês atrás
pai
commit
98af83a5a4

+ 2 - 1
app/api/data_model/routes.py

@@ -72,7 +72,8 @@ def data_model_save():
 
 
 # 新建数据模型请求接口(从数据资源中选取)
-@bp.route('/model/data/search', methods=['POST'])
+# @bp.route('/model/data/search', methods=['POST'])
+@bp.route('/data/search', methods=['POST'])
 def data_model_search():
     # 传入请求参数
     receiver = request.get_json()

+ 80 - 49
app/core/data_metric/metric_interface.py

@@ -227,7 +227,7 @@ def handle_data_metric(metric_name, result_list, receiver):
         if tag and not relationship_exists(data_metric_node, 'label', tag):
             connect_graph.create(Relationship(data_metric_node, 'label', tag))
 
-    return data_metric_node.identity, id_list
+    return data_metric_node.id, id_list
 
 
 def handle_meta_data_metric(data_metric_node_id, id_list):
@@ -241,41 +241,44 @@ def handle_meta_data_metric(data_metric_node_id, id_list):
     # 提取 model_id 和 metric_id
     model_ids = [item['id'] for item in id_list if item['type'] == 'model']
     metric_ids = [item['id'] for item in id_list if item['type'] == 'metric']
-    # 创建与data_model的关系
-    if model_ids:
-        cql_resource = """
-            MATCH (n:data_metric)
-            WHERE id(n) = $data_metric_node_id
-            UNWIND $model_ids AS model_id
-            MATCH (d:data_model)
-            WHERE id(d) = model_id
-            MERGE (n)-[:origin]->(d)
-        """
-        connect_graph.run(cql_resource, data_metric_node_id=data_metric_node_id, model_ids=model_ids)
-    # 创建与data_metric的关系
-    if metric_ids:
-        cql_resource = """
-            MATCH (n:data_metric)
-            WHERE id(n) = $data_metric_node_id
-            UNWIND $metric_ids AS metric_id
-            MATCH (d:data_metric)
-            WHERE id(d) = metric_id
-            MERGE (n)-[:origin]->(d)
-        """
-        connect_graph.run(cql_resource, data_metric_node_id=data_metric_node_id, metric_ids=metric_ids)
-
-    # 创建与元数据的关系
-    for record in id_list:
-        if "metaData" in record and record['metaData'] != []:
-            cql_meta = """
-                        MATCH (n:data_metric)
-                        WHERE id(n) = $data_metric_node_id
-                        UNWIND $meta_ids AS meta_id
-                        MATCH (d:meta_node)
-                        WHERE id(d) = meta_id
-                        MERGE (n)-[:connection]->(d)
-                    """
-            connect_graph.run(cql_meta, data_metric_node_id=data_metric_node_id, meta_ids=record['metaData'])
+    
+    with connect_graph().session() as session:
+        # 创建与data_model的关系
+        if model_ids:
+            cql_resource = """
+                MATCH (n:data_metric)
+                WHERE id(n) = $data_metric_node_id
+                UNWIND $model_ids AS model_id
+                MATCH (d:data_model)
+                WHERE id(d) = model_id
+                MERGE (n)-[:origin]->(d)
+            """
+            session.run(cql_resource, data_metric_node_id=data_metric_node_id, model_ids=model_ids)
+            
+        # 创建与data_metric的关系
+        if metric_ids:
+            cql_resource = """
+                MATCH (n:data_metric)
+                WHERE id(n) = $data_metric_node_id
+                UNWIND $metric_ids AS metric_id
+                MATCH (d:data_metric)
+                WHERE id(d) = metric_id
+                MERGE (n)-[:origin]->(d)
+            """
+            session.run(cql_resource, data_metric_node_id=data_metric_node_id, metric_ids=metric_ids)
+
+        # 创建与元数据的关系
+        for record in id_list:
+            if "metaData" in record and record['metaData'] != []:
+                cql_meta = """
+                            MATCH (n:data_metric)
+                            WHERE id(n) = $data_metric_node_id
+                            UNWIND $meta_ids AS meta_id
+                            MATCH (d:meta_node)
+                            WHERE id(d) = meta_id
+                            MERGE (n)-[:connection]->(d)
+                        """
+                session.run(cql_meta, data_metric_node_id=data_metric_node_id, meta_ids=record['metaData'])
 
 
 def handle_id_metric(id):
@@ -569,26 +572,54 @@ def data_metric_edit(data):
     for key, value in data.items():
         if value is not None and key != "model_selected":
             node_a[key] = value
-    connect_graph.push(node_a)
+    
+    with connect_graph().session() as session:
+        session.push(node_a)
 
-    child_list = data['childrenId']
+    child_list = data.get('childrenId', [])
     for child_id in child_list:
         child = get_node_by_id_no_label(child_id)
         # 建立关系:当前节点的childrenId指向,以及关系child
         if child and not relationship_exists(node_a, 'child', child):
-            connect_graph.create(Relationship(node_a, 'child', child))
+            connection = Relationship(node_a, 'child', child)
+            connect_graph.create(connection)
 
     # 处理数据标签及其关系
-    if data["tag"]:
+    if data.get("tag"):
         tag_node = get_node_by_id('data_label', data["tag"])
-        relationship_label = Relationship(node_a, "label", tag_node)
-        connect_graph.merge(relationship_label)
+        if tag_node:
+            relationship_label = Relationship(node_a, "label", tag_node)
+            connect_graph.merge(relationship_label)
 
     # 处理元数据节点及其关系(此处只调整关系,不修改对应属性)
-    for record in data['model_selected']:
-        for parsed_item in record["meta"]:
-            metadata_node = update_or_create_node(
-                parsed_item["id"]
-            )
-            relationship_connection = Relationship(node_a, "connection", metadata_node)
-            connect_graph.merge(relationship_connection) 
+    for record in data.get('model_selected', []):
+        for parsed_item in record.get("meta", []):
+            metadata_node = update_or_create_node(parsed_item["id"])
+            if metadata_node:
+                relationship_connection = Relationship(node_a, "connection", metadata_node)
+                connect_graph.merge(relationship_connection)
+
+
+def create_metric_node(name, description, category, id_list):
+    """
+    创建指标节点
+    
+    Args:
+        name: 指标名称
+        description: 指标描述
+        category: 指标分类
+        id_list: 相关ID列表
+        
+    Returns:
+        tuple: (节点ID, ID列表)
+    """
+    data_metric_node = create_or_get_node('data_metric', 
+                                        name=name,
+                                        description=description,
+                                        category=category,
+                                        id_list=id_list)
+                                        
+    if not hasattr(data_metric_node, 'id'):
+        raise ValueError("Failed to create valid metric node")
+        
+    return data_metric_node.id, id_list 

+ 471 - 241
app/core/data_model/model.py

@@ -37,7 +37,8 @@ def calculate_model_level(id):
         None
     """
     cql = """
-    MATCH (start_node:data_model {id: $nodeId})
+    MATCH (start_node:data_model)
+    WHERE id(start_node) = $nodeId
     CALL {
         WITH start_node
         OPTIONAL MATCH path = (start_node)-[:child*]->(end_node)
@@ -46,14 +47,20 @@ def calculate_model_level(id):
     WITH coalesce(max(level), 0) AS max_level
     RETURN max_level
     """
-    data = connect_graph.run(cql, nodeId=id).evaluate()
-    # 更新level属性
-    update_query = """
-        MATCH (n:data_model {id: $nodeId})
-        SET n.level = $level
-        RETURN n
-        """
-    connect_graph.run(update_query, nodeId=id, level=data)
+    
+    with connect_graph().session() as session:
+        result = session.run(cql, nodeId=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
+            SET n.level = $level
+            RETURN n
+            """
+        session.run(update_query, nodeId=id, level=data)
 
 
 # 处理数据模型血缘关系
@@ -86,8 +93,9 @@ def handle_model_relation(resource_ids):
             filtered_search_nodes as origin_nodes, filtered_connect_nodes as blood_nodes
             """
 
-    result = connect_graph.run(query, resource_Ids=resource_ids)
-    return result.data()
+    with connect_graph().session() as session:
+        result = session.run(query, resource_Ids=resource_ids)
+        return result.data()
 
 
 # 创建一个数据模型节点
@@ -105,7 +113,7 @@ def handle_data_model(data_model, result_list, result, receiver):
         tuple: (id, data_model_node)
     """
     # 添加数据资源 血缘关系的字段 blood_resource
-    data_model_en = result_list[0]
+    data_model_en = result_list[0] if result_list and len(result_list) > 0 else ""
     receiver['id_list'] = result
     add_attribute = {
         'time': get_formatted_time(),
@@ -114,24 +122,49 @@ def handle_data_model(data_model, result_list, result, receiver):
     receiver.update(add_attribute)
     data_model_node = get_node('data_model', name=data_model) or create_or_get_node('data_model', **receiver)
 
-    child_list = receiver['childrenId']
+    child_list = receiver.get('childrenId', [])
     for child_id in child_list:
-        child = get_node_by_id_no_label(child_id)
-        # 建立关系:当前节点的childrenId指向,以及关系child
-        res = relationship_exists(data_model_node, 'child', child)
-        if child and not res:
-            connect_graph.create(Relationship(data_model_node, 'child', child))
+        child_node = get_node_by_id_no_label(child_id)
+        if child_node and not relationship_exists(data_model_node, 'child', child_node):
+            with connect_graph().session() as session:
+                relationship = Relationship(data_model_node, 'child', child_node)
+                session.execute_write(
+                    lambda tx: tx.run(
+                        "MATCH (a), (b) WHERE id(a) = $a_id AND id(b) = $b_id CREATE (a)-[:child]->(b)",
+                        a_id=data_model_node.id, b_id=child_node.id
+                    )
+                )
 
     # 根据传入参数id,和数据标签建立关系
-    if receiver['tag']:
+    if receiver.get('tag'):
         # 使用 Cypher 查询通过 id 查找节点
         tag = get_node_by_id('data_label', receiver['tag'])
         if tag and not relationship_exists(data_model_node, 'label', tag):
-            connection = Relationship(data_model_node, 'label', tag)
-            connect_graph.create(connection)
+            with connect_graph().session() as session:
+                session.execute_write(
+                    lambda tx: tx.run(
+                        "MATCH (a), (b) WHERE id(a) = $a_id AND id(b) = $b_id CREATE (a)-[:label]->(b)",
+                        a_id=data_model_node.id, b_id=tag.id
+                    )
+                )
+
+    # 获取节点ID
+    node_id = None
+    if hasattr(data_model_node, 'id'):
+        node_id = data_model_node.id
+    else:
+        # 如果节点没有id属性,尝试通过查询获取
+        query = """
+        MATCH (n:data_model {name: $name})
+        RETURN id(n) as node_id
+        """
+        with connect_graph().session() as session:
+            result = session.run(query, name=data_model)
+            record = result.single()
+            if record and "node_id" in record:
+                node_id = record["node_id"]
 
-    id = data_model_node.identity
-    return id, data_model_node
+    return node_id, data_model_node
 
 
 # (从数据资源中选取)
@@ -226,6 +259,25 @@ def handle_no_meta_data_model(id_lists, receiver, data_model_node):
     resouce_ids = [record['resource_id'] for record in id_lists]
     meta_ids = [record['id'] for id_list in id_lists for record in id_list['metaData']]
     
+    # 获取数据模型节点ID
+    data_model_node_id = None
+    if hasattr(data_model_node, 'id'):
+        data_model_node_id = data_model_node.id
+    else:
+        # 如果节点没有id属性,尝试通过查询获取
+        query = """
+        MATCH (n:data_model {name: $name})
+        RETURN id(n) as node_id
+        """
+        with connect_graph().session() as session:
+            result = session.run(query, name=data_model_node.get('name'))
+            record = result.single()
+            if record:
+                data_model_node_id = record["node_id"]
+    
+    if not data_model_node_id:
+        return
+    
     # 创建与data_resource的关系 资源关系
     if resouce_ids:
         query = """
@@ -233,8 +285,8 @@ def handle_no_meta_data_model(id_lists, receiver, data_model_node):
         WHERE id(source)=$source_id AND id(target) IN $target_ids
         MERGE (source)-[:resource]->(target)
         """
-        with neo4j_driver.get_session() as session:
-            session.run(query, source_id=data_model_node.identity, target_ids=resouce_ids)
+        with connect_graph().session() as session:
+            session.run(query, source_id=data_model_node_id, target_ids=resouce_ids)
 
     if meta_ids:
         meta_node_list = []
@@ -244,11 +296,12 @@ def handle_no_meta_data_model(id_lists, receiver, data_model_node):
             WHERE id(n) = $node_id
             RETURN n
             """
-            result = connect_graph.run(query, node_id=id)
-            if result:
-                record = result.data()
-                if record:
-                    meta_node_list.append(record[0]['n'])
+            with connect_graph().session() as session:
+                result = session.run(query, node_id=id)
+                if result:
+                    record = result.data()
+                    if record:
+                        meta_node_list.append(record[0]['n'])
         
         # 提取接收到的数据并创建meta_node节点
         meta_node = None
@@ -277,11 +330,146 @@ def handle_no_meta_data_model(id_lists, receiver, data_model_node):
                 
                 # 创建与data_model的关系
                 if meta_node and not relationship_exists(data_model_node, 'component', meta_node):
-                    connection = Relationship(data_model_node, 'component', meta_node)
-                    connect_graph.create(connection)
+                    with connect_graph().session() as session:
+                        session.execute_write(
+                            lambda tx: tx.run(
+                                "MATCH (a), (b) WHERE id(a) = $a_id AND id(b) = $b_id CREATE (a)-[:component]->(b)",
+                                a_id=data_model_node.id, b_id=meta_node.id
+                            )
+                        )
+
+
+# 定义查询数据模型详情的Cypher查询
+def type_cql_query():
+    """
+    构建获取数据模型详情的Cypher查询
+    
+    Returns:
+        查询语句
+    """
+    query = """
+    MATCH (n:data_model)
+    WHERE id(n) = $nodeId
+    // 获取元数据节点, 数据模型
+    WITH n
+    OPTIONAL MATCH (n)-[:connection]->(a:meta_node)
+    // 获取数据标准
+    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
+    // 收集元数据信息并排序
+    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 进行排序
+    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
+    UNWIND resources as resource
+    WITH nodeid, collect(resource) as results, tag, properties, n,childrenId
+    // 合并结果集
+    RETURN results, tag, properties, childrenId
+    """
+
+    return query
+
+
+
+# 数据模型编辑接口
+def handle_id_model(id):
+    """
+    获取数据模型详情
+    
+    Args:
+        id: 数据模型ID (字符串或整数)
+        
+    Returns:
+        数据模型详情
+    """
+    # 获取数据模型的名称,元数据名称,对应选中的数据资源名称
+    query = type_cql_query()
+
+    # 确保id参数为合适的类型
+    try:
+        # 尝试将id转换为适当的类型
+        node_id = str(id) if isinstance(id, str) else id
+    except:
+        node_id = 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'])
+                
+            # 处理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'])
+            
+            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
 
 
 # 数据模型详情
+'''
 def handle_id_model(model_id):
     """
     获取数据模型详情
@@ -296,73 +484,79 @@ def handle_id_model(model_id):
     MATCH (n:data_model) WHERE id(n) = $model_id
     RETURN n
     """
-    model_detail_result = connect_graph.run(model_detail_query, model_id=model_id).data()
-    
-    if not model_detail_result:
-        return None
-    
-    model_detail = model_detail_result[0]['n']
-    model_info = dict(model_detail)
-    model_info['id'] = model_id
-    
-    # 获取data_model节点连接的resource节点
-    resource_query = """
-    MATCH (n:data_model)-[:resource]->(r:data_resource) WHERE id(n) = $model_id
-    RETURN r
-    """
-    resource_result = connect_graph.run(resource_query, model_id=model_id).data()
-    resources = []
-    
-    for item in resource_result:
-        resource = dict(item['r'])
-        resource['id'] = item['r'].identity
-        resources.append(resource)
-    
-    model_info['resources'] = resources
-    
-    # 获取data_model节点连接的component节点
-    component_query = """
-    MATCH (n:data_model)-[:component]->(m:meta_node) WHERE id(n) = $model_id
-    RETURN m
-    """
-    component_result = connect_graph.run(component_query, model_id=model_id).data()
-    components = []
-    
-    for item in component_result:
-        component = dict(item['m'])
-        component['id'] = item['m'].identity
-        components.append(component)
-    
-    model_info['components'] = components
-    
-    # 获取data_model节点连接的use节点
-    use_query = """
-    MATCH (n:data_model)-[:use]->(u:data_model) WHERE id(n) = $model_id
-    RETURN u
-    """
-    use_result = connect_graph.run(use_query, model_id=model_id).data()
-    uses = []
-    
-    for item in use_result:
-        use = dict(item['u'])
-        use['id'] = item['u'].identity
-        uses.append(use)
-    
-    model_info['uses'] = uses
-    
-    # 获取data_model节点连接的标签
-    tag_query = """
-    MATCH (n:data_model)-[:label]->(t:data_label) WHERE id(n) = $model_id
-    RETURN t
-    """
-    tag_result = connect_graph.run(tag_query, model_id=model_id).data()
-    
-    if tag_result:
-        tag = dict(tag_result[0]['t'])
-        tag['id'] = tag_result[0]['t'].identity
-        model_info['tag'] = tag
     
-    return model_info
+    with connect_graph().session() as session:
+        model_detail_result = session.run(model_detail_query, model_id=model_id).data()
+        
+        if not model_detail_result:
+            return None
+        
+        model_detail = model_detail_result[0]['n']
+        model_info = dict(model_detail)
+        model_info['id'] = model_id
+        
+        # 获取data_model节点连接的resource节点
+        resource_query = """
+        MATCH (n:data_model)-[:resource]->(r:data_resource) WHERE id(n) = $model_id
+        RETURN r
+        """
+        resource_result = session.run(resource_query, model_id=model_id).data()
+        resources = []
+        
+        for item in resource_result:
+            if 'r' in item and hasattr(item['r'], 'id'):
+                resource = dict(item['r'])
+                resource['id'] = item['r'].id
+                resources.append(resource)
+        
+        model_info['resources'] = resources
+        
+        # 获取data_model节点连接的component节点
+        component_query = """
+        MATCH (n:data_model)-[:component]->(m:meta_node) WHERE id(n) = $model_id
+        RETURN m
+        """
+        component_result = session.run(component_query, model_id=model_id).data()
+        components = []
+        
+        for item in component_result:
+            if 'm' in item and hasattr(item['m'], 'id'):
+                component = dict(item['m'])
+                component['id'] = item['m'].id
+                components.append(component)
+        
+        model_info['components'] = components
+        
+        # 获取data_model节点连接的use节点
+        use_query = """
+        MATCH (n:data_model)-[:use]->(u:data_model) WHERE id(n) = $model_id
+        RETURN u
+        """
+        use_result = session.run(use_query, model_id=model_id).data()
+        uses = []
+        
+        for item in use_result:
+            if 'u' in item and hasattr(item['u'], 'id'):
+                use = dict(item['u'])
+                use['id'] = item['u'].id
+                uses.append(use)
+        
+        model_info['uses'] = uses
+        
+        # 获取data_model节点连接的标签
+        tag_query = """
+        MATCH (n:data_model)-[:label]->(t:data_label) WHERE id(n) = $model_id
+        RETURN t
+        """
+        tag_result = session.run(tag_query, model_id=model_id).data()
+        
+        if tag_result and 't' in tag_result[0] and hasattr(tag_result[0]['t'], 'id'):
+            tag = dict(tag_result[0]['t'])
+            tag['id'] = tag_result[0]['t'].id
+            model_info['tag'] = tag
+        
+        return model_info
+'''
 
 
 # 数据模型列表
@@ -508,33 +702,41 @@ def model_resource_list(skip_count, page_size, name_filter=None, id=None,
     RETURN count(DISTINCT n) as count
     """
     
-    count = connect_graph.run(count_query, **params).evaluate()
-    
-    # 获取分页数据
-    params['skip'] = skip_count
-    params['limit'] = page_size
-    
-    data_query = f"""
-    MATCH (search:data_resource) WHERE id(search) = $id
-    MATCH (search)-[:connection]->(mn:meta_node)<-[:connection]-(n:data_resource)
-    {where_str}
-    WITH DISTINCT n, mn
-    RETURN 
-        id(n) as id, 
-        n.name as name, 
-        n.en_name as en_name, 
-        n.category as category, 
-        n.description as description, 
-        n.time as time,
-        collect({{id: id(mn), name: mn.name}}) as common_meta
-    ORDER BY n.time DESC
-    SKIP $skip
-    LIMIT $limit
-    """
-    
-    result = connect_graph.run(data_query, **params).data()
-    
-    return result, count
+    # 使用正确的session方式执行查询
+    driver = connect_graph()
+    if not driver:
+        return [], 0
+        
+    with driver.session() as session:
+        count_result = session.run(count_query, **params)
+        count = count_result.single()["count"]
+        
+        # 获取分页数据
+        params['skip'] = skip_count
+        params['limit'] = page_size
+        
+        data_query = f"""
+        MATCH (search:data_resource) WHERE id(search) = $id
+        MATCH (search)-[:connection]->(mn:meta_node)<-[:connection]-(n:data_resource)
+        {where_str}
+        WITH DISTINCT n, mn
+        RETURN 
+            id(n) as id, 
+            n.name as name, 
+            n.en_name as en_name, 
+            n.category as category, 
+            n.description as description, 
+            n.time as time,
+            collect({{id: id(mn), name: mn.name}}) as common_meta
+        ORDER BY n.time DESC
+        SKIP $skip
+        LIMIT $limit
+        """
+        
+        result = session.run(data_query, **params)
+        data = result.data()
+        
+    return data, count
 
 
 # 数据模型血缘图谱
@@ -566,44 +768,51 @@ def model_kinship_graph(nodeid, meta=False):
         limit 300
         """
     
-    result = connect_graph.run(query, nodeId=nodeid)
-    
-    nodes = set()
-    relationships = set()
-    nodes_by_id = {}
-    
-    for record in result:
-        path = record["p"]
+    # 使用正确的session方式执行查询
+    driver = connect_graph()
+    if not driver:
+        return {"nodes": [], "edges": []}
         
-        for node in path.nodes:
-            if node.identity not in nodes:
-                node_id = str(node.identity)
-                node_type = list(node.labels)[0].split('_')[1]
-                node_data = {
-                    "id": node_id,
-                    "text": node.get("name", ""),
-                    "type": node_type
-                }
-                
-                nodes.add(node.identity)
-                nodes_by_id[node.identity] = node_data
-        
-        for rel in path.relationships:
-            relationship_id = f"{rel.start_node.identity}-{rel.end_node.identity}"
-            if relationship_id not in relationships:
-                relationship_data = {
-                    "from": str(rel.start_node.identity),
-                    "to": str(rel.end_node.identity),
-                    "text": type(rel).__name__
-                }
-                relationships.add(relationship_id)
-    
-    # 转换为所需格式
-    return {
-        "nodes": list(nodes_by_id.values()),
-        "edges": [{"from": rel.split("-")[0], "to": rel.split("-")[1], "text": ""} 
-                for rel in relationships]
-    }
+    with driver.session() as session:
+        result = session.run(query, nodeId=nodeid)
+        
+        nodes = set()
+        relationships = set()
+        nodes_by_id = {}
+        
+        for record in result:
+            path = record["p"]
+            
+            for node in path.nodes:
+                if hasattr(node, 'id') and node.id not in nodes:
+                    node_id = str(node.id)
+                    node_type = list(node.labels)[0].split('_')[1]
+                    node_data = {
+                        "id": node_id,
+                        "text": node.get("name", ""),
+                        "type": node_type
+                    }
+                    
+                    nodes.add(node.id)
+                    nodes_by_id[node.id] = 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)
+        
+        # 转换为所需格式
+        return {
+            "nodes": list(nodes_by_id.values()),
+            "edges": [{"from": rel.split("-")[0], "to": rel.split("-")[1], "text": ""} 
+                    for rel in relationships]
+        }
 
 
 # 数据模型影响图谱
@@ -635,44 +844,51 @@ def model_impact_graph(nodeid, meta=False):
         limit 300
         """
     
-    result = connect_graph.run(query, nodeId=nodeid)
-    
-    nodes = set()
-    relationships = set()
-    nodes_by_id = {}
-    
-    for record in result:
-        path = record["p"]
+    # 使用正确的session方式执行查询
+    driver = connect_graph()
+    if not driver:
+        return {"nodes": [], "edges": []}
         
-        for node in path.nodes:
-            if node.identity not in nodes:
-                node_id = str(node.identity)
-                node_type = list(node.labels)[0].split('_')[1]
-                node_data = {
-                    "id": node_id,
-                    "text": node.get("name", ""),
-                    "type": node_type
-                }
-                
-                nodes.add(node.identity)
-                nodes_by_id[node.identity] = node_data
-        
-        for rel in path.relationships:
-            relationship_id = f"{rel.start_node.identity}-{rel.end_node.identity}"
-            if relationship_id not in relationships:
-                relationship_data = {
-                    "from": str(rel.start_node.identity),
-                    "to": str(rel.end_node.identity),
-                    "text": type(rel).__name__
-                }
-                relationships.add(relationship_id)
-    
-    # 转换为所需格式
-    return {
-        "nodes": list(nodes_by_id.values()),
-        "edges": [{"from": rel.split("-")[0], "to": rel.split("-")[1], "text": ""} 
-                for rel in relationships]
-    }
+    with driver.session() as session:
+        result = session.run(query, nodeId=nodeid)
+        
+        nodes = set()
+        relationships = set()
+        nodes_by_id = {}
+        
+        for record in result:
+            path = record["p"]
+            
+            for node in path.nodes:
+                if hasattr(node, 'id') and node.id not in nodes:
+                    node_id = str(node.id)
+                    node_type = list(node.labels)[0].split('_')[1]
+                    node_data = {
+                        "id": node_id,
+                        "text": node.get("name", ""),
+                        "type": node_type
+                    }
+                    
+                    nodes.add(node.id)
+                    nodes_by_id[node.id] = 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)
+        
+        # 转换为所需格式
+        return {
+            "nodes": list(nodes_by_id.values()),
+            "edges": [{"from": rel.split("-")[0], "to": rel.split("-")[1], "text": ""} 
+                    for rel in relationships]
+        }
 
 
 # 数据模型全部图谱
@@ -704,44 +920,51 @@ def model_all_graph(nodeid, meta=False):
         limit 300
         """
     
-    result = connect_graph.run(query, nodeId=nodeid)
-    
-    nodes = set()
-    relationships = set()
-    nodes_by_id = {}
-    
-    for record in result:
-        path = record["p"]
+    # 使用正确的session方式执行查询
+    driver = connect_graph()
+    if not driver:
+        return {"nodes": [], "edges": []}
         
-        for node in path.nodes:
-            if node.identity not in nodes:
-                node_id = str(node.identity)
-                node_type = list(node.labels)[0].split('_')[1]
-                node_data = {
-                    "id": node_id,
-                    "text": node.get("name", ""),
-                    "type": node_type
-                }
-                
-                nodes.add(node.identity)
-                nodes_by_id[node.identity] = node_data
-        
-        for rel in path.relationships:
-            relationship_id = f"{rel.start_node.identity}-{rel.end_node.identity}"
-            if relationship_id not in relationships:
-                relationship_data = {
-                    "from": str(rel.start_node.identity),
-                    "to": str(rel.end_node.identity),
-                    "text": type(rel).__name__
-                }
-                relationships.add(relationship_id)
-    
-    # 转换为所需格式
-    return {
-        "nodes": list(nodes_by_id.values()),
-        "edges": [{"from": rel.split("-")[0], "to": rel.split("-")[1], "text": ""} 
-                for rel in relationships]
-    }
+    with driver.session() as session:
+        result = session.run(query, nodeId=nodeid)
+        
+        nodes = set()
+        relationships = set()
+        nodes_by_id = {}
+        
+        for record in result:
+            path = record["p"]
+            
+            for node in path.nodes:
+                if hasattr(node, 'id') and node.id not in nodes:
+                    node_id = str(node.id)
+                    node_type = list(node.labels)[0].split('_')[1]
+                    node_data = {
+                        "id": node_id,
+                        "text": node.get("name", ""),
+                        "type": node_type
+                    }
+                    
+                    nodes.add(node.id)
+                    nodes_by_id[node.id] = 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)
+        
+        # 转换为所需格式
+        return {
+            "nodes": list(nodes_by_id.values()),
+            "edges": [{"from": rel.split("-")[0], "to": rel.split("-")[1], "text": ""} 
+                    for rel in relationships]
+        }
 
 
 # 更新数据模型
@@ -769,8 +992,9 @@ def data_model_edit(receiver):
     RETURN n
     """
     
-    result = connect_graph.run(query, id=id, name=name, en_name=en_name, 
-                             category=category, description=description).data()
+    with connect_graph().session() as session:
+        result = session.run(query, id=id, name=name, en_name=en_name, 
+                           category=category, description=description).data()
     
     # 处理标签关系
     if tag:
@@ -779,14 +1003,20 @@ def data_model_edit(receiver):
         MATCH (n:data_model)-[r:label]->() WHERE id(n) = $id
         DELETE r
         """
-        connect_graph.run(delete_query, id=id)
+        with connect_graph().session() as session:
+            session.run(delete_query, id=id)
         
         # 再创建新的标签关系
         tag_node = get_node_by_id('data_label', tag)
         if tag_node:
             model_node = get_node_by_id_no_label(id)
             if model_node and not relationship_exists(model_node, 'label', tag_node):
-                connection = Relationship(model_node, 'label', tag_node)
-                connect_graph.create(connection)
+                with connect_graph().session() as session:
+                    session.execute_write(
+                        lambda tx: tx.run(
+                            "MATCH (a), (b) WHERE id(a) = $a_id AND id(b) = $b_id CREATE (a)-[:label]->(b)",
+                            a_id=model_node.id, b_id=tag_node.id
+                        )
+                    )
     
     return {"message": "数据模型更新成功"} 

+ 27 - 37
app/core/graph/graph_operations.py

@@ -108,49 +108,39 @@ def create_or_get_node(label, **properties):
         logger.error(f"Error in create_or_get_node: {str(e)}")
         raise e
 
-def create_relationship(start_node_id, end_node_id, rel_type, **properties):
+def create_relationship(start_node, end_node, relationship_type, properties=None):
     """
-    在两个节点之间创建关系
+    创建两个节点之间的关系
     
     Args:
-        start_node_id: 起始节点ID
-        end_node_id: 结束节点ID
-        rel_type: 关系类型
-        **properties: 关系属性
+        start_node: 起始节点
+        end_node: 结束节点
+        relationship_type: 关系类型
+        properties: 关系属性
         
     Returns:
-        关系的ID
+        创建的关系对象
     """
-    try:
-        # 构建属性部分
-        properties_str = ', '.join([f"{k}: ${k}" for k in properties.keys()])
-        properties_part = f" {{{properties_str}}}" if properties else ""
+    if not hasattr(start_node, 'id') or not hasattr(end_node, 'id'):
+        raise ValueError("Invalid node objects provided")
         
-        # 构建Cypher语句
-        cypher = f"""
-        MATCH (a), (b)
-        WHERE id(a) = $start_node_id AND id(b) = $end_node_id
-        CREATE (a)-[r:{rel_type}{properties_part}]->(b)
-        RETURN id(r) as rel_id
-        """
+    if properties is None:
+        properties = {}
         
-        # 执行创建
-        with connect_graph().session() as session:
-            params = {
-                'start_node_id': int(start_node_id),
-                'end_node_id': int(end_node_id),
-                **properties
-            }
-            result = session.run(cypher, **params).single()
-            
-            if result:
-                return result["rel_id"]
-            else:
-                logger.error("Failed to create relationship")
-                return None
-    except Exception as e:
-        logger.error(f"Error creating relationship: {str(e)}")
-        raise e
+    query = """
+    MATCH (start), (end)
+    WHERE id(start) = $start_id AND id(end) = $end_id
+    MERGE (start)-[r:%s]->(end)
+    SET r += $properties
+    RETURN r
+    """ % relationship_type
+    
+    with connect_graph().session() as session:
+        result = session.run(query,
+                         start_id=start_node.id,
+                         end_id=end_node.id,
+                         properties=properties)
+        return result.single()["r"]
 
 def get_subgraph(node_ids, rel_types=None, max_depth=1):
     """
@@ -355,8 +345,8 @@ def relationship_exists(start_node, rel_type, end_node, **properties):
             
             # 执行查询
             params = {
-                'start_id': start_node.identity,
-                'end_id': end_node.identity,
+                'start_id': start_node.id,
+                'end_id': end_node.id,
                 **properties
             }
             result = session.run(query, **params).single()