Parcourir la source

已完成ddl解析,节点保存,准备开发表抽取作业.

wangxq il y a 1 mois
Parent
commit
8cfad275bb

+ 66 - 17
app/api/data_resource/routes.py

@@ -72,10 +72,24 @@ def data_resource_translate():
     # 处理meta_data可能为None的情况
     if meta_data:
         try:
+            # 修复JSON解析问题,处理可能包含特殊引号的情况
+            # 替换可能存在的特殊引号字符
+            meta_data = meta_data.replace('â', '"').replace('"', '"').replace('"', '"')
             meta_data_list = json.loads(meta_data)
-        except json.JSONDecodeError:
-            logger.error(f"解析meta_data失败: {meta_data}")
-            meta_data_list = []
+        except json.JSONDecodeError as e:
+            logger.error(f"解析meta_data失败: {meta_data}, 错误: {str(e)}")
+            # 尝试进行基本的字符串解析,以处理简单的数组格式
+            if meta_data.startswith('[') and meta_data.endswith(']'):
+                try:
+                    # 使用ast.literal_eval作为备用解析方法
+                    import ast
+                    meta_data_list = ast.literal_eval(meta_data)
+                except Exception:
+                    # 如果仍然失败,使用简单的字符串分割
+                    meta_data = meta_data.strip('[]')
+                    meta_data_list = [item.strip('"\'') for item in meta_data.split(',')]
+            else:
+                meta_data_list = []
     else:
         logger.warning("meta_data为空,将使用空列表")
         meta_data_list = []
@@ -312,20 +326,30 @@ def data_resource_list():
 
 @bp.route('/search', methods=['POST'])
 def id_data_search():
-    """搜索数据资源关联元数据"""
+    """数据资源关联元数据搜索"""
     try:
-        # 获取参数
-        resource_id = request.json.get('id')
-        if not resource_id:
-            return jsonify(failed("资源ID不能为空"))
-            
+        # 获取分页和筛选参数
         page = int(request.json.get('current', 1))
         page_size = int(request.json.get('size', 10))
+        resource_id = request.json.get('id')
+        
         en_name_filter = request.json.get('en_name')
         name_filter = request.json.get('name')
         category_filter = request.json.get('category')
         tag_filter = request.json.get('tag')
         
+        if resource_id is None:
+            return jsonify(failed("资源ID不能为空"))
+            
+        # 确保传入的ID为整数
+        try:
+            resource_id = int(resource_id)
+        except (ValueError, TypeError):
+            return jsonify(failed(f"资源ID必须为整数, 收到的是: {resource_id}"))
+            
+        # 记录请求信息
+        logger.info(f"获取资源关联元数据请求,ID: {resource_id}")
+            
         # 调用业务逻辑查询关联元数据
         metadata_list, total_count = id_data_search_list(
             resource_id, 
@@ -345,7 +369,7 @@ def id_data_search():
             "current": page
         }))
     except Exception as e:
-        logger.error(f"搜索数据资源关联元数据失败: {str(e)}")
+        logger.error(f"数据资源关联元数据搜索失败: {str(e)}")
         return jsonify(failed(str(e)))
 
 def dynamic_type_conversion(value, target_type):
@@ -372,10 +396,16 @@ def data_resource_graph_all():
         resource_id = request.json.get('id')
         meta = request.json.get('meta', True)
         
-        if not resource_id:
+        if resource_id is None:
             return jsonify(failed("资源ID不能为空"))
             
-        # 调用业务逻辑获取图谱
+        # 确保传入的ID为整数
+        try:
+            resource_id = int(resource_id)
+        except (ValueError, TypeError):
+            return jsonify(failed(f"资源ID必须为整数, 收到的是: {resource_id}"))
+            
+        # 调用业务逻辑获取完整图谱
         graph_data = resource_impact_all_graph(resource_id, meta)
         
         return jsonify(success(graph_data))
@@ -391,9 +421,18 @@ def data_resource_list_graph():
         resource_id = request.json.get('id')
         meta = request.json.get('meta', True)
         
-        if not resource_id:
+        if resource_id is None:
             return jsonify(failed("资源ID不能为空"))
             
+        # 确保传入的ID为整数
+        try:
+            resource_id = int(resource_id)
+        except (ValueError, TypeError):
+            return jsonify(failed(f"资源ID必须为整数, 收到的是: {resource_id}"))
+            
+        # 记录请求信息
+        logger.info(f"获取图谱请求,ID: {resource_id}")
+            
         # 调用业务逻辑获取图谱
         graph_data = resource_kinship_graph(resource_id, meta)
         
@@ -430,7 +469,7 @@ def id_data_save():
             for meta in metadata_list:
                 # 创建元数据节点
                 meta_cypher = """
-                MERGE (m:Metadata {name: $name})
+                MERGE (m:meta_data {name: $name})
                 ON CREATE SET m.en_name = $en_name, 
                             m.createTime = $create_time,
                             m.type = $type
@@ -455,7 +494,7 @@ def id_data_save():
                 
                 # 使用明确的属性名匹配而不是ID
                 rel_cypher = """
-                MATCH (a:data_resource {name: $r_name}), (m:Metadata {name: $m_name})
+                MATCH (a:data_resource {name: $r_name}), (m:meta_data {name: $m_name})
                 MERGE (a)-[r:contain]->(m)
                 RETURN r
                 """
@@ -474,7 +513,7 @@ def id_data_save():
 
                 # 额外验证关系是否创建
                 verify_cypher = """
