Просмотр исходного кода

数据资源的增删改查功能已经前后端联调跑通。

maxiaolong 1 месяц назад
Родитель
Сommit
ec5052e407

+ 23 - 4
app/api/data_model/routes.py

@@ -109,11 +109,30 @@ def data_model_model_add():
     try:
         from app.core.meta_data import translate_and_parse
         result_list = translate_and_parse(data_model)
-        id, data_model_node = model_functions.handle_data_model(data_model, result_list, result, receiver)
-        model_functions.model_handle_meta_data_model(id_list, id)
-        model_functions.calculate_model_level(id)
+        node_id, data_model_node = model_functions.handle_data_model(data_model, result_list, result, receiver)
+        model_functions.model_handle_meta_data_model(id_list, node_id)
+        model_functions.calculate_model_level(node_id)
+
+        # 构建响应数据
+        response_data = {
+            "id": node_id,
+            "name": data_model_node.get('name'),
+            "en_name": data_model_node.get('en_name'),
+            "description": data_model_node.get('description'),
+            "category": data_model_node.get('category'),
+            "time": data_model_node.get('time'),
+            "level": data_model_node.get('level'),
+            "tag": data_model_node.get('tag'),
+            "childrenId": data_model_node.get('childrenId', []),
+            "leader": data_model_node.get('leader'),
+            "origin": data_model_node.get('origin'),
+            "frequency": data_model_node.get('frequency'),
+            "organization": data_model_node.get('organization'),
+            "data_sensitivity": data_model_node.get('data_sensitivity'),
+            "status": data_model_node.get('status')
+        }
 
-        res = success({}, "success")
+        res = success(response_data, "success")
         return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
 
     except Exception as e:

+ 28 - 1
app/api/data_resource/routes.py

@@ -725,8 +725,35 @@ def data_resource_detail():
         if not resource_data:
             logger.error(f"资源不存在,ID: {resource_id}")
             return jsonify(failed("资源不存在"))
+        
+        # 记录从handle_id_resource返回的数据
+        logger.info(f"handle_id_resource返回数据,describe字段: {resource_data.get('describe')}")
+            
+        # 确保返回的数据格式符合要求
+        response_data = {
+            "parsed_data": resource_data.get("parsed_data", []),
+            "tag": resource_data.get("tag", {"name": None, "id": None}),
+            "leader": resource_data.get("leader", ""),
+            "organization": resource_data.get("organization", ""),
+            "name": resource_data.get("name", ""),
+            "en_name": resource_data.get("en_name", ""),
+            "data_sensitivity": resource_data.get("data_sensitivity", ""),
+            "location": resource_data.get("location", "/"),
+            "time": resource_data.get("time", ""),
+            "type": resource_data.get("type", ""),
+            "category": resource_data.get("category", ""),
+            "url": resource_data.get("url", ""),
+            "frequency": resource_data.get("frequency", ""),
+            "status": resource_data.get("status", True),
+            "id": resource_data.get("id"),
+            "keywords": resource_data.get("keywords", []),
+            "describe": resource_data.get("describe", "")
+        }
+        
+        # 记录最终返回的数据
+        logger.info(f"最终返回的response_data,describe字段: {response_data.get('describe')}")
             
-        return jsonify(success(resource_data))
+        return jsonify(success(response_data))
     except Exception as e:
         logger.error(f"获取数据资源详情失败: {str(e)}")
         return jsonify(failed(str(e)))

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

@@ -39,14 +39,14 @@ def get_minio_client():
 def get_minio_config():
     """获取 MinIO 配置"""
     return {
-        'bucket_name': current_app.config['BUCKET_NAME'],
-        'prefix': current_app.config['PREFIX'],
-        'allowed_extensions': current_app.config['ALLOWED_EXTENSIONS']
+        'MINIO_BUCKET': current_app.config['MINIO_BUCKET'],
+        'PREFIX': current_app.config['PREFIX'],
+        'ALLOWED_EXTENSIONS': current_app.config['ALLOWED_EXTENSIONS']
     }
 
 def allowed_file(filename):
     """检查文件扩展名是否允许"""
