Bladeren bron

代码提交

SGTY 2 weken geleden
bovenliggende
commit
c7eb0ddaad
2 gewijzigde bestanden met toevoegingen van 215 en 0 verwijderingen
  1. 25 0
      src/knowledge/router/graph_api.py
  2. 190 0
      src/knowledge/service/kg_graph_service.py

+ 25 - 0
src/knowledge/router/graph_api.py

@@ -0,0 +1,25 @@
+from fastapi import APIRouter, Depends
+from pydantic import BaseModel
+from typing import Optional
+
+from ..db.session import get_db
+from ..model.response import StandardResponse
+from ..service.kg_graph_service import KgGraphService
+
+router = APIRouter()
+
+class KgQuery(BaseModel):
+    label_name: str
+    input_str: str
+
+@router.post("/getGraph")
+async def get_graph(kg_query: KgQuery) -> StandardResponse:
+    db = next(get_db())
+    kg_graph_service = KgGraphService(db)
+    graph_data = kg_graph_service.get_graph_fac(kg_query.label_name,kg_query.input_str)
+    return StandardResponse(
+        success=True,
+        data=graph_data
+    )
+
+graph_router = router

+ 190 - 0
src/knowledge/service/kg_graph_service.py

@@ -0,0 +1,190 @@
+from typing import List, Dict, Optional
+from sqlalchemy.orm import Session
+from sqlalchemy import text
+from ..db.session import get_db
+
+class KgGraphService:
+    def __init__(self, db: Session):
+        self.db = db
+
+    def get_node_properties(self, node_id: int) -> Dict[str, str]:
+        """查询节点属性"""
+        prop_sql = "SELECT prop_title, prop_value FROM kg_props WHERE ref_id = :node_id"
+        result = self.db.execute(text(prop_sql), {'node_id': node_id}).fetchall()
+        return {row[0]: row[1] for row in result}
+
+    def get_graph(self, label_name: str, input_str: str) -> List[Dict]:
+        """查询知识图谱关系"""
+        # 1. 查询中心节点
+        node_sql = """
+        SELECT n.id, n.name, n.category 
+        FROM kg_nodes n 
+        WHERE n.category = :label_name AND n.name = :input_str 
+        AND n.status = '0'"""
+        
+        center_node = self.db.execute(
+            text(node_sql), 
+            {'label_name': label_name, 'input_str': input_str}
+        ).fetchone()
+        
+        if not center_node:
+            return []
+            
+        # 获取中心节点属性
+        s_id, s_name, s_label = center_node
+        s_prop = self.get_node_properties(s_id)
+        s_prop['name'] = s_name
+        
+        # 2. 查询关联的边和目标节点
+        relation_sql = """
+        WITH RankedRelations AS (
+            SELECT e.name as rType, m.id as target_id, m.name as target_name, 
+                   m.category as target_label, 
+                   (SELECT COUNT(*) FROM kg_edges WHERE src_id = m.id) as pCount, 
+                   ROW_NUMBER() OVER(PARTITION BY e.name ORDER BY m.id) as rn 
+            FROM kg_nodes n 
+            JOIN kg_edges e ON n.id = e.src_id 
+            JOIN kg_nodes m ON e.dest_id = m.id 
+            WHERE n.category = :label_name AND n.name = :input_str 
+            AND n.status = '0' 
+        ) 
+        SELECT rType, target_id, target_name, target_label, pCount 
+        FROM RankedRelations 
+        WHERE rn <= 50 
+        ORDER BY rType"""
+        
+        relations = self.db.execute(
+            text(relation_sql),
+            {'label_name': label_name, 'input_str': input_str}
+        ).fetchall()
+        
+        # 3. 组装返回结果
+        graph_data = {
+            'name': s_name,
+            'label': s_label,
+            'id': s_id,
+            'properties': s_prop,
+            'relations': []
+        }
+        
+        for r in relations:
+            r_type, e_id, e_name, e_label, p_count = r
+            e_prop = self.get_node_properties(e_id)
+            e_prop['name'] = e_name
+            
+            relation_data = {
+                'rType': r_type,
+                'target': {
+                    'id': e_id,
+                    'name': e_name,
+                    'label': e_label,
+                    'pCount': p_count,
+                    'properties': e_prop
+                }
+            }
+            graph_data['relations'].append(relation_data)
+        
+        return [graph_data]
+        
+    def get_graph_fac(self, label_name: str, input_str: str) -> Dict:
+        """获取知识图谱前端展示数据"""
+        graph_data = {
+            'categories': [],
+            'node': [],
+            'links': []
+        }
+        
+        # 获取原始图谱数据
+        res = self.get_graph(label_name, input_str)
+        if not res:
+            return graph_data
+            
+        item_style_map = {"display": True}
+        node_id = 0
+        
+        # 添加分类
+        graph_data['categories'].append({"name": "中心词"})
+        graph_data['categories'].append({"name": "关系"})
+        c_map = {"中心词": 0, "关系": 1}
+        
+        # 处理中心节点
+        graph_dto = res[0]
+        g_node_dto = {
+            'name': graph_dto['name'],
+            'category': 0,
+            'label': graph_dto['label'],
+            'id': node_id,
+            'symbol': 'circle',
+            'size': 50,
+            'properties': graph_dto['properties'],
+            'kg_id': graph_dto['id'],
+            'itemStyle': item_style_map
+        }
+        node_id += 1
+        graph_data['node'].append(g_node_dto)
+        
+        # 处理关系节点
+        if graph_dto['relations']:
+            rs_id = 2
+            for relation in graph_dto['relations']:
+                r_type = relation['rType']
+                if r_type not in c_map:
+                    c_map[r_type] = rs_id
+                    graph_data['categories'].append({"name": r_type})
+                    rs_id += 1
+                
+                # 添加关系节点
+                n_node_dto = {
+                    'name': "",
+                    'category': 1,
+                    'label': graph_dto['label'],
+                    'id': node_id,
+                    'symbol': 'diamond',
+                    'size': 10,
+                    'properties': graph_dto['properties'],
+                    'kg_id': graph_dto['id'],
+                    'itemStyle': item_style_map
+                }
+                graph_data['node'].append(n_node_dto)
+                
+                # 添加关系链接
+                graph_data['links'].append({
+                    'source': g_node_dto['name'],
+                    'target': n_node_dto['name'],
+                    'label': r_type,
+                    'category': r_type
+                })
+                
+                node_id += 1
+                
+                # 处理目标节点
+                target = relation['target']
+                children_item_style_map = {"display": True}
+                symbol = "circle"
+                
+                if target['pCount'] == 0:
+                    children_item_style_map["display"] = False
+                
+                e_node_dto = {
+                    'name': target['name'],
+                    'category': c_map[r_type],
+                    'label': target['label'],
+                    'id': node_id,
+                    'symbol': symbol,
+                    'size': 28,
+                    'properties': target['properties'],
+                    'kg_id': target['id'],
+                    'itemStyle': children_item_style_map
+                }
+                node_id += 1
+                graph_data['node'].append(e_node_dto)
+                
+                # 添加目标节点链接
+                graph_data['links'].append({
+                    'source': n_node_dto['name'],
+                    'target': e_node_dto['name'],
+                    'label': "",
+                    'category': r_type
+                })
+        
+        return graph_data