-                MATCH (a:data_resource {name: $r_name})-[r:contain]->(m:Metadata {name: $m_name})
+                MATCH (a:data_resource {name: $r_name})-[r:contain]->(m:meta_data {name: $m_name})
                 RETURN count(r) as rel_count
                 """
                 
@@ -643,13 +682,23 @@ def data_resource_detail():
         # 获取资源ID
         resource_id = request.json.get('id')
         
-        if not resource_id:
+        if resource_id is None:
             return jsonify(failed("资源ID不能为空"))
+        
+        # 确保传入的ID为整数
+        try:
+            resource_id = int(resource_id)
+        except (ValueError, TypeError):
+            return jsonify(failed(f"资源ID必须为整数, 收到的是: {resource_id}"))
             
+        # 记录请求信息
+        logger.info(f"获取资源详情请求,ID: {resource_id}")
+        
         # 调用业务逻辑查询数据资源详情
         resource_data = handle_id_resource(resource_id)
         
         if not resource_data:
+            logger.error(f"资源不存在,ID: {resource_id}")
             return jsonify(failed("资源不存在"))
             
         return jsonify(success(resource_data))

+ 4 - 4
app/api/meta_data/routes.py

@@ -172,7 +172,7 @@ def meta_node_add():
         # 创建节点
         with neo4j_driver.get_session() as session:
             cypher = """