-    return '.' in filename and filename.rsplit('.', 1)[1].lower() in get_minio_config()['allowed_extensions']
+    return '.' in filename and filename.rsplit('.', 1)[1].lower() in get_minio_config()['ALLOWED_EXTENSIONS']
 
 # 元数据列表
 @bp.route('/node/list', methods=['POST'])
@@ -354,7 +354,7 @@ def unstructure_text_query():
         # 获取 MinIO 配置
         minio_client = get_minio_client()
         config = get_minio_config()
-        bucket_name = config['bucket_name']
+        bucket_name = config['MINIO_BUCKET']
             
         # 从MinIO获取文件内容
         file_content = get_file_content(minio_client, bucket_name, object_name)
@@ -409,11 +409,11 @@ def upload_file():
         timestamp = time.strftime("%Y%m%d%H%M%S", time.localtime())
         
         # 生成唯一文件名
-        object_name = f"{config['prefix']}/{filename_without_ext}_{timestamp}.{file_type}"
+        object_name = f"{config['PREFIX']}/{filename_without_ext}_{timestamp}.{file_type}"
         
         # 上传文件
         minio_client.put_object(
-            config['bucket_name'], 
+            config['MINIO_BUCKET'], 
             object_name,
             io.BytesIO(file_content),
             file_size,
@@ -445,7 +445,7 @@ def upload_file_display():
         config = get_minio_config()
             
         # 获取文件内容
-        response = minio_client.get_object(config['bucket_name'], object_name)
+        response = minio_client.get_object(config['MINIO_BUCKET'], object_name)
         file_data = response.read()
         
         # 获取文件名
@@ -508,7 +508,7 @@ def download_file():
         
         # 获取文件
         try:
-            response = minio_client.get_object(config['bucket_name'], object_name)
+            response = minio_client.get_object(config['MINIO_BUCKET'], object_name)
             file_data = response.read()
         except S3Error as e:
             logger.error(f"MinIO获取文件失败: {str(e)}")
@@ -649,7 +649,7 @@ def processing_unstructured_data():
         # 获取 MinIO 配置
         minio_client = get_minio_client()
         config = get_minio_config()
-        prefix = config['prefix']
+        prefix = config['PREFIX']
             
         # 调用处理逻辑
         result = solve_unstructured_data(node_id, minio_client, prefix)
@@ -691,9 +691,9 @@ def get_meta_config():
     """获取元数据配置信息"""
     config = get_minio_config()
     return jsonify({
-        'bucket_name': config['bucket_name'],
-        'prefix': config['prefix'],
-        'allowed_extensions': list(config['allowed_extensions'])
+        'bucket_name': config['MINIO_BUCKET'],
+        'prefix': config['PREFIX'],
+        'allowed_extensions': list(config['ALLOWED_EXTENSIONS'])
     })
 
 # 更新元数据

+ 43 - 23
app/core/data_model/model.py

@@ -17,6 +17,9 @@ from py2neo import Relationship
 import logging
 import json
 
+# Configure logger
+logger = logging.getLogger(__name__)
+
 from app.core.graph.graph_operations import relationship_exists
 from app.core.graph.graph_operations import connect_graph,create_or_get_node,get_node
 from app.services.neo4j_driver import neo4j_driver
@@ -187,30 +190,47 @@ def resource_handle_meta_data_model(id_lists, data_model_node_id):
     Returns:
         None
     """
-    # 构建meta_id和resouce_id的列表
-    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']]
-    metaData = [record['data_standard'] for id_list in id_lists for record in id_list['metaData']]
-    
-    # 创建与meta_node的关系 组成关系
-    if meta_ids:
-        query = """
-        MATCH (source:data_model), (target:meta_node)
-        WHERE id(source)=$source_id AND id(target) IN $target_ids
-        MERGE (source)-[:component]->(target)
-        """
-        with neo4j_driver.get_session() as session:
-            session.run(query, source_id=data_model_node_id, target_ids=meta_ids)
+    try:
+        logger.info(f"开始处理数据模型与元数据的关系,数据模型ID: {data_model_node_id}")
+        
+        # 构建meta_id和resouce_id的列表
+        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']]
+        
+        logger.info(f"资源ID列表: {resouce_ids}")
+        logger.info(f"元数据ID列表: {meta_ids}")
+        
+        # 创建与meta_node的关系 组成关系
+        if meta_ids:
+            logger.info("开始创建数据模型与元数据的关系")
+            query = """
+            MATCH (source:data_model), (target:meta_node)
+            WHERE id(source)=$source_id AND id(target) IN $target_ids
+            MERGE (source)-[:INCLUDE]->(target)
+            RETURN count(*) as count
+            """
+            with connect_graph().session() as session:
+                result = session.run(query, source_id=data_model_node_id, target_ids=meta_ids)
+                count = result.single()["count"]
+                logger.info(f"成功创建 {count} 个数据模型与元数据的关系")
 
-    # 创建与data_resource的关系 资源关系
-    if resouce_ids:
-        query = """
-        MATCH (source:data_model), (target:data_resource)
-        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_id, target_ids=resouce_ids)
+        # 创建与data_resource的关系 资源关系
+        if resouce_ids:
+            logger.info("开始创建数据模型与数据资源的关系")
+            query = """
+            MATCH (source:data_model), (target:data_resource)
+            WHERE id(source)=$source_id AND id(target) IN $target_ids
+            MERGE (source)-[:DERIVES_FROM]->(target)
+            RETURN count(*) as count
+            """
+            with connect_graph().session() as session:
+                result = session.run(query, source_id=data_model_node_id, target_ids=resouce_ids)
+                count = result.single()["count"]
+                logger.info(f"成功创建 {count} 个数据模型与数据资源的关系")
+                
+    except Exception as e:
+        logger.error(f"处理数据模型与元数据的关系时发生错误: {str(e)}")
+        raise
 
 
 # (从数据模型中选取)

