""" Graph API module 提供图数据库操作的API接口 """ import logging from flask import jsonify, request from app.api.graph import bp from app.core.graph import ( create_or_get_node, create_relationship, execute_cypher_query, get_subgraph, ) from app.models.result import failed, success logger = logging.getLogger("app") # 查询图数据 @bp.route("/query", methods=["POST"]) def query_graph(): """ 执行自定义Cypher查询 Args (通过JSON请求体): cypher (str): Cypher查询语句 params (dict, optional): 查询参数 Returns: JSON: 包含查询结果的响应 """ try: # 获取查询语句 cypher = request.json.get("cypher", "") if request.json is not None else "" params = request.json.get("params", {}) if request.json is not None else {} if not cypher: return jsonify(failed("查询语句不能为空")) # 执行查询 data = execute_cypher_query(cypher, params) return jsonify(success(data)) except Exception as e: logger.error(f"图数据查询失败: {str(e)}") return jsonify(failed(str(e))) # 创建节点 @bp.route("/node/create", methods=["POST"]) def create_node(): """ 创建新节点 Args (通过JSON请求体): labels (list): 节点标签列表 properties (dict): 节点属性 Returns: JSON: 包含创建的节点信息的响应 """ try: # 获取节点信息 labels = request.json.get("labels", []) if request.json is not None else [] properties = ( request.json.get("properties", {}) if request.json is not None else {} ) if not labels: return jsonify(failed("节点标签不能为空")) # 构建标签字符串 label = ":".join(labels) # 创建节点 node_id = create_or_get_node(label, **properties) # 查询创建的节点 cypher = f"MATCH (n) WHERE id(n) = {node_id} RETURN n" result = execute_cypher_query(cypher) if result and len(result) > 0: return jsonify(success(result[0])) else: return jsonify(failed("节点创建失败")) except Exception as e: logger.error(f"创建节点失败: {str(e)}") return jsonify(failed(str(e))) # 创建关系 @bp.route("/relationship/create", methods=["POST"]) def create_rel(): """ 创建节点间的关系 Args (通过JSON请求体): startNodeId (int): 起始节点ID endNodeId (int): 结束节点ID type (str): 关系类型 properties (dict, optional): 关系属性 Returns: JSON: 包含创建的关系信息的响应 """ try: # 获取关系信息 start_node_id = ( request.json.get("startNodeId") if request.json is not None else None ) end_node_id = ( request.json.get("endNodeId") if request.json is not None else None ) rel_type = request.json.get("type") if request.json is not None else None properties = ( request.json.get("properties", {}) if request.json is not None else {} ) if not all([start_node_id, end_node_id, rel_type]): return jsonify(failed("关系参数不完整")) # 创建关系 rel_id = create_relationship(start_node_id, end_node_id, rel_type, **properties) if rel_id: # 查询创建的关系 cypher = f"MATCH ()-[r]-() WHERE id(r) = {rel_id} RETURN r" result = execute_cypher_query(cypher) if result and len(result) > 0: return jsonify(success(result[0])) return jsonify(failed("关系创建失败")) except Exception as e: logger.error(f"创建关系失败: {str(e)}") return jsonify(failed(str(e))) # 获取图谱数据 @bp.route("/subgraph", methods=["POST"]) def get_graph_data(): """ 获取子图数据 Args (通过JSON请求体): nodeIds (list): 节点ID列表 relationshipTypes (list, optional): 关系类型列表 maxDepth (int, optional): 最大深度,默认为1 Returns: JSON: 包含节点和关系的子图数据 """ try: # 获取请求参数 node_ids = request.json.get("nodeIds", []) if request.json is not None else [] rel_types = ( request.json.get("relationshipTypes", []) if request.json is not None else [] ) max_depth = request.json.get("maxDepth", 1) if request.json is not None else 1 if not node_ids: return jsonify(failed("节点ID列表不能为空")) # 获取子图 graph_data = get_subgraph(node_ids, rel_types, max_depth) return jsonify(success(graph_data)) except Exception as e: logger.error(f"获取图谱数据失败: {str(e)}") return jsonify(failed(str(e)))