-            CREATE (n:Metadata {name: $name, type: $type, desc: $desc, 
+            CREATE (n:meta_data {name: $name, type: $type, desc: $desc, 
                                properties: $properties, createTime: $create_time, 
                                updateTime: $update_time})
             RETURN n
@@ -203,7 +203,7 @@ def search_metadata_route():
             return jsonify(success([]))
             
         cypher = """
-        MATCH (n:Metadata) 
+        MATCH (n:meta_data) 
         WHERE n.name CONTAINS $keyword
         RETURN n LIMIT 100
         """
@@ -229,7 +229,7 @@ def full_text_query():
         # 执行Neo4j全文索引查询
         with neo4j_driver.get_session() as session:
             cypher = """
-            CALL db.index.fulltext.queryNodes("metadataFulltext", $query)
+            CALL db.index.fulltext.queryNodes("meta_dataFulltext", $query)
             YIELD node, score
             RETURN node, score
             ORDER BY score DESC
@@ -486,7 +486,7 @@ def text_resource_node():
         with neo4j_driver.get_session() as session:
             # 创建资源节点
             cypher = """
-            CREATE (n:TextResource {
+            CREATE (n:meta_data {
                 name: $name,
                 en_name: $en_name,
                 keywords: $keywords,

+ 2 - 1
app/config/config.py

@@ -44,7 +44,8 @@ class BaseConfig:
     # LLM基础配置
     LLM_BASE_URL = "https://dashscope.aliyuncs.com/compatible-mode/v1"
     LLM_MODEL_NAME = "qwen-turbo"
-    LLM_API_KEY = os.environ.get('LLM_API_KEY', "sk-86d4622141d74e9a8d7c38ee873c4d91")
+    # LLM_API_KEY = os.environ.get('LLM_API_KEY', "sk-86d4622141d74e9a8d7c38ee873c4d91")
+    LLM_API_KEY = os.environ.get('LLM_API_KEY', "sk-db68e37f00974031935395315bfe07f0")
     
     # 日志基础配置
     LOG_FORMAT = '%(asctime)s - %(levelname)s - %(filename)s - %(funcName)s - %(lineno)s - %(message)s'

+ 101 - 50
app/core/data_interface/interface.py

@@ -57,7 +57,7 @@ def standard_list(skip_count, page_size, en_name_filter=None,
     cql = f"""
     MATCH (n:data_standard)
     WHERE {where_str}
-    RETURN properties(n) as properties,n.time as time,elementId(n) as nodeid,
+    RETURN properties(n) as properties,n.time as time,id(n) as nodeid,
            COUNT((()-[]->(n))) + COUNT(((n)-[]->()))  as relationship_count
     ORDER BY time desc
     SKIP $skip_count
@@ -108,17 +108,17 @@ def standard_kinship_graph(nodeid):
     # 查询语句
     cql = """
     MATCH(da:data_standard)
-    WHERE elementId(da)=$nodeId
+    WHERE id(da)=$nodeId
     OPTIONAL MATCH(a:data_resource)-[:clean_resource]-(da)
     OPTIONAL MATCH(b:data_model)-[:clean_model]-(da)
     WITH 
-        collect({id:toString(elementId(a)),text:a.name,type:split(labels(a)[0],'_')[1]})+
-        collect({id:toString(elementId(b)),text:b.name,type:split(labels(b)[0],'_')[1]})+
-        collect({id:toString(elementId(da)),text:da.name,type:split(labels(da)[0],'_')[1]}) as nodes,da,
-        collect({from:toString(elementId(a)),to:toString(elementId(da)),text:'标准'})+
-        collect({from:toString(elementId(b)),to:toString(elementId(da)),text:'标准'})as lines
+        collect({id:toString(id(a)),text:a.name,type:split(labels(a)[0],'_')[1]})+
+        collect({id:toString(id(b)),text:b.name,type:split(labels(b)[0],'_')[1]})+
+        collect({id:toString(id(da)),text:da.name,type:split(labels(da)[0],'_')[1]}) as nodes,da,
+        collect({from:toString(id(a)),to:toString(id(da)),text:'标准'})+
+        collect({from:toString(id(b)),to:toString(id(da)),text:'标准'})as lines
     WITH  
-        toString(elementId(da)) as rootId,
+        toString(id(da)) as rootId,
         apoc.coll.toSet(lines) as lines,
         apoc.coll.toSet(nodes) as nodes
     RETURN nodes,lines,rootId
@@ -155,17 +155,17 @@ def standard_impact_graph(nodeid):
     # 查询语句
     cql = """
         MATCH(da:data_standard)
-        WHERE elementId(da)=$nodeId
+        WHERE id(da)=$nodeId
         OPTIONAL MATCH(da)-[:clean_model]-(m1:meta_node)
         OPTIONAL MATCH(da)-[:clean_model]-(m2:meta_node)
         WITH 
-            collect({id:toString(elementId(da)),text:da.name,type:split(labels(da)[0],'_')[1]})+
-            collect({id:toString(elementId(m1)),text:m1.name})+
-            collect({id:toString(elementId(m2)),text:m2.name})as nodes,da,
-            collect({from:toString(elementId(da)),to:toString(elementId(m1)),text:'标准清洗'})+
-            collect({from:toString(elementId(da)),to:toString(elementId(m2)),text:'标准清洗'})as lines
+            collect({id:toString(id(da)),text:da.name,type:split(labels(da)[0],'_')[1]})+
+            collect({id:toString(id(m1)),text:m1.name})+
+            collect({id:toString(id(m2)),text:m2.name})as nodes,da,
+            collect({from:toString(id(da)),to:toString(id(m1)),text:'标准清洗'})+
+            collect({from:toString(id(da)),to:toString(id(m2)),text:'标准清洗'})as lines
         WITH  
-            toString(elementId(da)) as rootId,
+            toString(id(da)) as rootId,
             apoc.coll.toSet(lines) as lines,
             apoc.coll.toSet(nodes) as nodes
         RETURN nodes,lines,rootId
@@ -202,23 +202,23 @@ def standard_all_graph(nodeid):
     # 查询语句
     cql = """
     MATCH(da:data_standard)
-    WHERE elementId(da)=$nodeId
+    WHERE id(da)=$nodeId
     OPTIONAL MATCH(a:data_resource)-[:clean_resource]-(da)
     OPTIONAL MATCH(b:data_model)-[:clean_model]-(da)
     OPTIONAL MATCH(da)-[:clean_model]-(m1:meta_node)
     OPTIONAL MATCH(da)-[:clean_model]-(m2:meta_node)
     WITH 
-        collect({id:toString(elementId(a)),text:a.name,type:split(labels(a)[0],'_')[1]})+
-        collect({id:toString(elementId(b)),text:b.name,type:split(labels(b)[0],'_')[1]})+
-        collect({id:toString(elementId(da)),text:da.name,type:split(labels(da)[0],'_')[1]})+
-        collect({id:toString(elementId(m1)),text:m1.name})+
-        collect({id:toString(elementId(m2)),text:m2.name})as nodes,da,
-        collect({from:toString(elementId(a)),to:toString(elementId(da)),text:'标准'})+
-        collect({from:toString(elementId(b)),to:toString(elementId(da)),text:'标准'})+
-        collect({from:toString(elementId(da)),to:toString(elementId(m1)),text:'标准清洗'})+
-        collect({from:toString(elementId(da)),to:toString(elementId(m2)),text:'标准清洗'})as lines
+        collect({id:toString(id(a)),text:a.name,type:split(labels(a)[0],'_')[1]})+
+        collect({id:toString(id(b)),text:b.name,type:split(labels(b)[0],'_')[1]})+
+        collect({id:toString(id(da)),text:da.name,type:split(labels(da)[0],'_')[1]})+
+        collect({id:toString(id(m1)),text:m1.name})+
+        collect({id:toString(id(m2)),text:m2.name})as nodes,da,
+        collect({from:toString(id(a)),to:toString(id(da)),text:'标准'})+
+        collect({from:toString(id(b)),to:toString(id(da)),text:'标准'})+
+        collect({from:toString(id(da)),to:toString(id(m1)),text:'标准清洗'})+
+        collect({from:toString(id(da)),to:toString(id(m2)),text:'标准清洗'})as lines
     WITH  
-        toString(elementId(da)) as rootId,
+        toString(id(da)) as rootId,
         apoc.coll.toSet(lines) as lines,
         apoc.coll.toSet(nodes) as nodes
     RETURN nodes,lines,rootId
@@ -283,7 +283,7 @@ def label_list(skip_count, page_size, en_name_filter=None,
     cql = f"""
     MATCH (n:data_label)
     WHERE {where_str}
-    WITH n, properties(n) as properties, n.time as time, elementId(n) as nodeid
+    WITH n, properties(n) as properties, n.time as time, id(n) as nodeid
     OPTIONAL MATCH (n)<-[r]-()
     WITH n, properties, time, nodeid, count(r) as incoming
     OPTIONAL MATCH (n)-[r]->()
@@ -337,15 +337,15 @@ def id_label_graph(id):
     """
     query = """
     MATCH (n:data_label)
-    WHERE elementId(n) = $nodeId
+    WHERE id(n) = $nodeId
     OPTIONAL MATCH (a)-[:label]-(n)
     WITH 
-       collect({from: toString(elementId(a)), to: toString(elementId(n)), text: "标签"}) AS line1,
-       collect({id: toString(elementId(n)), text: n.name, type:"label"}) AS node1,
-       collect({id: toString(elementId(a)), text: a.name, type: split(labels(a)[0], '_')[1]}) AS node2, n
+       collect({from: toString(id(a)), to: toString(id(n)), text: "标签"}) AS line1,
+       collect({id: toString(id(n)), text: n.name, type:"label"}) AS node1,
+       collect({id: toString(id(a)), text: a.name, type: split(labels(a)[0], '_')[1]}) AS node2, n
     WITH apoc.coll.toSet(line1) AS lines,
                  apoc.coll.toSet(node1 + node2) AS nodes,
-                 toString(elementId(n)) AS res
+                 toString(id(n)) AS res
     RETURN lines, nodes, res
     """
     # 修复:使用正确的session方式执行查询
@@ -379,26 +379,26 @@ def label_kinship_graph(nodeid):
     # 查询语句
     cql = """
     MATCH(la:data_label)
-    WHERE elementId(la)=$nodeId
+    WHERE id(la)=$nodeId
     OPTIONAL MATCH(a:data_resource)-[:label]-(la)
     OPTIONAL MATCH(b:data_model)-[:label]-(la)
     OPTIONAL MATCH(meta:meta_node)-[:label]-(la)
     OPTIONAL MATCH(d:data_standard)-[:label]-(la)
     OPTIONAL MATCH(e:data_metric)-[:label]-(la)
     WITH 
-        collect({id:toString(elementId(a)),text:a.name,type:split(labels(a)[0],'_')[1]})+
-        collect({id:toString(elementId(b)),text:b.name,type:split(labels(b)[0],'_')[1]})+
-        collect({id:toString(elementId(d)),text:d.name,type:split(labels(d)[0],'_')[1]})+
-        collect({id:toString(elementId(e)),text:e.name,type:split(labels(e)[0],'_')[1]})+
-        collect({id:toString(elementId(la)),text:la.name,type:split(labels(la)[0],'_')[1]})+
-        collect({id:toString(elementId(meta)),text:meta.name}) as nodes,la,
-        collect({from:toString(elementId(a)),to:toString(elementId(la)),text:'标签'})+
-        collect({from:toString(elementId(b)),to:toString(elementId(la)),text:'标签'})+
-        collect({from:toString(elementId(meta)),to:toString(elementId(la)),text:'标签'})+
-        collect({from:toString(elementId(d)),to:toString(elementId(la)),text:'标签'})+
-        collect({from:toString(elementId(e)),to:toString(elementId(la)),text:'标签'})as lines
+        collect({id:toString(id(a)),text:a.name,type:split(labels(a)[0],'_')[1]})+
+        collect({id:toString(id(b)),text:b.name,type:split(labels(b)[0],'_')[1]})+
+        collect({id:toString(id(d)),text:d.name,type:split(labels(d)[0],'_')[1]})+
+        collect({id:toString(id(e)),text:e.name,type:split(labels(e)[0],'_')[1]})+
+        collect({id:toString(id(la)),text:la.name,type:split(labels(la)[0],'_')[1]})+
+        collect({id:toString(id(meta)),text:meta.name}) as nodes,la,
+        collect({from:toString(id(a)),to:toString(id(la)),text:'标签'})+
+        collect({from:toString(id(b)),to:toString(id(la)),text:'标签'})+
+        collect({from:toString(id(meta)),to:toString(id(la)),text:'标签'})+
+        collect({from:toString(id(d)),to:toString(id(la)),text:'标签'})+
+        collect({from:toString(id(e)),to:toString(id(la)),text:'标签'})as lines
     WITH  
-        toString(elementId(la)) as rootId,
+        toString(id(la)) as rootId,
         apoc.coll.toSet(lines) as lines,
         apoc.coll.toSet(nodes) as nodes
     RETURN nodes,lines,rootId
@@ -434,9 +434,9 @@ def label_impact_graph(nodeid):
     # 查询语句
     cql = """
         MATCH(n:data_label)
-        WHERE elementId(n)=$nodeId
-        RETURN {id:toString(elementId(n)),text:(n.name),type:"label"} AS nodes,
-               toString(elementId(n)) as rootId
+        WHERE id(n)=$nodeId
+        RETURN {id:toString(id(n)),text:(n.name),type:"label"} AS nodes,
+               toString(id(n)) as rootId
         """
     # 修复:使用正确的session方式执行查询
     driver = connect_graph()
@@ -471,7 +471,7 @@ def dynamic_label_list(name_filter=None):
     MATCH (n:data_label)
     WITH n, apoc.text.levenshteinSimilarity(n.group, "{name_filter}") AS similarity
     WHERE similarity > 0.1 // 设置相似度阈值
-    RETURN DISTINCT n.group as name, elementId(n) as nodeid
+    RETURN DISTINCT n.group as name, id(n) as nodeid
     """
 
     # 修复:使用正确的session方式执行查询
@@ -488,4 +488,55 @@ def dynamic_label_list(name_filter=None):
                 "id": record['nodeid']
             })
         
-        return data 
+        return data
+
+def search_info(key, value):
+    """
+    搜索指定属性的节点信息
+    
+    Args:
+        key: 搜索属性键
+        value: 搜索属性值
+        
+    Returns:
+        搜索结果列表
+    """
+    query = """
+    MATCH (n)
+    WHERE n.{} =~ '(?i).*{}.*'
+    WITH n, properties(n) as properties, n.time as time, id(n) as nodeid
+    RETURN properties, nodeid, time, labels(n) as labels
+    LIMIT 30
+    """.format(key, value)
+    
+    result = connect_graph.run(query)
+    
+    results = []
+    for record in result:
+        results.append({
+            "properties": record["properties"],
+            "id": record["nodeid"],
+            "time": record["time"],
+            "labels": record["labels"]
+        })
+    
+    return results
+
+def label_info(id):
+    """
+    获取标签节点的信息
+    
+    Args:
+        id: 节点ID
+        
+    Returns:
+        标签节点信息
+    """
+    query = """
+    MATCH (n)
+    WHERE id(n) = $nodeId
+    RETURN {id:toString(id(n)),text:(n.name),type:"label"} AS nodes,
+            toString(id(n)) as rootId
+    """
+    res = connect_graph.run(query, nodeId=id).data()
+    return res[0] if res else {} 

+ 126 - 70
app/core/data_resource/resource.py

@@ -17,8 +17,15 @@ def get_node_by_id(label, id):
     """根据ID获取指定标签的节点"""
     try:
         with neo4j_driver.get_session() as session:
-            cypher = f"MATCH (n:{label}) WHERE elementId(n) = $id RETURN n"
-            result = session.run(cypher, id=int(id))
+            # 确保id为整数
+            try:
+                id_int = int(id)
+            except (ValueError, TypeError):
+                logger.error(f"节点ID不是有效的整数: {id}")
+                return None
+                
+            cypher = f"MATCH (n:{label}) WHERE id(n) = $id RETURN n"
+            result = session.run(cypher, id=id_int)
             record = result.single()
             return record["n"] if record else None
     except Exception as e:
@@ -29,8 +36,15 @@ def get_node_by_id_no_label(id):
     """根据ID获取节点,不限制标签"""
     try:
         with neo4j_driver.get_session() as session:
-            cypher = "MATCH (n) WHERE elementId(n) = $id RETURN n"
-            result = session.run(cypher, id=int(id))
+            # 确保id为整数
+            try:
+                id_int = int(id)
+            except (ValueError, TypeError):
+                logger.error(f"节点ID不是有效的整数: {id}")
+                return None
+                
+            cypher = "MATCH (n) WHERE id(n) = $id RETURN n"
+            result = session.run(cypher, id=id_int)
             record = result.single()
             return record["n"] if record else None
     except Exception as e:
@@ -42,15 +56,15 @@ def delete_relationships(start_node, rel_type=None, end_node=None):
     try:
         with neo4j_driver.get_session() as session:
             if rel_type and end_node:
-                cypher = "MATCH (a)-[r:`{rel_type}`]->(b) WHERE elementId(a) = $start_id AND elementId(b) = $end_id DELETE r"
+                cypher = "MATCH (a)-[r:`{rel_type}`]->(b) WHERE id(a) = $start_id AND id(b) = $end_id DELETE r"
                 cypher = cypher.replace("{rel_type}", rel_type)
                 session.run(cypher, start_id=start_node.id, end_id=end_node.id)
             elif rel_type:
-                cypher = "MATCH (a)-[r:`{rel_type}`]->() WHERE elementId(a) = $start_id DELETE r"
+                cypher = "MATCH (a)-[r:`{rel_type}`]->() WHERE id(a) = $start_id DELETE r"
                 cypher = cypher.replace("{rel_type}", rel_type)
                 session.run(cypher, start_id=start_node.id)
             else:
-                cypher = "MATCH (a)-[r]->() WHERE elementId(a) = $start_id DELETE r"
+                cypher = "MATCH (a)-[r]->() WHERE id(a) = $start_id DELETE r"
                 session.run(cypher, start_id=start_node.id)
         return True
     except Exception as e:
@@ -65,7 +79,7 @@ def update_or_create_node(label, **properties):
             if node_id:
                 # 更新现有节点
                 set_clause = ", ".join([f"n.{k} = ${k}" for k in properties.keys()])
-                cypher = f"MATCH (n:{label}) WHERE elementId(n) = $id SET {set_clause} RETURN n"
+                cypher = f"MATCH (n:{label}) WHERE id(n) = $id SET {set_clause} RETURN n"
                 result = session.run(cypher, id=int(node_id), **properties)
             else:
                 # 创建新节点
@@ -109,7 +123,7 @@ def handle_node(receiver, head_data, data_resource, data_source=None):
             """
             result = session.run(cypher, **receiver)
             data_resource_node = result.single()["n"]
-            resource_id = data_resource_node.element_id # 使用element_id属性获取完整ID
+            resource_id = data_resource_node.id  # 使用id属性获取数值ID
 
             # 处理标签关系
             if tag_list:
@@ -118,16 +132,16 @@ def handle_node(receiver, head_data, data_resource, data_source=None):
                     # 检查关系是否存在
                     rel_check = """
                     MATCH (a:data_resource)-[r:label]->(b:data_label) 
-                    WHERE elementId(a) = $resource_id AND elementId(b) = $tag_id
+                    WHERE id(a) = $resource_id AND id(b) = $tag_id
                     RETURN r
                     """
-                    rel_result = session.run(rel_check, resource_id=resource_id, tag_id=tag_node.element_id)  # 使用element_id
+                    rel_result = session.run(rel_check, resource_id=resource_id, tag_id=tag_node.id)  # 使用数值id
                     
                     # 如果关系不存在则创建
                     if not rel_result.single():
                         rel_create = """
                         MATCH (a:data_resource), (b:data_label)
-                        WHERE elementId(a) = $resource_id AND elementId(b) = $tag_id
+                        WHERE id(a) = $resource_id AND id(b) = $tag_id
                         CREATE (a)-[r:label]->(b)
                         RETURN r
                         """
@@ -139,7 +153,7 @@ def handle_node(receiver, head_data, data_resource, data_source=None):
                 for item in head_data:
                     # 创建元数据节点
                     meta_cypher = """
-                    MERGE (m:Metadata {name: $name})
+                    MERGE (m:meta_data {name: $name})
                     ON CREATE SET m.en_name = $en_name, 
                                 m.createTime = $create_time,
                                 m.type = $type
@@ -159,7 +173,7 @@ def handle_node(receiver, head_data, data_resource, data_source=None):
                     
                     if meta_record and meta_record["m"]:
                         meta_node = meta_record["m"]
-                        meta_id = meta_node.element_id
+                        meta_id = meta_node.id  # 使用数值ID
                         
                         # 打印日志确认节点创建成功和ID
                         logger.info(f"创建或获取到元数据节点: ID={meta_id}, name={item['name']}")
@@ -167,7 +181,7 @@ def handle_node(receiver, head_data, data_resource, data_source=None):
                         # 确认数据资源节点是否可以正确查询到
                         check_resource_cypher = """
                         MATCH (n:data_resource) 
-                        WHERE elementId(n) = $resource_id 
+                        WHERE id(n) = $resource_id 
                         RETURN n
                         """
                         check_resource = session.run(check_resource_cypher, resource_id=resource_id)
@@ -179,8 +193,8 @@ def handle_node(receiver, head_data, data_resource, data_source=None):
                         
                         # 创建关系
                         rel_cypher = """
-                        MATCH (a:data_resource), (m:Metadata)
-                        WHERE elementId(a) = $resource_id AND elementId(m) = $meta_id
+                        MATCH (a:data_resource), (m:meta_data)
+                        WHERE id(a) = $resource_id AND id(m) = $meta_id
                         MERGE (a)-[r:contain]->(m)
                         RETURN r
                         """
@@ -210,7 +224,7 @@ def handle_node(receiver, head_data, data_resource, data_source=None):
                         # 创建 isbelongto 关系
                         rel_data_source_cypher = """
                         MATCH (a:data_resource), (b:data_source)
-                        WHERE elementId(a) = $resource_id AND b.en_name = $ds_en_name
+                        WHERE id(a) = $resource_id AND b.en_name = $ds_en_name
                         MERGE (a)-[r:isbelongto]->(b)
                         RETURN r
                         """
@@ -235,28 +249,37 @@ def handle_id_resource(resource_id):
     """处理单个数据资源查询"""
     try:
         with neo4j_driver.get_session() as session:
-            # 查询数据资源节点
+            # 确保resource_id为整数
+            try:
+                resource_id_int = int(resource_id)
+            except (ValueError, TypeError):
+                logger.error(f"资源ID不是有效的整数: {resource_id}")
+                return None
+            
+            # 使用数值ID查询
             cypher = """
             MATCH (n:data_resource)
-            WHERE elementId(n) = $resource_id
+            WHERE id(n) = $resource_id
             RETURN n
             """
-            result = session.run(cypher, resource_id=int(resource_id))
+            result = session.run(cypher, resource_id=resource_id_int)
             record = result.single()
             
             if not record:
+                logger.error(f"未找到资源,ID: {resource_id_int}")
                 return None
                 
+            # 构建返回数据
             data_resource = dict(record["n"])
             data_resource["id"] = record["n"].id
             
             # 查询关联的标签
             tag_cypher = """
             MATCH (n:data_resource)-[:label]->(t:data_label)
-            WHERE elementId(n) = $resource_id
+            WHERE id(n) = $resource_id
             RETURN t
             """
-            tag_result = session.run(tag_cypher, resource_id=int(resource_id))
+            tag_result = session.run(tag_cypher, resource_id=resource_id_int)
             tag_record = tag_result.single()
             
             if tag_record:
@@ -264,13 +287,14 @@ def handle_id_resource(resource_id):
                 tag["id"] = tag_record["t"].id
                 data_resource["tag_info"] = tag
             
-            # 查询关联的元数据
+            # 查询关联的元数据 - 支持meta_data和Metadata两种标签
             meta_cypher = """
-            MATCH (n:data_resource)-[:contain]->(m:Metadata)
-            WHERE elementId(n) = $resource_id
+            MATCH (n:data_resource)-[:contain]->(m)
+            WHERE id(n) = $resource_id
+            AND (m:meta_data OR m:Metadata)
             RETURN m
             """
-            meta_result = session.run(meta_cypher, resource_id=int(resource_id))
+            meta_result = session.run(meta_cypher, resource_id=resource_id_int)
             
             meta_list = []
             for meta_record in meta_result:
@@ -280,6 +304,7 @@ def handle_id_resource(resource_id):
             
             data_resource["meta_list"] = meta_list
             
+            logger.info(f"成功获取资源详情,ID: {resource_id_int}")
             return data_resource
     except Exception as e:
         logger.error(f"处理单个数据资源查询失败: {str(e)}")
@@ -292,7 +317,7 @@ def id_resource_graph(resource_id):
             # 查询数据资源节点及其关系
             cypher = """
             MATCH (n:data_resource)-[r]-(m)
-            WHERE elementId(n) = $resource_id
+            WHERE id(n) = $resource_id
             RETURN n, r, m
             """
             result = session.run(cypher, resource_id=int(resource_id))
@@ -382,7 +407,7 @@ def resource_list(page, page_size, en_name_filter=None, name_filter=None,
                 # 查询关联的标签
                 tag_cypher = """
                 MATCH (n:data_resource)-[:label]->(t:data_label)
-                WHERE elementId(n) = $resource_id
+                WHERE id(n) = $resource_id
                 RETURN t
                 """
                 tag_result = session.run(tag_cypher, resource_id=node["id"])
@@ -405,11 +430,20 @@ def id_data_search_list(resource_id, page, page_size, en_name_filter=None,
     """获取特定数据资源关联的元数据列表"""
     try:
         with neo4j_driver.get_session() as session:
-            # 基本匹配语句
+            # 确保resource_id为整数
+            try:
+                resource_id_int = int(resource_id)
+            except (ValueError, TypeError):
+                logger.error(f"资源ID不是有效的整数: {resource_id}")
+                return [], 0
+            
+            # 基本匹配语句 - 支持meta_data和Metadata标签
             match_clause = """
-            MATCH (n:data_resource)-[:contain]->(m:Metadata)
-            WHERE elementId(n) = $resource_id
+            MATCH (n:data_resource)-[:contain]->(m)
+            WHERE id(n) = $resource_id
+            AND (m:meta_data OR m:Metadata)
             """
+            
             where_conditions = []
             
             if en_name_filter:
@@ -434,7 +468,7 @@ def id_data_search_list(resource_id, page, page_size, en_name_filter=None,
             {tag_match}
             RETURN count(m) as count
             """
-            count_params = {"resource_id": int(resource_id)}
+            count_params = {"resource_id": resource_id_int}
             if tag_filter:
                 count_params["tag_filter"] = tag_filter
                 
@@ -456,10 +490,11 @@ def id_data_search_list(resource_id, page, page_size, en_name_filter=None,
             # 格式化结果
             metadata_list = []
             for record in result:
-                node = dict(record["m"])
-                node["id"] = record["m"].id
-                metadata_list.append(node)
-                
+                meta = dict(record["m"])
+                meta["id"] = record["m"].id
+                metadata_list.append(meta)
+            
+            logger.info(f"成功获取资源关联元数据,ID: {resource_id_int}, 元数据数量: {total_count}")
             return metadata_list, total_count
     except Exception as e:
         logger.error(f"获取数据资源关联的元数据列表失败: {str(e)}")
@@ -469,24 +504,32 @@ def resource_kinship_graph(resource_id, include_meta=True):
     """获取数据资源亲缘关系图谱"""
     try:
         with neo4j_driver.get_session() as session:
+            # 确保resource_id为整数
+            try:
+                resource_id_int = int(resource_id)
+            except (ValueError, TypeError):
+                logger.error(f"资源ID不是有效的整数: {resource_id}")
+                return {"nodes": [], "relationships": []}
+            
             # 基本查询
             cypher_parts = [
-                "MATCH (n:data_resource) WHERE elementId(n) = $resource_id",
+                f"MATCH (n:data_resource) WHERE id(n) = $resource_id",
                 "OPTIONAL MATCH (n)-[:label]->(l:data_label)",
             ]
             
-            # 是否包含元数据
+            # 是否包含元数据 - 支持meta_data和Metadata两种标签
             if include_meta:
-                cypher_parts.append("OPTIONAL MATCH (n)-[:contain]->(m:Metadata)")
+                cypher_parts.append("OPTIONAL MATCH (n)-[:contain]->(m) WHERE (m:meta_data OR m:Metadata)")
                 
             cypher_parts.append("RETURN n, l, collect(m) as metadata")
             
             cypher = "\n".join(cypher_parts)
             
-            result = session.run(cypher, resource_id=int(resource_id))
+            result = session.run(cypher, resource_id=resource_id_int)
             record = result.single()
             
             if not record:
+                logger.error(f"未找到资源图谱数据,ID: {resource_id_int}")
                 return {"nodes": [], "relationships": []}
                 
             # 收集节点和关系
@@ -531,6 +574,7 @@ def resource_kinship_graph(resource_id, include_meta=True):
                             "type": "contain"
                         })
             
+            logger.info(f"成功获取资源图谱,ID: {resource_id_int}, 节点数: {len(nodes)}")
             return {
                 "nodes": list(nodes.values()),
                 "relationships": relationships
@@ -543,22 +587,29 @@ def resource_impact_all_graph(resource_id, include_meta=True):
     """获取数据资源影响关系图谱"""
     try:
         with neo4j_driver.get_session() as session:
+            # 确保resource_id为整数
+            try:
+                resource_id_int = int(resource_id)
+            except (ValueError, TypeError):
+                logger.error(f"资源ID不是有效的整数: {resource_id}")
+                return {"nodes": [], "relationships": []}
+            
             # 根据meta参数决定查询深度
             if include_meta:
                 cypher = """
                 MATCH path = (n:data_resource)-[*1..3]-(m)
-                WHERE elementId(n) = $resource_id
+                WHERE id(n) = $resource_id
                 RETURN path
                 """
             else:
                 cypher = """
                 MATCH path = (n:data_resource)-[*1..2]-(m)
-                WHERE elementId(n) = $resource_id
-                AND NOT (m:Metadata)
+                WHERE id(n) = $resource_id
+                AND NOT (m:meta_data) AND NOT (m:Metadata)
                 RETURN path
                 """
                 
-            result = session.run(cypher, resource_id=int(resource_id))
+            result = session.run(cypher, resource_id=resource_id_int)
             
             # 收集节点和关系
             nodes = {}
@@ -586,6 +637,7 @@ def resource_impact_all_graph(resource_id, include_meta=True):
                         }
                         relationships[rel.id] = rel_dict
             
+            logger.info(f"成功获取完整图谱,ID: {resource_id_int}, 节点数: {len(nodes)}")
             return {
                 "nodes": list(nodes.values()),
                 "relationships": list(relationships.values())
@@ -1072,7 +1124,7 @@ def data_resource_edit(data):
             set_clause = ", ".join([f"n.{k} = ${k}" for k in update_fields.keys()])
             cypher = f"""
             MATCH (n:data_resource)
-            WHERE elementId(n) = $resource_id
+            WHERE id(n) = $resource_id
             SET {set_clause}
             RETURN n
             """
@@ -1089,7 +1141,7 @@ def data_resource_edit(data):
                 # 删除旧的标签关系
                 delete_rel_cypher = """
                 MATCH (n:data_resource)-[r:label]->()
-                WHERE elementId(n) = $resource_id
+                WHERE id(n) = $resource_id
                 DELETE r
                 """
                 session.run(delete_rel_cypher, resource_id=int(resource_id))
@@ -1097,7 +1149,7 @@ def data_resource_edit(data):
                 # 创建新的标签关系
                 create_rel_cypher = """
                 MATCH (n:data_resource), (t:data_label)
-                WHERE elementId(n) = $resource_id AND elementId(t) = $tag_id
+                WHERE id(n) = $resource_id AND id(t) = $tag_id
                 CREATE (n)-[r:label]->(t)
                 RETURN r
                 """
@@ -1115,14 +1167,19 @@ def handle_data_source(data_source):
     
     参数:
         data_source: 包含数据源信息的字典,支持两种情况:
-            1. 只包含名称的情况,如:
+            1. 简单情况(只需查询已有数据源),只要包含en_name即可:
                {
                    "en_name": "10-52-31-104_5432_inventory"
                }
-            2. 完整的数据源信息,如:
+               或
+               {
+                   "en_name": "10-52-31-104_5432_inventory",
+                   "name": "教师数据库"
+               }
+            2. 完整的数据源信息(用于创建新数据源):
                {
                    "en_name": "10-52-31-104_5432_inventory",
-                   "name": "",
+                   "name": "教师数据库",
                    "type": "postgresql",
                    "host": "10.52.31.104",
                    "port": 5432,
@@ -1140,12 +1197,15 @@ def handle_data_source(data_source):
         if not ds_en_name:
             raise ValueError("数据源信息不完整,缺少名称")
         
-        # 检查是否只有名称参数
-        only_en_name = len(data_source) == 1 and "en_name" in data_source
+        # 检查是否为简单查询模式
+        # 判断数据源是否包含创建新数据源所需的必要字段
+        required_fields = ["type", "host", "port", "database", "username"]
+        has_required_fields = all(data_source.get(field) for field in required_fields)
         
         with neo4j_driver.get_session() as session:
-            if only_en_name:
-                # 仅有英文名称的情况:查询是否存在该名称的数据源
+            if not has_required_fields:
+                # 简单查询模式:只通过en_name查找已有数据源
+                logger.info(f"简单数据源查询模式,查找en_name为: {ds_en_name}")
                 check_name_cypher = """
                 MATCH (ds:data_source {en_name: $en_name})
                 RETURN ds
@@ -1160,18 +1220,14 @@ def handle_data_source(data_source):
                     return existing_data_source.get("en_name")
                 else:
                     # 数据源不存在,抛出异常
-                    raise ValueError(f"未找到名称为 {ds_en_name} 的数据源")
+                    raise ValueError(f"未找到名称为 {ds_en_name} 的数据源,请先创建该数据源或提供完整的数据源信息")
             else:
-                # 完整的数据源信息:提取其它属性
-                ds_type = data_source.get("type")
-                ds_host = data_source.get("host")
-                ds_port = data_source.get("port")
-                ds_database = data_source.get("database")
-                ds_username = data_source.get("username")
+                # 完整的数据源信息模式:创建或获取数据源
                 
-                # 检查必要的属性是否存在
-                if not all([ds_type, ds_host, ds_port, ds_database, ds_username]):
-                    raise ValueError("数据源信息不完整,缺少必要的属性")
+                # 确保name不为空,如果为空则使用en_name
+                if "name" not in data_source or not data_source["name"]:
+                    data_source["name"] = ds_en_name
+                    logger.info(f"数据源name为空,使用en_name作为替代: {ds_en_name}")
                 
                 # 检查是否已存在相同数据源(除名称和密码外属性相同)
                 check_cypher = """
@@ -1186,11 +1242,11 @@ def handle_data_source(data_source):
                 
                 check_result = session.run(
                     check_cypher,
-                    type=ds_type,
-                    host=ds_host,
-                    port=ds_port,
-                    database=ds_database,
-                    username=ds_username
+                    type=data_source["type"],
+                    host=data_source["host"],
+                    port=data_source["port"],
+                    database=data_source["database"],
+                    username=data_source["username"]
                 )
                 
                 existing_record = check_result.single()

+ 1 - 1
app/core/meta_data/meta_data.py

@@ -117,7 +117,7 @@ def meta_list(page, page_size, search="", en_name_filter=None,
     try:
         with neo4j_driver.get_session() as session:
             # 构建查询条件
-            match_clause = "MATCH (n:Metadata)"
+            match_clause = "MATCH (n:meta_data)"
             where_conditions = []
             
             if search:

+ 1 - 1
app/core/production_line/production_line.py

@@ -218,7 +218,7 @@ def get_resource_storage_info(resource_id):
                 
             # 查询元数据节点
             metadata_query = """
-            MATCH (n:data_resource)-[:contain]->(m:Metadata)
+            MATCH (n:data_resource)-[:contain]->(m:meta_data)
             WHERE id(n) = $resource_id
             RETURN m.name as name, m.en_name as en_name, m.type as type
             """

+ 2 - 1
requirements.txt

@@ -15,4 +15,5 @@ PyYAML>=6.0
 python-dateutil>=2.8.0
 psutil>=6.0.0
 flask_sqlalchemy>=3.1.1
-openpyxl>=3.1.5
+openpyxl>=3.1.5
+requests>=2.32.3