+ 153 - 13
app/core/data_resource/resource.py

@@ -4,7 +4,7 @@ import logging
 from py2neo import Relationship
 import pandas as pd
 from app.services.neo4j_driver import neo4j_driver
-from app.core.graph.graph_operations import create_or_get_node, relationship_exists, get_node
+from app.core.graph.graph_operations import create_or_get_node, relationship_exists, get_node, connect_graph
 import time
 
 logger = logging.getLogger("app")
@@ -109,6 +109,13 @@ def handle_node(receiver, head_data, data_source=None, resource_type=None):
             'time': get_formatted_time(),
             'type': type_value  # 根据资源类型设置不同的type值
         }
+        
+        # 记录describe字段是否存在于创建数据中
+        if "describe" in receiver:
+            logger.info(f"创建资源,describe字段将被设置为: {receiver.get('describe')}")
+        else:
+            logger.info("创建资源,describe字段不在创建数据中")
+        
         if 'additional_info' in receiver:
             del receiver['additional_info']
         # 从receiver中移除data_source属性,避免将复杂对象作为节点属性
@@ -130,6 +137,9 @@ def handle_node(receiver, head_data, data_source=None, resource_type=None):
             result = session.run(cypher, **receiver)
             data_resource_node = result.single()["n"]
             resource_id = data_resource_node.id  # 使用id属性获取数值ID
+            
+            # 记录创建后的节点数据
+            logger.info(f"创建后的节点数据,describe字段: {data_resource_node.get('describe')}")
 
             # 处理标签关系
             if tag_list:
@@ -301,7 +311,18 @@ def handle_id_resource(resource_id):
                 return None
                 
             # 构建返回数据
+            logger.info(f"record: {record}")
+
             data_resource = dict(record["n"])
+            
+            logger.info(f"data_resource: {data_resource}")
+            logger.info(f"describe field in node: {record['n'].get('describe')}")
+            
+            # 确保describe字段存在,即使为null也记录下来
+            if 'describe' in record["n"]:
+                data_resource["describe"] = record["n"].get('describe')
+                logger.info(f"设置describe字段: {data_resource['describe']}")
+            
             data_resource["id"] = record["n"].id
             
             # 查询关联的标签
@@ -313,10 +334,18 @@ def handle_id_resource(resource_id):
             tag_result = session.run(tag_cypher, resource_id=resource_id_int)
             tag_record = tag_result.single()
             
+            # 设置标签信息
             if tag_record:
-                tag = dict(tag_record["t"])
-                tag["id"] = tag_record["t"].id
-                data_resource["tag_info"] = tag
+                tag = {
+                    "name": tag_record["t"].get("name"),
+                    "id": tag_record["t"].id
+                }
+            else:
+                tag = {
+                    "name": None,
+                    "id": None
+                }
+            data_resource["tag"] = tag
             
             # 查询关联的元数据 - 支持meta_data和Metadata两种标签
             meta_cypher = """
@@ -327,15 +356,46 @@ def handle_id_resource(resource_id):
             """
             meta_result = session.run(meta_cypher, resource_id=resource_id_int)
             
-            meta_list = []
+            parsed_data = []
             for meta_record in meta_result:
                 meta = dict(meta_record["m"])
-                meta["id"] = meta_record["m"].id
-                meta_list.append(meta)
+                meta_data = {
+                    "id": meta_record["m"].id,
+                    "name": meta.get("name"),
+                    "en_name": meta.get("en_name"),
+                    "data_type": meta.get("data_type"),
+                    "data_standard": {
+                        "name": None,
+                        "id": None
+                    }
+                }
+                parsed_data.append(meta_data)
+            
+            data_resource["parsed_data"] = parsed_data
+            
+            # 确保所有必需字段都有默认值
+            required_fields = {
+                "leader": "",
+                "organization": "",
+                "name": "",
+                "en_name": "",
+                "data_sensitivity": "",
+                "location": "/",
+                "time": "",
+                "type": "",
+                "category": "",
+                "url": "",
+                "frequency": "",
+                "status": True,
+                "keywords": [],
+                "describe": ""
+            }
             
-            data_resource["meta_list"] = meta_list
+            for field, default_value in required_fields.items():
+                if field not in data_resource or data_resource[field] is None:
+                    data_resource[field] = default_value
             
-            logger.info(f"成功获取资源详情,ID: {resource_id_int}")
+            logger.info(f"成功获取资源详情,ID: {resource_id_int}, describe: {data_resource.get('describe')}")
             return data_resource
     except Exception as e:
         logger.error(f"处理单个数据资源查询失败: {str(e)}")
@@ -1145,9 +1205,15 @@ def data_resource_edit(data):
             # 更新节点属性
             update_fields = {}
             for key, value in data.items():
-                if key != "id" and key != "tag":
+                if key != "id" and key != "parsed_data" and value is not None:
                     update_fields[key] = value
             
+            # 记录describe字段是否存在于待更新数据中
+            if "describe" in data:
+                logger.info(f"编辑资源,describe字段将被更新为: {data.get('describe')}")
+            else:
+                logger.info("编辑资源,describe字段不在更新数据中")
+            
             # 添加更新时间
             update_fields["updateTime"] = get_formatted_time()
             
@@ -1165,7 +1231,10 @@ def data_resource_edit(data):
             
             if not updated_node:
                 raise ValueError("资源不存在")
-                
+            
+            # 记录更新后的节点数据
+            logger.info(f"更新后的节点数据,describe字段: {updated_node['n'].get('describe')}")
+            
             # 处理标签关系
             tag_id = data.get("tag")
             if tag_id:
@@ -1184,11 +1253,82 @@ def data_resource_edit(data):
                 CREATE (n)-[r:label]->(t)
                 RETURN r
                 """
-                
                 session.run(create_rel_cypher, resource_id=int(resource_id), tag_id=int(tag_id))
             
+            # 处理元数据关系
+            parsed_data = data.get("parsed_data", [])
+            if parsed_data:
+                # 删除旧的元数据关系
+                delete_meta_cypher = """
+                MATCH (n:data_resource)-[r:contain]->()
+                WHERE id(n) = $resource_id
+                DELETE r
+                """
+                session.run(delete_meta_cypher, resource_id=int(resource_id))
+                
+                # 删除旧的清洗资源关系
+                delete_clean_cypher = """
+                MATCH (n:data_resource)-[r:clean_resource]->()
+                WHERE id(n) = $resource_id
+                DELETE r
+                """
+                session.run(delete_clean_cypher, resource_id=int(resource_id))
+                
+                # 创建新的元数据关系和相关关系
+                for meta in parsed_data:
+                    meta_id = meta.get("id")
+                    if meta_id:
+                        # 创建元数据关系
+                        create_meta_cypher = """
+                        MATCH (n:data_resource), (m:meta_data)
+                        WHERE id(n) = $resource_id AND id(m) = $meta_id
+                        CREATE (n)-[r:contain]->(m)
+                        RETURN r
+                        """
+                        session.run(create_meta_cypher, resource_id=int(resource_id), meta_id=int(meta_id))
+                        
+                        # 处理主数据关系
+                        master_data = meta.get("master_data")
+                        if master_data:
+                            # 创建主数据关系
+                            create_master_cypher = """
+                            MATCH (master), (meta:meta_data)
+                            WHERE id(master) = $master_id AND id(meta) = $meta_id
+                            MERGE (master)-[r:master]->(meta)
+                            RETURN r
+                            """
+                            session.run(create_master_cypher, master_id=int(master_data), meta_id=int(meta_id))
+                        
+                        # 处理数据标准关系
+                        data_standard = meta.get("data_standard")
+                        if data_standard and isinstance(data_standard, dict) and data_standard.get("id"):
+                            standard_id = data_standard.get("id")
+                            # 创建数据标准与元数据的关系
+                            create_standard_meta_cypher = """
+                            MATCH (standard), (meta:meta_data)
+                            WHERE id(standard) = $standard_id AND id(meta) = $meta_id
+                            MERGE (standard)-[r:clean_resource]->(meta)
+                            RETURN r
+                            """
+                            session.run(create_standard_meta_cypher, standard_id=int(standard_id), meta_id=int(meta_id))
+                            
+                            # 创建数据资源与数据标准的关系
+                            create_resource_standard_cypher = """
+                            MATCH (resource:data_resource), (standard)
+                            WHERE id(resource) = $resource_id AND id(standard) = $standard_id
+                            MERGE (resource)-[r:clean_resource]->(standard)
+                            RETURN r
+                            """
+                            session.run(create_resource_standard_cypher, resource_id=int(resource_id), standard_id=int(standard_id))
+            
             # 返回更新后的节点
-            return dict(updated_node["n"])
+            node_data = dict(updated_node["n"])
+            node_data["id"] = updated_node["n"].id
+            
+            # 记录最终返回的describe字段
+            logger.info(f"data_resource_edit返回数据,describe字段: {node_data.get('describe')}")
+            
+            return node_data
     except Exception as e:
         logger.error(f"编辑数据资源失败: {str(e)}")
         raise

+ 4 - 0
app/core/graph/graph_operations.py

@@ -72,6 +72,10 @@ def create_or_get_node(label, **properties):
     """
     try:
         with connect_graph().session() as session:
+            # 移除 id_list 属性
+            if 'id_list' in properties:
+                properties.pop('id_list')
+                
             # 检查是否提供了id
             if 'id' in properties:
                 node_id = properties['id']