refactor: 按go modules规范重构

This commit is contained in:
2026-04-15 15:19:39 +08:00
parent 8c5cd3705a
commit 5d4bf761b8
21 changed files with 524 additions and 679 deletions
+10 -10
View File
@@ -10,11 +10,11 @@ import (
swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
"knowledge-graph-backend/config"
"knowledge-graph-backend/docs"
"knowledge-graph-backend/handlers"
neo4jClient "knowledge-graph-backend/neo4j"
"knowledge-graph-backend/services"
"knowledge-graph-backend/internal/config"
"knowledge-graph-backend/internal/handler"
neo4jClient "knowledge-graph-backend/internal/repository/neo4j"
"knowledge-graph-backend/internal/service"
)
// @title 知识图谱 API
@@ -31,15 +31,15 @@ func main() {
driver := neo4jClient.NewDriver(cfg.Neo4j)
defer driver.Close(context.Background())
graphService := services.NewNeo4jService(driver)
graphService := service.NewNeo4jService(driver)
graphHandler := handlers.NewGraphHandler(graphService)
searchHandler := handlers.NewSearchHandler(graphService)
nodeHandler := handlers.NewNodeHandler(graphService)
graphHandler := handler.NewGraphHandler(graphService)
searchHandler := handler.NewSearchHandler(graphService)
nodeHandler := handler.NewNodeHandler(graphService)
// 增删改处理器
nodeCRUDHandler := handlers.NewNodeCRUDHandler(graphService)
edgeCRUDHandler := handlers.NewEdgeCRUDHandler(graphService)
nodeCRUDHandler := handler.NewNodeCRUDHandler(graphService)
edgeCRUDHandler := handler.NewEdgeCRUDHandler(graphService)
router := gin.Default()
+83 -93
View File
@@ -32,7 +32,7 @@ const docTemplate = `{
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/models.CreateEdgeRequest"
"$ref": "#/definitions/model.CreateEdgeRequest"
}
}
],
@@ -40,31 +40,31 @@ const docTemplate = `{
"200": {
"description": "创建成功",
"schema": {
"$ref": "#/definitions/models.EdgeResponse"
"$ref": "#/definitions/model.EdgeResponse"
}
},
"400": {
"description": "请求错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
},
"404": {
"description": "源节点或目标节点未找到",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
},
"409": {
"description": "边已存在",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
},
"500": {
"description": "内部错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
}
}
@@ -90,19 +90,19 @@ const docTemplate = `{
"200": {
"description": "删除成功",
"schema": {
"$ref": "#/definitions/models.DeleteResponse"
"$ref": "#/definitions/model.DeleteResponse"
}
},
"404": {
"description": "边未找到",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
},
"500": {
"description": "内部错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
}
}
@@ -119,13 +119,13 @@ const docTemplate = `{
"200": {
"description": "成功",
"schema": {
"$ref": "#/definitions/models.GraphData"
"$ref": "#/definitions/model.GraphData"
}
},
"500": {
"description": "内部错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
}
}
@@ -142,13 +142,13 @@ const docTemplate = `{
"200": {
"description": "成功",
"schema": {
"$ref": "#/definitions/models.SimpleGraphData"
"$ref": "#/definitions/model.SimpleGraphData"
}
},
"500": {
"description": "内部错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
}
}
@@ -172,7 +172,7 @@ const docTemplate = `{
"500": {
"description": "内部错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
}
}
@@ -195,7 +195,7 @@ const docTemplate = `{
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/models.CreateNodeRequest"
"$ref": "#/definitions/model.CreateNodeRequest"
}
}
],
@@ -203,25 +203,25 @@ const docTemplate = `{
"200": {
"description": "创建成功",
"schema": {
"$ref": "#/definitions/models.Node"
"$ref": "#/definitions/model.Node"
}
},
"400": {
"description": "请求错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
},
"409": {
"description": "节点已存在",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
},
"500": {
"description": "内部错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
}
}
@@ -247,25 +247,25 @@ const docTemplate = `{
"200": {
"description": "成功",
"schema": {
"$ref": "#/definitions/models.NodeResponse"
"$ref": "#/definitions/model.NodeResponse"
}
},
"400": {
"description": "请求错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
},
"404": {
"description": "节点未找到",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
},
"500": {
"description": "内部错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
}
}
@@ -293,7 +293,7 @@ const docTemplate = `{
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/models.UpdateNodeRequest"
"$ref": "#/definitions/model.UpdateNodeRequest"
}
}
],
@@ -301,25 +301,25 @@ const docTemplate = `{
"200": {
"description": "更新成功",
"schema": {
"$ref": "#/definitions/models.Node"
"$ref": "#/definitions/model.Node"
}
},
"400": {
"description": "请求错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
},
"404": {
"description": "节点未找到",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
},
"500": {
"description": "内部错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
}
}
@@ -343,19 +343,19 @@ const docTemplate = `{
"200": {
"description": "删除成功",
"schema": {
"$ref": "#/definitions/models.DeleteResponse"
"$ref": "#/definitions/model.DeleteResponse"
}
},
"404": {
"description": "节点未找到",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
},
"500": {
"description": "内部错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
}
}
@@ -381,25 +381,25 @@ const docTemplate = `{
"200": {
"description": "成功",
"schema": {
"$ref": "#/definitions/models.NeighborResponse"
"$ref": "#/definitions/model.NeighborResponse"
}
},
"400": {
"description": "请求错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
},
"404": {
"description": "节点未找到",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
},
"500": {
"description": "内部错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
}
}
@@ -425,19 +425,19 @@ const docTemplate = `{
"200": {
"description": "成功",
"schema": {
"$ref": "#/definitions/models.SearchResponse"
"$ref": "#/definitions/model.SearchResponse"
}
},
"400": {
"description": "请求错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
},
"500": {
"description": "内部错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
}
}
@@ -445,7 +445,7 @@ const docTemplate = `{
}
},
"definitions": {
"models.CreateEdgeRequest": {
"model.CreateEdgeRequest": {
"type": "object",
"required": [
"id",
@@ -455,38 +455,32 @@ const docTemplate = `{
],
"properties": {
"id": {
"description": "边的唯一标识",
"type": "string",
"example": "edge_123"
},
"label": {
"description": "边的显示标签",
"type": "string",
"example": "包含"
},
"properties": {
"description": "自定义属性",
"type": "object",
"additionalProperties": true
},
"source": {
"description": "源节点ID",
"type": "string",
"example": "node_1"
},
"target": {
"description": "目标节点ID",
"type": "string",
"example": "node_2"
},
"type": {
"description": "边的类型(可选,默认为关系类型)",
"type": "string",
"example": "CONTAINS"
}
}
},
"models.CreateNodeRequest": {
"model.CreateNodeRequest": {
"type": "object",
"required": [
"id",
@@ -495,58 +489,49 @@ const docTemplate = `{
],
"properties": {
"id": {
"description": "节点唯一标识",
"type": "string",
"example": "node_123"
},
"label": {
"description": "节点显示标签",
"type": "string",
"example": "人工智能"
},
"properties": {
"description": "自定义属性",
"type": "object",
"additionalProperties": true
},
"type": {
"description": "节点类型",
"type": "string",
"example": "概念"
},
"x": {
"description": "X坐标(可选)",
"type": "number",
"example": 100
},
"y": {
"description": "Y坐标(可选)",
"type": "number",
"example": 200
}
}
},
"models.DeleteResponse": {
"model.DeleteResponse": {
"type": "object",
"properties": {
"id": {
"description": "被删除的实体ID(可选)",
"type": "string",
"example": "node_123"
},
"message": {
"description": "消息",
"type": "string",
"example": "节点已成功删除"
},
"success": {
"description": "是否成功",
"type": "boolean",
"example": true
}
}
},
"models.Edge": {
"model.Edge": {
"type": "object",
"properties": {
"id": {
@@ -574,42 +559,36 @@ const docTemplate = `{
}
}
},
"models.EdgeResponse": {
"model.EdgeResponse": {
"type": "object",
"properties": {
"id": {
"description": "边的ID",
"type": "string",
"example": "edge_123"
},
"label": {
"description": "边的显示标签",
"type": "string",
"example": "包含"
},
"properties": {
"description": "自定义属性",
"type": "object",
"additionalProperties": true
},
"source": {
"description": "源节点ID",
"type": "string",
"example": "node_1"
},
"target": {
"description": "目标节点ID",
"type": "string",
"example": "node_2"
},
"type": {
"description": "边的类型",
"type": "string",
"example": "CONTAINS"
}
}
},
"models.ErrorResponse": {
"model.ErrorResponse": {
"type": "object",
"properties": {
"error": {
@@ -620,41 +599,41 @@ const docTemplate = `{
}
}
},
"models.GraphData": {
"model.GraphData": {
"type": "object",
"properties": {
"edges": {
"type": "array",
"items": {
"$ref": "#/definitions/models.Edge"
"$ref": "#/definitions/model.Edge"
}
},
"nodes": {
"type": "array",
"items": {
"$ref": "#/definitions/models.Node"
"$ref": "#/definitions/model.Node"
}
}
}
},
"models.NeighborResponse": {
"model.NeighborResponse": {
"type": "object",
"properties": {
"edges": {
"type": "array",
"items": {
"$ref": "#/definitions/models.Edge"
"$ref": "#/definitions/model.Edge"
}
},
"nodes": {
"type": "array",
"items": {
"$ref": "#/definitions/models.Node"
"$ref": "#/definitions/model.Node"
}
}
}
},
"models.Node": {
"model.Node": {
"type": "object",
"properties": {
"id": {
@@ -682,42 +661,58 @@ const docTemplate = `{
}
}
},
"models.NodeResponse": {
"model.NodeResponse": {
"type": "object",
"properties": {
"id": {
"type": "string",
"example": "1"
"type": "string"
},
"label": {
"type": "string",
"example": "人工智能"
"type": "string"
},
"neighbors": {
"type": "array",
"items": {
"$ref": "#/definitions/model.Node"
}
},
"properties": {
"type": "object",
"additionalProperties": true
},
"style": {
"type": "object",
"additionalProperties": true
},
"type": {
"type": "string",
"example": "概念"
"type": "string"
},
"x": {
"type": "number"
},
"y": {
"type": "number"
}
}
},
"models.SearchResponse": {
"model.SearchResponse": {
"type": "object",
"properties": {
"count": {
"type": "integer"
},
"results": {
"nodes": {
"type": "array",
"items": {
"$ref": "#/definitions/models.Node"
"$ref": "#/definitions/model.Node"
}
},
"query": {
"type": "string"
}
}
},
"models.SimpleEdge": {
"model.SimpleEdge": {
"type": "object",
"properties": {
"label": {
@@ -738,24 +733,24 @@ const docTemplate = `{
}
}
},
"models.SimpleGraphData": {
"model.SimpleGraphData": {
"type": "object",
"properties": {
"edges": {
"type": "array",
"items": {
"$ref": "#/definitions/models.SimpleEdge"
"$ref": "#/definitions/model.SimpleEdge"
}
},
"nodes": {
"type": "array",
"items": {
"$ref": "#/definitions/models.SimpleNode"
"$ref": "#/definitions/model.SimpleNode"
}
}
}
},
"models.SimpleNode": {
"model.SimpleNode": {
"type": "object",
"properties": {
"id": {
@@ -772,31 +767,26 @@ const docTemplate = `{
}
}
},
"models.UpdateNodeRequest": {
"model.UpdateNodeRequest": {
"type": "object",
"properties": {
"label": {
"description": "节点显示标签",
"type": "string",
"example": "机器学习"
},
"properties": {
"description": "自定义属性(更新)",
"type": "object",
"additionalProperties": true
},
"type": {
"description": "节点类型",
"type": "string",
"example": "工具"
},
"x": {
"description": "X坐标",
"type": "number",
"example": 150
},
"y": {
"description": "Y坐标",
"type": "number",
"example": 250
}
+83 -93
View File
@@ -26,7 +26,7 @@
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/models.CreateEdgeRequest"
"$ref": "#/definitions/model.CreateEdgeRequest"
}
}
],
@@ -34,31 +34,31 @@
"200": {
"description": "创建成功",
"schema": {
"$ref": "#/definitions/models.EdgeResponse"
"$ref": "#/definitions/model.EdgeResponse"
}
},
"400": {
"description": "请求错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
},
"404": {
"description": "源节点或目标节点未找到",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
},
"409": {
"description": "边已存在",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
},
"500": {
"description": "内部错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
}
}
@@ -84,19 +84,19 @@
"200": {
"description": "删除成功",
"schema": {
"$ref": "#/definitions/models.DeleteResponse"
"$ref": "#/definitions/model.DeleteResponse"
}
},
"404": {
"description": "边未找到",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
},
"500": {
"description": "内部错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
}
}
@@ -113,13 +113,13 @@
"200": {
"description": "成功",
"schema": {
"$ref": "#/definitions/models.GraphData"
"$ref": "#/definitions/model.GraphData"
}
},
"500": {
"description": "内部错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
}
}
@@ -136,13 +136,13 @@
"200": {
"description": "成功",
"schema": {
"$ref": "#/definitions/models.SimpleGraphData"
"$ref": "#/definitions/model.SimpleGraphData"
}
},
"500": {
"description": "内部错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
}
}
@@ -166,7 +166,7 @@
"500": {
"description": "内部错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
}
}
@@ -189,7 +189,7 @@
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/models.CreateNodeRequest"
"$ref": "#/definitions/model.CreateNodeRequest"
}
}
],
@@ -197,25 +197,25 @@
"200": {
"description": "创建成功",
"schema": {
"$ref": "#/definitions/models.Node"
"$ref": "#/definitions/model.Node"
}
},
"400": {
"description": "请求错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
},
"409": {
"description": "节点已存在",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
},
"500": {
"description": "内部错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
}
}
@@ -241,25 +241,25 @@
"200": {
"description": "成功",
"schema": {
"$ref": "#/definitions/models.NodeResponse"
"$ref": "#/definitions/model.NodeResponse"
}
},
"400": {
"description": "请求错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
},
"404": {
"description": "节点未找到",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
},
"500": {
"description": "内部错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
}
}
@@ -287,7 +287,7 @@
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/models.UpdateNodeRequest"
"$ref": "#/definitions/model.UpdateNodeRequest"
}
}
],
@@ -295,25 +295,25 @@
"200": {
"description": "更新成功",
"schema": {
"$ref": "#/definitions/models.Node"
"$ref": "#/definitions/model.Node"
}
},
"400": {
"description": "请求错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
},
"404": {
"description": "节点未找到",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
},
"500": {
"description": "内部错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
}
}
@@ -337,19 +337,19 @@
"200": {
"description": "删除成功",
"schema": {
"$ref": "#/definitions/models.DeleteResponse"
"$ref": "#/definitions/model.DeleteResponse"
}
},
"404": {
"description": "节点未找到",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
},
"500": {
"description": "内部错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
}
}
@@ -375,25 +375,25 @@
"200": {
"description": "成功",
"schema": {
"$ref": "#/definitions/models.NeighborResponse"
"$ref": "#/definitions/model.NeighborResponse"
}
},
"400": {
"description": "请求错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
},
"404": {
"description": "节点未找到",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
},
"500": {
"description": "内部错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
}
}
@@ -419,19 +419,19 @@
"200": {
"description": "成功",
"schema": {
"$ref": "#/definitions/models.SearchResponse"
"$ref": "#/definitions/model.SearchResponse"
}
},
"400": {
"description": "请求错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
},
"500": {
"description": "内部错误",
"schema": {
"$ref": "#/definitions/models.ErrorResponse"
"$ref": "#/definitions/model.ErrorResponse"
}
}
}
@@ -439,7 +439,7 @@
}
},
"definitions": {
"models.CreateEdgeRequest": {
"model.CreateEdgeRequest": {
"type": "object",
"required": [
"id",
@@ -449,38 +449,32 @@
],
"properties": {
"id": {
"description": "边的唯一标识",
"type": "string",
"example": "edge_123"
},
"label": {
"description": "边的显示标签",
"type": "string",
"example": "包含"
},
"properties": {
"description": "自定义属性",
"type": "object",
"additionalProperties": true
},
"source": {
"description": "源节点ID",
"type": "string",
"example": "node_1"
},
"target": {
"description": "目标节点ID",
"type": "string",
"example": "node_2"
},
"type": {
"description": "边的类型(可选,默认为关系类型)",
"type": "string",
"example": "CONTAINS"
}
}
},
"models.CreateNodeRequest": {
"model.CreateNodeRequest": {
"type": "object",
"required": [
"id",
@@ -489,58 +483,49 @@
],
"properties": {
"id": {
"description": "节点唯一标识",
"type": "string",
"example": "node_123"
},
"label": {
"description": "节点显示标签",
"type": "string",
"example": "人工智能"
},
"properties": {
"description": "自定义属性",
"type": "object",
"additionalProperties": true
},
"type": {
"description": "节点类型",
"type": "string",
"example": "概念"
},
"x": {
"description": "X坐标(可选)",
"type": "number",
"example": 100
},
"y": {
"description": "Y坐标(可选)",
"type": "number",
"example": 200
}
}
},
"models.DeleteResponse": {
"model.DeleteResponse": {
"type": "object",
"properties": {
"id": {
"description": "被删除的实体ID(可选)",
"type": "string",
"example": "node_123"
},
"message": {
"description": "消息",
"type": "string",
"example": "节点已成功删除"
},
"success": {
"description": "是否成功",
"type": "boolean",
"example": true
}
}
},
"models.Edge": {
"model.Edge": {
"type": "object",
"properties": {
"id": {
@@ -568,42 +553,36 @@
}
}
},
"models.EdgeResponse": {
"model.EdgeResponse": {
"type": "object",
"properties": {
"id": {
"description": "边的ID",
"type": "string",
"example": "edge_123"
},
"label": {
"description": "边的显示标签",
"type": "string",
"example": "包含"
},
"properties": {
"description": "自定义属性",
"type": "object",
"additionalProperties": true
},
"source": {
"description": "源节点ID",
"type": "string",
"example": "node_1"
},
"target": {
"description": "目标节点ID",
"type": "string",
"example": "node_2"
},
"type": {
"description": "边的类型",
"type": "string",
"example": "CONTAINS"
}
}
},
"models.ErrorResponse": {
"model.ErrorResponse": {
"type": "object",
"properties": {
"error": {
@@ -614,41 +593,41 @@
}
}
},
"models.GraphData": {
"model.GraphData": {
"type": "object",
"properties": {
"edges": {
"type": "array",
"items": {
"$ref": "#/definitions/models.Edge"
"$ref": "#/definitions/model.Edge"
}
},
"nodes": {
"type": "array",
"items": {
"$ref": "#/definitions/models.Node"
"$ref": "#/definitions/model.Node"
}
}
}
},
"models.NeighborResponse": {
"model.NeighborResponse": {
"type": "object",
"properties": {
"edges": {
"type": "array",
"items": {
"$ref": "#/definitions/models.Edge"
"$ref": "#/definitions/model.Edge"
}
},
"nodes": {
"type": "array",
"items": {
"$ref": "#/definitions/models.Node"
"$ref": "#/definitions/model.Node"
}
}
}
},
"models.Node": {
"model.Node": {
"type": "object",
"properties": {
"id": {
@@ -676,42 +655,58 @@
}
}
},
"models.NodeResponse": {
"model.NodeResponse": {
"type": "object",
"properties": {
"id": {
"type": "string",
"example": "1"
"type": "string"
},
"label": {
"type": "string",
"example": "人工智能"
"type": "string"
},
"neighbors": {
"type": "array",
"items": {
"$ref": "#/definitions/model.Node"
}
},
"properties": {
"type": "object",
"additionalProperties": true
},
"style": {
"type": "object",
"additionalProperties": true
},
"type": {
"type": "string",
"example": "概念"
"type": "string"
},
"x": {
"type": "number"
},
"y": {
"type": "number"
}
}
},
"models.SearchResponse": {
"model.SearchResponse": {
"type": "object",
"properties": {
"count": {
"type": "integer"
},
"results": {
"nodes": {
"type": "array",
"items": {
"$ref": "#/definitions/models.Node"
"$ref": "#/definitions/model.Node"
}
},
"query": {
"type": "string"
}
}
},
"models.SimpleEdge": {
"model.SimpleEdge": {
"type": "object",
"properties": {
"label": {
@@ -732,24 +727,24 @@
}
}
},
"models.SimpleGraphData": {
"model.SimpleGraphData": {
"type": "object",
"properties": {
"edges": {
"type": "array",
"items": {
"$ref": "#/definitions/models.SimpleEdge"
"$ref": "#/definitions/model.SimpleEdge"
}
},
"nodes": {
"type": "array",
"items": {
"$ref": "#/definitions/models.SimpleNode"
"$ref": "#/definitions/model.SimpleNode"
}
}
}
},
"models.SimpleNode": {
"model.SimpleNode": {
"type": "object",
"properties": {
"id": {
@@ -766,31 +761,26 @@
}
}
},
"models.UpdateNodeRequest": {
"model.UpdateNodeRequest": {
"type": "object",
"properties": {
"label": {
"description": "节点显示标签",
"type": "string",
"example": "机器学习"
},
"properties": {
"description": "自定义属性(更新)",
"type": "object",
"additionalProperties": true
},
"type": {
"description": "节点类型",
"type": "string",
"example": "工具"
},
"x": {
"description": "X坐标",
"type": "number",
"example": 150
},
"y": {
"description": "Y坐标",
"type": "number",
"example": 250
}
+74 -90
View File
@@ -1,29 +1,23 @@
basePath: /
definitions:
models.CreateEdgeRequest:
model.CreateEdgeRequest:
properties:
id:
description: 边的唯一标识
example: edge_123
type: string
label:
description: 边的显示标签
example: 包含
type: string
properties:
additionalProperties: true
description: 自定义属性
type: object
source:
description: 源节点ID
example: node_1
type: string
target:
description: 目标节点ID
example: node_2
type: string
type:
description: 边的类型(可选,默认为关系类型)
example: CONTAINS
type: string
required:
@@ -32,30 +26,24 @@ definitions:
- source
- target
type: object
models.CreateNodeRequest:
model.CreateNodeRequest:
properties:
id:
description: 节点唯一标识
example: node_123
type: string
label:
description: 节点显示标签
example: 人工智能
type: string
properties:
additionalProperties: true
description: 自定义属性
type: object
type:
description: 节点类型
example: 概念
type: string
x:
description: X坐标(可选)
example: 100
type: number
"y":
description: Y坐标(可选)
example: 200
type: number
required:
@@ -63,22 +51,19 @@ definitions:
- label
- type
type: object
models.DeleteResponse:
model.DeleteResponse:
properties:
id:
description: 被删除的实体ID(可选)
example: node_123
type: string
message:
description: 消息
example: 节点已成功删除
type: string
success:
description: 是否成功
example: true
type: boolean
type: object
models.Edge:
model.Edge:
properties:
id:
type: string
@@ -97,63 +82,57 @@ definitions:
type:
type: string
type: object
models.EdgeResponse:
model.EdgeResponse:
properties:
id:
description: 边的ID
example: edge_123
type: string
label:
description: 边的显示标签
example: 包含
type: string
properties:
additionalProperties: true
description: 自定义属性
type: object
source:
description: 源节点ID
example: node_1
type: string
target:
description: 目标节点ID
example: node_2
type: string
type:
description: 边的类型
example: CONTAINS
type: string
type: object
models.ErrorResponse:
model.ErrorResponse:
properties:
error:
type: string
message:
type: string
type: object
models.GraphData:
model.GraphData:
properties:
edges:
items:
$ref: '#/definitions/models.Edge'
$ref: '#/definitions/model.Edge'
type: array
nodes:
items:
$ref: '#/definitions/models.Node'
$ref: '#/definitions/model.Node'
type: array
type: object
models.NeighborResponse:
model.NeighborResponse:
properties:
edges:
items:
$ref: '#/definitions/models.Edge'
$ref: '#/definitions/model.Edge'
type: array
nodes:
items:
$ref: '#/definitions/models.Node'
$ref: '#/definitions/model.Node'
type: array
type: object
models.Node:
model.Node:
properties:
id:
type: string
@@ -172,31 +151,41 @@ definitions:
"y":
type: number
type: object
models.NodeResponse:
model.NodeResponse:
properties:
id:
example: "1"
type: string
label:
example: 人工智能
type: string
neighbors:
items:
$ref: '#/definitions/model.Node'
type: array
properties:
additionalProperties: true
type: object
style:
additionalProperties: true
type: object
type:
example: 概念
type: string
x:
type: number
"y":
type: number
type: object
models.SearchResponse:
model.SearchResponse:
properties:
count:
type: integer
results:
nodes:
items:
$ref: '#/definitions/models.Node'
$ref: '#/definitions/model.Node'
type: array
query:
type: string
type: object
models.SimpleEdge:
model.SimpleEdge:
properties:
label:
example: 包含
@@ -211,18 +200,18 @@ definitions:
example: CONTAINS
type: string
type: object
models.SimpleGraphData:
model.SimpleGraphData:
properties:
edges:
items:
$ref: '#/definitions/models.SimpleEdge'
$ref: '#/definitions/model.SimpleEdge'
type: array
nodes:
items:
$ref: '#/definitions/models.SimpleNode'
$ref: '#/definitions/model.SimpleNode'
type: array
type: object
models.SimpleNode:
model.SimpleNode:
properties:
id:
example: "1"
@@ -234,26 +223,21 @@ definitions:
example: 概念
type: string
type: object
models.UpdateNodeRequest:
model.UpdateNodeRequest:
properties:
label:
description: 节点显示标签
example: 机器学习
type: string
properties:
additionalProperties: true
description: 自定义属性(更新)
type: object
type:
description: 节点类型
example: 工具
type: string
x:
description: X坐标
example: 150
type: number
"y":
description: Y坐标
example: 250
type: number
type: object
@@ -275,30 +259,30 @@ paths:
name: request
required: true
schema:
$ref: '#/definitions/models.CreateEdgeRequest'
$ref: '#/definitions/model.CreateEdgeRequest'
produces:
- application/json
responses:
"200":
description: 创建成功
schema:
$ref: '#/definitions/models.EdgeResponse'
$ref: '#/definitions/model.EdgeResponse'
"400":
description: 请求错误
schema:
$ref: '#/definitions/models.ErrorResponse'
$ref: '#/definitions/model.ErrorResponse'
"404":
description: 源节点或目标节点未找到
schema:
$ref: '#/definitions/models.ErrorResponse'
$ref: '#/definitions/model.ErrorResponse'
"409":
description: 边已存在
schema:
$ref: '#/definitions/models.ErrorResponse'
$ref: '#/definitions/model.ErrorResponse'
"500":
description: 内部错误
schema:
$ref: '#/definitions/models.ErrorResponse'
$ref: '#/definitions/model.ErrorResponse'
summary: 创建边
/api/edges/{id}:
delete:
@@ -315,15 +299,15 @@ paths:
"200":
description: 删除成功
schema:
$ref: '#/definitions/models.DeleteResponse'
$ref: '#/definitions/model.DeleteResponse'
"404":
description: 边未找到
schema:
$ref: '#/definitions/models.ErrorResponse'
$ref: '#/definitions/model.ErrorResponse'
"500":
description: 内部错误
schema:
$ref: '#/definitions/models.ErrorResponse'
$ref: '#/definitions/model.ErrorResponse'
summary: 删除边
/api/graph:
get:
@@ -334,11 +318,11 @@ paths:
"200":
description: 成功
schema:
$ref: '#/definitions/models.GraphData'
$ref: '#/definitions/model.GraphData'
"500":
description: 内部错误
schema:
$ref: '#/definitions/models.ErrorResponse'
$ref: '#/definitions/model.ErrorResponse'
summary: 获取图数据
/api/graph/simpleJson:
get:
@@ -349,11 +333,11 @@ paths:
"200":
description: 成功
schema:
$ref: '#/definitions/models.SimpleGraphData'
$ref: '#/definitions/model.SimpleGraphData'
"500":
description: 内部错误
schema:
$ref: '#/definitions/models.ErrorResponse'
$ref: '#/definitions/model.ErrorResponse'
summary: 获取简化图数据
/api/graph/stats:
get:
@@ -369,7 +353,7 @@ paths:
"500":
description: 内部错误
schema:
$ref: '#/definitions/models.ErrorResponse'
$ref: '#/definitions/model.ErrorResponse'
summary: 获取图统计信息
/api/nodes:
post:
@@ -382,26 +366,26 @@ paths:
name: request
required: true
schema:
$ref: '#/definitions/models.CreateNodeRequest'
$ref: '#/definitions/model.CreateNodeRequest'
produces:
- application/json
responses:
"200":
description: 创建成功
schema:
$ref: '#/definitions/models.Node'
$ref: '#/definitions/model.Node'
"400":
description: 请求错误
schema:
$ref: '#/definitions/models.ErrorResponse'
$ref: '#/definitions/model.ErrorResponse'
"409":
description: 节点已存在
schema:
$ref: '#/definitions/models.ErrorResponse'
$ref: '#/definitions/model.ErrorResponse'
"500":
description: 内部错误
schema:
$ref: '#/definitions/models.ErrorResponse'
$ref: '#/definitions/model.ErrorResponse'
summary: 创建节点
/api/nodes/{id}:
delete:
@@ -418,15 +402,15 @@ paths:
"200":
description: 删除成功
schema:
$ref: '#/definitions/models.DeleteResponse'
$ref: '#/definitions/model.DeleteResponse'
"404":
description: 节点未找到
schema:
$ref: '#/definitions/models.ErrorResponse'
$ref: '#/definitions/model.ErrorResponse'
"500":
description: 内部错误
schema:
$ref: '#/definitions/models.ErrorResponse'
$ref: '#/definitions/model.ErrorResponse'
summary: 删除节点
get:
description: 根据节点 ID 获取知识图谱中的节点详细信息
@@ -442,19 +426,19 @@ paths:
"200":
description: 成功
schema:
$ref: '#/definitions/models.NodeResponse'
$ref: '#/definitions/model.NodeResponse'
"400":
description: 请求错误
schema:
$ref: '#/definitions/models.ErrorResponse'
$ref: '#/definitions/model.ErrorResponse'
"404":
description: 节点未找到
schema:
$ref: '#/definitions/models.ErrorResponse'
$ref: '#/definitions/model.ErrorResponse'
"500":
description: 内部错误
schema:
$ref: '#/definitions/models.ErrorResponse'
$ref: '#/definitions/model.ErrorResponse'
summary: 获取节点详情
put:
consumes:
@@ -471,26 +455,26 @@ paths:
name: request
required: true
schema:
$ref: '#/definitions/models.UpdateNodeRequest'
$ref: '#/definitions/model.UpdateNodeRequest'
produces:
- application/json
responses:
"200":
description: 更新成功
schema:
$ref: '#/definitions/models.Node'
$ref: '#/definitions/model.Node'
"400":
description: 请求错误
schema:
$ref: '#/definitions/models.ErrorResponse'
$ref: '#/definitions/model.ErrorResponse'
"404":
description: 节点未找到
schema:
$ref: '#/definitions/models.ErrorResponse'
$ref: '#/definitions/model.ErrorResponse'
"500":
description: 内部错误
schema:
$ref: '#/definitions/models.ErrorResponse'
$ref: '#/definitions/model.ErrorResponse'
summary: 更新节点
/api/nodes/{id}/neighbors:
get:
@@ -507,19 +491,19 @@ paths:
"200":
description: 成功
schema:
$ref: '#/definitions/models.NeighborResponse'
$ref: '#/definitions/model.NeighborResponse'
"400":
description: 请求错误
schema:
$ref: '#/definitions/models.ErrorResponse'
$ref: '#/definitions/model.ErrorResponse'
"404":
description: 节点未找到
schema:
$ref: '#/definitions/models.ErrorResponse'
$ref: '#/definitions/model.ErrorResponse'
"500":
description: 内部错误
schema:
$ref: '#/definitions/models.ErrorResponse'
$ref: '#/definitions/model.ErrorResponse'
summary: 获取节点邻居
/api/search:
get:
@@ -536,14 +520,14 @@ paths:
"200":
description: 成功
schema:
$ref: '#/definitions/models.SearchResponse'
$ref: '#/definitions/model.SearchResponse'
"400":
description: 请求错误
schema:
$ref: '#/definitions/models.ErrorResponse'
$ref: '#/definitions/model.ErrorResponse'
"500":
description: 内部错误
schema:
$ref: '#/definitions/models.ErrorResponse'
$ref: '#/definitions/model.ErrorResponse'
summary: 搜索节点
swagger: "2.0"
@@ -41,8 +41,8 @@ type Config struct {
func Load() (*Config, error) {
var err error
err = godotenv.Load("../config/.env")
err = godotenv.Load("./config/.env")
err = godotenv.Load("../configs/.env")
err = godotenv.Load("./configs/.env")
if err != nil {
return nil, fmt.Errorf("error loading .env file: %w", err)
}
@@ -1,34 +1,34 @@
package handlers
package handler
import (
"net/http"
"github.com/gin-gonic/gin"
"knowledge-graph-backend/models"
"knowledge-graph-backend/services"
"knowledge-graph-backend/internal/model"
"knowledge-graph-backend/internal/service"
)
// NodeCRUDHandler 节点的增删改处理器
type NodeCRUDHandler struct {
service services.GraphService
service service.GraphService
}
// NewNodeCRUDHandler 创建节点CRUD处理器
func NewNodeCRUDHandler(service services.GraphService) *NodeCRUDHandler {
func NewNodeCRUDHandler(svc service.GraphService) *NodeCRUDHandler {
return &NodeCRUDHandler{
service: service,
service: svc,
}
}
// EdgeCRUDHandler 边的增删改处理器
type EdgeCRUDHandler struct {
service services.GraphService
service service.GraphService
}
// NewEdgeCRUDHandler 创建边CRUD处理器
func NewEdgeCRUDHandler(service services.GraphService) *EdgeCRUDHandler {
func NewEdgeCRUDHandler(svc service.GraphService) *EdgeCRUDHandler {
return &EdgeCRUDHandler{
service: service,
service: svc,
}
}
@@ -37,16 +37,16 @@ func NewEdgeCRUDHandler(service services.GraphService) *EdgeCRUDHandler {
// @Description 在知识图谱中创建一个新节点
// @Accept json
// @Produce json
// @Param request body models.CreateNodeRequest true "节点创建请求"
// @Success 200 {object} models.Node "创建成功"
// @Failure 400 {object} models.ErrorResponse "请求错误"
// @Failure 409 {object} models.ErrorResponse "节点已存在"
// @Failure 500 {object} models.ErrorResponse "内部错误"
// @Param request body model.CreateNodeRequest true "节点创建请求"
// @Success 200 {object} model.Node "创建成功"
// @Failure 400 {object} model.ErrorResponse "请求错误"
// @Failure 409 {object} model.ErrorResponse "节点已存在"
// @Failure 500 {object} model.ErrorResponse "内部错误"
// @Router /api/nodes [post]
func (h *NodeCRUDHandler) CreateNode(c *gin.Context) {
var req models.CreateNodeRequest
var req model.CreateNodeRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, models.ErrorResponse{
c.JSON(http.StatusBadRequest, model.ErrorResponse{
Error: "invalid_request",
Message: err.Error(),
})
@@ -55,7 +55,7 @@ func (h *NodeCRUDHandler) CreateNode(c *gin.Context) {
node, err := h.service.CreateNode(req)
if err != nil {
c.JSON(http.StatusConflict, models.ErrorResponse{
c.JSON(http.StatusConflict, model.ErrorResponse{
Error: "create_failed",
Message: err.Error(),
})
@@ -71,18 +71,18 @@ func (h *NodeCRUDHandler) CreateNode(c *gin.Context) {
// @Accept json
// @Produce json
// @Param id path string true "节点ID"
// @Param request body models.UpdateNodeRequest true "节点更新请求"
// @Success 200 {object} models.Node "更新成功"
// @Failure 400 {object} models.ErrorResponse "请求错误"
// @Failure 404 {object} models.ErrorResponse "节点未找到"
// @Failure 500 {object} models.ErrorResponse "内部错误"
// @Param request body model.UpdateNodeRequest true "节点更新请求"
// @Success 200 {object} model.Node "更新成功"
// @Failure 400 {object} model.ErrorResponse "请求错误"
// @Failure 404 {object} model.ErrorResponse "节点未找到"
// @Failure 500 {object} model.ErrorResponse "内部错误"
// @Router /api/nodes/{id} [put]
func (h *NodeCRUDHandler) UpdateNode(c *gin.Context) {
id := c.Param("id")
var req models.UpdateNodeRequest
var req model.UpdateNodeRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, models.ErrorResponse{
c.JSON(http.StatusBadRequest, model.ErrorResponse{
Error: "invalid_request",
Message: err.Error(),
})
@@ -91,7 +91,7 @@ func (h *NodeCRUDHandler) UpdateNode(c *gin.Context) {
node, err := h.service.UpdateNode(id, req)
if err != nil {
c.JSON(http.StatusNotFound, models.ErrorResponse{
c.JSON(http.StatusNotFound, model.ErrorResponse{
Error: "update_failed",
Message: err.Error(),
})
@@ -106,23 +106,23 @@ func (h *NodeCRUDHandler) UpdateNode(c *gin.Context) {
// @Description 从知识图谱中删除指定节点及其相关的所有边
// @Produce json
// @Param id path string true "节点ID"
// @Success 200 {object} models.DeleteResponse "删除成功"
// @Failure 404 {object} models.ErrorResponse "节点未找到"
// @Failure 500 {object} models.ErrorResponse "内部错误"
// @Success 200 {object} model.DeleteResponse "删除成功"
// @Failure 404 {object} model.ErrorResponse "节点未找到"
// @Failure 500 {object} model.ErrorResponse "内部错误"
// @Router /api/nodes/{id} [delete]
func (h *NodeCRUDHandler) DeleteNode(c *gin.Context) {
id := c.Param("id")
err := h.service.DeleteNode(id)
if err != nil {
c.JSON(http.StatusNotFound, models.ErrorResponse{
c.JSON(http.StatusNotFound, model.ErrorResponse{
Error: "delete_failed",
Message: err.Error(),
})
return
}
c.JSON(http.StatusOK, models.DeleteResponse{
c.JSON(http.StatusOK, model.DeleteResponse{
Success: true,
Message: "节点已成功删除",
ID: id,
@@ -134,17 +134,17 @@ func (h *NodeCRUDHandler) DeleteNode(c *gin.Context) {
// @Description 在知识图谱中创建一个新边(关系)
// @Accept json
// @Produce json
// @Param request body models.CreateEdgeRequest true "边创建请求"
// @Success 200 {object} models.EdgeResponse "创建成功"
// @Failure 400 {object} models.ErrorResponse "请求错误"
// @Failure 404 {object} models.ErrorResponse "源节点或目标节点未找到"
// @Failure 409 {object} models.ErrorResponse "边已存在"
// @Failure 500 {object} models.ErrorResponse "内部错误"
// @Param request body model.CreateEdgeRequest true "边创建请求"
// @Success 200 {object} model.EdgeResponse "创建成功"
// @Failure 400 {object} model.ErrorResponse "请求错误"
// @Failure 404 {object} model.ErrorResponse "源节点或目标节点未找到"
// @Failure 409 {object} model.ErrorResponse "边已存在"
// @Failure 500 {object} model.ErrorResponse "内部错误"
// @Router /api/edges [post]
func (h *EdgeCRUDHandler) CreateEdge(c *gin.Context) {
var req models.CreateEdgeRequest
var req model.CreateEdgeRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, models.ErrorResponse{
c.JSON(http.StatusBadRequest, model.ErrorResponse{
Error: "invalid_request",
Message: err.Error(),
})
@@ -153,7 +153,7 @@ func (h *EdgeCRUDHandler) CreateEdge(c *gin.Context) {
edge, err := h.service.CreateEdge(req)
if err != nil {
c.JSON(http.StatusConflict, models.ErrorResponse{
c.JSON(http.StatusConflict, model.ErrorResponse{
Error: "create_failed",
Message: err.Error(),
})
@@ -161,7 +161,7 @@ func (h *EdgeCRUDHandler) CreateEdge(c *gin.Context) {
}
// 转换为响应格式
response := models.EdgeResponse{
response := model.EdgeResponse{
ID: edge.ID,
Source: edge.Source,
Target: edge.Target,
@@ -178,23 +178,23 @@ func (h *EdgeCRUDHandler) CreateEdge(c *gin.Context) {
// @Description 从知识图谱中删除指定的边
// @Produce json
// @Param id path string true "边ID"
// @Success 200 {object} models.DeleteResponse "删除成功"
// @Failure 404 {object} models.ErrorResponse "边未找到"
// @Failure 500 {object} models.ErrorResponse "内部错误"
// @Success 200 {object} model.DeleteResponse "删除成功"
// @Failure 404 {object} model.ErrorResponse "边未找到"
// @Failure 500 {object} model.ErrorResponse "内部错误"
// @Router /api/edges/{id} [delete]
func (h *EdgeCRUDHandler) DeleteEdge(c *gin.Context) {
edgeID := c.Param("id")
err := h.service.DeleteEdge(edgeID)
if err != nil {
c.JSON(http.StatusNotFound, models.ErrorResponse{
c.JSON(http.StatusNotFound, model.ErrorResponse{
Error: "delete_failed",
Message: err.Error(),
})
return
}
c.JSON(http.StatusOK, models.DeleteResponse{
c.JSON(http.StatusOK, model.DeleteResponse{
Success: true,
Message: "边已成功删除",
ID: edgeID,
@@ -1,27 +1,27 @@
package handlers
package handler
import (
"net/http"
"github.com/gin-gonic/gin"
"knowledge-graph-backend/services"
"knowledge-graph-backend/internal/service"
)
type GraphHandler struct {
service services.GraphService
service service.GraphService
}
func NewGraphHandler(service services.GraphService) *GraphHandler {
func NewGraphHandler(svc service.GraphService) *GraphHandler {
return &GraphHandler{
service: service,
service: svc,
}
}
// @Summary 获取图数据
// @Description 获取知识图谱的全部节点和边数据
// @Produce json
// @Success 200 {object} models.GraphData "成功"
// @Failure 500 {object} models.ErrorResponse "内部错误"
// @Success 200 {object} model.GraphData "成功"
// @Failure 500 {object} model.ErrorResponse "内部错误"
// @Router /api/graph [get]
func (h *GraphHandler) GetGraphData(c *gin.Context) {
data := h.service.GetGraphData()
@@ -32,7 +32,7 @@ func (h *GraphHandler) GetGraphData(c *gin.Context) {
// @Description 获取知识图谱的节点数、边数等统计信息
// @Produce json
// @Success 200 {object} map[string]interface{} "成功"
// @Failure 500 {object} models.ErrorResponse "内部错误"
// @Failure 500 {object} model.ErrorResponse "内部错误"
// @Router /api/graph/stats [get]
func (h *GraphHandler) GetStats(c *gin.Context) {
stats := h.service.GetStats()
@@ -42,8 +42,8 @@ func (h *GraphHandler) GetStats(c *gin.Context) {
// @Summary 获取简化图数据
// @Description 获取知识图谱的全部节点和边数据(仅保留核心信息,适合LLM处理)
// @Produce json
// @Success 200 {object} models.SimpleGraphData "成功"
// @Failure 500 {object} models.ErrorResponse "内部错误"
// @Success 200 {object} model.SimpleGraphData "成功"
// @Failure 500 {object} model.ErrorResponse "内部错误"
// @Router /api/graph/simpleJson [get]
func (h *GraphHandler) GetSimpleGraphData(c *gin.Context) {
data := h.service.GetSimpleGraphData()
@@ -1,19 +1,19 @@
package handlers
package handler
import (
"net/http"
"github.com/gin-gonic/gin"
"knowledge-graph-backend/services"
"knowledge-graph-backend/internal/service"
)
type NodeHandler struct {
service services.GraphService
service service.GraphService
}
func NewNodeHandler(service services.GraphService) *NodeHandler {
func NewNodeHandler(svc service.GraphService) *NodeHandler {
return &NodeHandler{
service: service,
service: svc,
}
}
@@ -21,10 +21,10 @@ func NewNodeHandler(service services.GraphService) *NodeHandler {
// @Description 根据节点 ID 获取知识图谱中的节点详细信息
// @Produce json
// @Param id path string true "节点 ID"
// @Success 200 {object} models.NodeResponse "成功"
// @Failure 400 {object} models.ErrorResponse "请求错误"
// @Failure 404 {object} models.ErrorResponse "节点未找到"
// @Failure 500 {object} models.ErrorResponse "内部错误"
// @Success 200 {object} model.NodeResponse "成功"
// @Failure 400 {object} model.ErrorResponse "请求错误"
// @Failure 404 {object} model.ErrorResponse "节点未找到"
// @Failure 500 {object} model.ErrorResponse "内部错误"
// @Router /api/nodes/{id} [get]
func (h *NodeHandler) GetNodeByID(c *gin.Context) {
nodeID := c.Param("id")
@@ -52,10 +52,10 @@ func (h *NodeHandler) GetNodeByID(c *gin.Context) {
// @Description 根据节点 ID 获取其所有邻居节点及关联边
// @Produce json
// @Param id path string true "节点 ID"
// @Success 200 {object} models.NeighborResponse "成功"
// @Failure 400 {object} models.ErrorResponse "请求错误"
// @Failure 404 {object} models.ErrorResponse "节点未找到"
// @Failure 500 {object} models.ErrorResponse "内部错误"
// @Success 200 {object} model.NeighborResponse "成功"
// @Failure 400 {object} model.ErrorResponse "请求错误"
// @Failure 404 {object} model.ErrorResponse "节点未找到"
// @Failure 500 {object} model.ErrorResponse "内部错误"
// @Router /api/nodes/{id}/neighbors [get]
func (h *NodeHandler) GetNeighbors(c *gin.Context) {
nodeID := c.Param("id")
@@ -1,19 +1,19 @@
package handlers
package handler
import (
"net/http"
"github.com/gin-gonic/gin"
"knowledge-graph-backend/services"
"knowledge-graph-backend/internal/service"
)
type SearchHandler struct {
service services.GraphService
service service.GraphService
}
func NewSearchHandler(service services.GraphService) *SearchHandler {
func NewSearchHandler(svc service.GraphService) *SearchHandler {
return &SearchHandler{
service: service,
service: svc,
}
}
@@ -21,9 +21,9 @@ func NewSearchHandler(service services.GraphService) *SearchHandler {
// @Description 根据关键词搜索知识图谱中的节点
// @Produce json
// @Param q query string true "搜索关键词"
// @Success 200 {object} models.SearchResponse "成功"
// @Failure 400 {object} models.ErrorResponse "请求错误"
// @Failure 500 {object} models.ErrorResponse "内部错误"
// @Success 200 {object} model.SearchResponse "成功"
// @Failure 400 {object} model.ErrorResponse "请求错误"
// @Failure 500 {object} model.ErrorResponse "内部错误"
// @Router /api/search [get]
func (h *SearchHandler) SearchNodes(c *gin.Context) {
query := c.Query("q")
@@ -1,25 +1,28 @@
package models
package model
// Node represents a graph node
type Node struct {
ID string `json:"id"`
Label string `json:"label"`
Type string `json:"type,omitempty"`
Properties map[string]interface{} `json:"properties,omitempty"`
X float64 `json:"x,omitempty"`
Y float64 `json:"y,omitempty"`
Style map[string]interface{} `json:"style,omitempty"`
Properties map[string]interface{} `json:"properties,omitempty"`
}
// Edge represents a graph edge
type Edge struct {
ID string `json:"id"`
Source string `json:"source"`
Target string `json:"target"`
Label string `json:"label,omitempty"`
Type string `json:"type,omitempty"`
Properties map[string]interface{} `json:"properties,omitempty"`
Style map[string]interface{} `json:"style,omitempty"`
Properties map[string]interface{} `json:"properties,omitempty"`
}
// GraphData represents the complete graph structure
type GraphData struct {
Nodes []Node `json:"nodes"`
Edges []Edge `json:"edges"`
@@ -45,3 +48,43 @@ type SimpleGraphData struct {
Nodes []SimpleNode `json:"nodes"`
Edges []SimpleEdge `json:"edges"`
}
// StatsResponse represents graph statistics
type StatsResponse struct {
TotalNodes int `json:"totalNodes"`
TotalEdges int `json:"totalEdges"`
ConceptNodes int `json:"conceptNodes,omitempty"`
ToolNodes int `json:"toolNodes,omitempty"`
ApplicationNodes int `json:"applicationNodes,omitempty"`
}
// NeighborResponse represents a node's neighbors and related edges
type NeighborResponse struct {
Nodes []Node `json:"nodes"`
Edges []Edge `json:"edges"`
}
// NodeResponse represents a node detail response
type NodeResponse struct {
ID string `json:"id"`
Label string `json:"label"`
Type string `json:"type,omitempty"`
X float64 `json:"x,omitempty"`
Y float64 `json:"y,omitempty"`
Style map[string]interface{} `json:"style,omitempty"`
Properties map[string]interface{} `json:"properties,omitempty"`
Neighbors []Node `json:"neighbors,omitempty"`
}
// SearchResponse represents search results
type SearchResponse struct {
Count int `json:"count"`
Query string `json:"query"`
Nodes []Node `json:"nodes"`
}
// ErrorResponse represents an error response
type ErrorResponse struct {
Error string `json:"error"`
Message string `json:"message"`
}
+12
View File
@@ -0,0 +1,12 @@
package model
// NodeInfo represents detailed node information
type NodeInfo struct {
ID string `json:"id"`
Label string `json:"label"`
Type string `json:"type"`
X float64 `json:"x,omitempty"`
Y float64 `json:"y,omitempty"`
Properties map[string]interface{} `json:"properties,omitempty"`
Neighbors []Node `json:"neighbors,omitempty"`
}
+47
View File
@@ -0,0 +1,47 @@
package model
// CreateNodeRequest creates a new node
type CreateNodeRequest struct {
ID string `json:"id" binding:"required" example:"node_123"`
Label string `json:"label" binding:"required" example:"人工智能"`
Type string `json:"type" binding:"required" example:"概念"`
X float64 `json:"x" example:"100"`
Y float64 `json:"y" example:"200"`
Properties map[string]interface{} `json:"properties,omitempty"`
}
// UpdateNodeRequest updates an existing node
type UpdateNodeRequest struct {
Label string `json:"label,omitempty" example:"机器学习"`
Type string `json:"type,omitempty" example:"工具"`
X *float64 `json:"x,omitempty" example:"150"`
Y *float64 `json:"y,omitempty" example:"250"`
Properties map[string]interface{} `json:"properties,omitempty"`
}
// DeleteResponse represents a delete operation response
type DeleteResponse struct {
Success bool `json:"success" example:"true"`
Message string `json:"message" example:"节点已成功删除"`
ID string `json:"id,omitempty" example:"node_123"`
}
// CreateEdgeRequest creates a new edge
type CreateEdgeRequest struct {
ID string `json:"id" binding:"required" example:"edge_123"`
Source string `json:"source" binding:"required" example:"node_1"`
Target string `json:"target" binding:"required" example:"node_2"`
Label string `json:"label" binding:"required" example:"包含"`
Type string `json:"type" example:"CONTAINS"`
Properties map[string]interface{} `json:"properties,omitempty"`
}
// EdgeResponse represents an edge response
type EdgeResponse struct {
ID string `json:"id" example:"edge_123"`
Source string `json:"source" example:"node_1"`
Target string `json:"target" example:"node_2"`
Label string `json:"label" example:"包含"`
Type string `json:"type" example:"CONTAINS"`
Properties map[string]interface{} `json:"properties,omitempty"`
}
@@ -5,7 +5,7 @@ import (
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
"knowledge-graph-backend/config"
"knowledge-graph-backend/internal/config"
)
func NewDriver(cfg config.Neo4jConfig) neo4j.DriverWithContext {
@@ -4,7 +4,7 @@ import (
"context"
"testing"
"knowledge-graph-backend/config"
"knowledge-graph-backend/internal/config"
)
func TestNewDriver(t *testing.T) {
+20
View File
@@ -0,0 +1,20 @@
package service
import "knowledge-graph-backend/internal/model"
type GraphService interface {
GetGraphData() model.GraphData
GetSimpleGraphData() model.SimpleGraphData
GetNodeByID(id string) (model.Node, bool)
SearchNodes(query string) []model.Node
GetNeighbors(nodeID string) (model.NeighborResponse, bool)
GetStats() map[string]int
// 新增增删改接口
CreateNode(req model.CreateNodeRequest) (model.Node, error)
UpdateNode(id string, req model.UpdateNodeRequest) (model.Node, error)
DeleteNode(id string) error
CreateEdge(req model.CreateEdgeRequest) (model.Edge, error)
DeleteEdge(id string) error
}
@@ -1,4 +1,4 @@
package services
package service
import (
"context"
@@ -7,7 +7,7 @@ import (
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
"knowledge-graph-backend/models"
"knowledge-graph-backend/internal/model"
)
type Neo4jService struct {
@@ -18,10 +18,10 @@ func NewNeo4jService(driver neo4j.DriverWithContext) *Neo4jService {
return &Neo4jService{driver: driver}
}
func (s *Neo4jService) GetGraphData() models.GraphData {
func (s *Neo4jService) GetGraphData() model.GraphData {
ctx := context.Background()
var nodes []models.Node
var edges []models.Edge
var nodes []model.Node
var edges []model.Edge
nodeResult, err := neo4j.ExecuteQuery(ctx, s.driver,
"MATCH (n) RETURN n",
@@ -30,7 +30,7 @@ func (s *Neo4jService) GetGraphData() models.GraphData {
)
if err != nil {
fmt.Printf("Error querying nodes: %v\n", err)
return models.GraphData{}
return model.GraphData{}
}
for _, record := range nodeResult.Records {
if v, ok := record.Get("n"); ok {
@@ -47,7 +47,7 @@ func (s *Neo4jService) GetGraphData() models.GraphData {
)
if err != nil {
fmt.Printf("Error querying edges: %v\n", err)
return models.GraphData{Nodes: nodes}
return model.GraphData{Nodes: nodes}
}
for _, record := range edgeResult.Records {
source, _ := record.Get("source")
@@ -65,10 +65,10 @@ func (s *Neo4jService) GetGraphData() models.GraphData {
}
}
return models.GraphData{Nodes: nodes, Edges: edges}
return model.GraphData{Nodes: nodes, Edges: edges}
}
func (s *Neo4jService) GetNodeByID(id string) (models.Node, bool) {
func (s *Neo4jService) GetNodeByID(id string) (model.Node, bool) {
ctx := context.Background()
result, err := neo4j.ExecuteQuery(ctx, s.driver,
"MATCH (n {id: $id}) RETURN n",
@@ -76,18 +76,18 @@ func (s *Neo4jService) GetNodeByID(id string) (models.Node, bool) {
neo4j.EagerResultTransformer,
)
if err != nil || len(result.Records) == 0 {
return models.Node{}, false
return model.Node{}, false
}
v, _ := result.Records[0].Get("n")
if n, ok := v.(neo4j.Node); ok {
return neo4jNodeToModel(n), true
}
return models.Node{}, false
return model.Node{}, false
}
func (s *Neo4jService) SearchNodes(query string) []models.Node {
func (s *Neo4jService) SearchNodes(query string) []model.Node {
if query == "" {
return []models.Node{}
return []model.Node{}
}
ctx := context.Background()
result, err := neo4j.ExecuteQuery(ctx, s.driver,
@@ -100,9 +100,9 @@ func (s *Neo4jService) SearchNodes(query string) []models.Node {
neo4j.EagerResultTransformer,
)
if err != nil {
return []models.Node{}
return []model.Node{}
}
var nodes []models.Node
var nodes []model.Node
for _, record := range result.Records {
v, _ := record.Get("n")
if n, ok := v.(neo4j.Node); ok {
@@ -112,12 +112,12 @@ func (s *Neo4jService) SearchNodes(query string) []models.Node {
return nodes
}
func (s *Neo4jService) GetNeighbors(nodeID string) (models.NeighborResponse, bool) {
func (s *Neo4jService) GetNeighbors(nodeID string) (model.NeighborResponse, bool) {
ctx := context.Background()
_, exists := s.GetNodeByID(nodeID)
if !exists {
return models.NeighborResponse{}, false
return model.NeighborResponse{}, false
}
result, err := neo4j.ExecuteQuery(ctx, s.driver,
@@ -127,11 +127,11 @@ func (s *Neo4jService) GetNeighbors(nodeID string) (models.NeighborResponse, boo
neo4j.EagerResultTransformer,
)
if err != nil {
return models.NeighborResponse{Nodes: []models.Node{}, Edges: []models.Edge{}}, true
return model.NeighborResponse{Nodes: []model.Node{}, Edges: []model.Edge{}}, true
}
neighborMap := make(map[string]models.Node)
edgeMap := make(map[string]models.Edge)
neighborMap := make(map[string]model.Node)
edgeMap := make(map[string]model.Edge)
for _, record := range result.Records {
if v, ok := record.Get("m"); ok {
@@ -159,17 +159,17 @@ func (s *Neo4jService) GetNeighbors(nodeID string) (models.NeighborResponse, boo
}
}
var neighborNodes []models.Node
var neighborNodes []model.Node
for _, n := range neighborMap {
neighborNodes = append(neighborNodes, n)
}
var relatedEdges []models.Edge
var relatedEdges []model.Edge
for _, e := range edgeMap {
relatedEdges = append(relatedEdges, e)
}
return models.NeighborResponse{
return model.NeighborResponse{
Nodes: neighborNodes,
Edges: relatedEdges,
}, true
@@ -216,10 +216,10 @@ func (s *Neo4jService) GetStats() map[string]int {
}
// GetSimpleGraphData 获取简化的图数据,仅保留核心信息,适合 LLM 处理
func (s *Neo4jService) GetSimpleGraphData() models.SimpleGraphData {
func (s *Neo4jService) GetSimpleGraphData() model.SimpleGraphData {
ctx := context.Background()
var nodes []models.SimpleNode
var edges []models.SimpleEdge
var nodes []model.SimpleNode
var edges []model.SimpleEdge
nodeResult, err := neo4j.ExecuteQuery(ctx, s.driver,
"MATCH (n) RETURN n",
@@ -228,13 +228,13 @@ func (s *Neo4jService) GetSimpleGraphData() models.SimpleGraphData {
)
if err != nil {
fmt.Printf("Error querying nodes: %v\n", err)
return models.SimpleGraphData{}
return model.SimpleGraphData{}
}
for _, record := range nodeResult.Records {
if v, ok := record.Get("n"); ok {
if n, ok := v.(neo4j.Node); ok {
props := n.Props
node := models.SimpleNode{
node := model.SimpleNode{
ID: getStr(props, "id"),
Label: getStr(props, "label"),
Type: getStr(props, "type"),
@@ -251,7 +251,7 @@ func (s *Neo4jService) GetSimpleGraphData() models.SimpleGraphData {
)
if err != nil {
fmt.Printf("Error querying edges: %v\n", err)
return models.SimpleGraphData{Nodes: nodes}
return model.SimpleGraphData{Nodes: nodes}
}
for _, record := range edgeResult.Records {
source, _ := record.Get("source")
@@ -259,7 +259,7 @@ func (s *Neo4jService) GetSimpleGraphData() models.SimpleGraphData {
v, _ := record.Get("r")
if rel, ok := v.(neo4j.Relationship); ok {
props := rel.Props
edge := models.SimpleEdge{
edge := model.SimpleEdge{
Source: getStr(props, "source"),
Target: getStr(props, "target"),
Type: rel.Type,
@@ -275,12 +275,12 @@ func (s *Neo4jService) GetSimpleGraphData() models.SimpleGraphData {
}
}
return models.SimpleGraphData{Nodes: nodes, Edges: edges}
return model.SimpleGraphData{Nodes: nodes, Edges: edges}
}
func neo4jNodeToModel(n neo4j.Node) models.Node {
func neo4jNodeToModel(n neo4j.Node) model.Node {
props := n.Props
node := models.Node{
node := model.Node{
ID: getStr(props, "id"),
Label: getStr(props, "label"),
Type: getStr(props, "type"),
@@ -307,9 +307,9 @@ func neo4jNodeToModel(n neo4j.Node) models.Node {
return node
}
func neo4jRelToModel(r neo4j.Relationship) models.Edge {
func neo4jRelToModel(r neo4j.Relationship) model.Edge {
props := r.Props
edge := models.Edge{
edge := model.Edge{
ID: getStr(props, "id"),
Label: getStr(props, "label"),
Type: r.Type,
@@ -365,7 +365,7 @@ func getInt(record *neo4j.Record, key string) int {
}
// CreateNode 创建新节点
func (s *Neo4jService) CreateNode(req models.CreateNodeRequest) (models.Node, error) {
func (s *Neo4jService) CreateNode(req model.CreateNodeRequest) (model.Node, error) {
ctx := context.Background()
// 检查节点是否已存在
@@ -373,10 +373,10 @@ func (s *Neo4jService) CreateNode(req models.CreateNodeRequest) (models.Node, er
checkResult, err := neo4j.ExecuteQuery(ctx, s.driver, checkQuery,
map[string]any{"id": req.ID}, neo4j.EagerResultTransformer)
if err != nil {
return models.Node{}, fmt.Errorf("error checking node existence: %w", err)
return model.Node{}, fmt.Errorf("error checking node existence: %w", err)
}
if len(checkResult.Records) > 0 {
return models.Node{}, fmt.Errorf("node with id %s already exists", req.ID)
return model.Node{}, fmt.Errorf("node with id %s already exists", req.ID)
}
// 构建创建属性
@@ -419,11 +419,11 @@ func (s *Neo4jService) CreateNode(req models.CreateNodeRequest) (models.Node, er
map[string]any{"props": props}, neo4j.EagerResultTransformer)
if err != nil {
fmt.Printf("Error creating node: %v\n", err)
return models.Node{}, fmt.Errorf("failed to create node: %w", err)
return model.Node{}, fmt.Errorf("failed to create node: %w", err)
}
if len(result.Records) == 0 {
return models.Node{}, fmt.Errorf("failed to create node: no result returned")
return model.Node{}, fmt.Errorf("failed to create node: no result returned")
}
v, _ := result.Records[0].Get("n")
@@ -431,11 +431,11 @@ func (s *Neo4jService) CreateNode(req models.CreateNodeRequest) (models.Node, er
return neo4jNodeToModel(n), nil
}
return models.Node{}, fmt.Errorf("unexpected result type while creating node")
return model.Node{}, fmt.Errorf("unexpected result type while creating node")
}
// CreateNodeV2 创建新节点(改进版)
func (s *Neo4jService) CreateNodeV2(req models.CreateNodeRequest) (models.Node, error) {
func (s *Neo4jService) CreateNodeV2(req model.CreateNodeRequest) (model.Node, error) {
ctx := context.Background()
// 先检查节点是否已存在
@@ -443,10 +443,10 @@ func (s *Neo4jService) CreateNodeV2(req models.CreateNodeRequest) (models.Node,
checkResult, err := neo4j.ExecuteQuery(ctx, s.driver, checkQuery,
map[string]any{"id": req.ID}, neo4j.EagerResultTransformer)
if err != nil {
return models.Node{}, err
return model.Node{}, err
}
if len(checkResult.Records) > 0 {
return models.Node{}, fmt.Errorf("node with id %s already exists", req.ID)
return model.Node{}, fmt.Errorf("node with id %s already exists", req.ID)
}
// 构建创建属性
@@ -489,11 +489,11 @@ func (s *Neo4jService) CreateNodeV2(req models.CreateNodeRequest) (models.Node,
map[string]any{"props": props}, neo4j.EagerResultTransformer)
if err != nil {
fmt.Printf("Error creating node: %v\n", err)
return models.Node{}, err
return model.Node{}, err
}
if len(result.Records) == 0 {
return models.Node{}, fmt.Errorf("failed to create node")
return model.Node{}, fmt.Errorf("failed to create node")
}
v, _ := result.Records[0].Get("n")
@@ -501,17 +501,17 @@ func (s *Neo4jService) CreateNodeV2(req models.CreateNodeRequest) (models.Node,
return neo4jNodeToModel(n), nil
}
return models.Node{}, fmt.Errorf("unexpected result type while creating node")
return model.Node{}, fmt.Errorf("unexpected result type while creating node")
}
// UpdateNode 更新节点
func (s *Neo4jService) UpdateNode(id string, req models.UpdateNodeRequest) (models.Node, error) {
func (s *Neo4jService) UpdateNode(id string, req model.UpdateNodeRequest) (model.Node, error) {
ctx := context.Background()
// 检查节点是否存在
_, exists := s.GetNodeByID(id)
if !exists {
return models.Node{}, fmt.Errorf("node with id %s not found", id)
return model.Node{}, fmt.Errorf("node with id %s not found", id)
}
// 构建更新语句
@@ -558,11 +558,11 @@ func (s *Neo4jService) UpdateNode(id string, req models.UpdateNodeRequest) (mode
result, err := neo4j.ExecuteQuery(ctx, s.driver, query, params, neo4j.EagerResultTransformer)
if err != nil {
fmt.Printf("Error updating node: %v\n", err)
return models.Node{}, err
return model.Node{}, err
}
if len(result.Records) == 0 {
return models.Node{}, fmt.Errorf("failed to update node")
return model.Node{}, fmt.Errorf("failed to update node")
}
v, _ := result.Records[0].Get("n")
@@ -570,7 +570,7 @@ func (s *Neo4jService) UpdateNode(id string, req models.UpdateNodeRequest) (mode
return neo4jNodeToModel(n), nil
}
return models.Node{}, fmt.Errorf("unexpected result type while updating node")
return model.Node{}, fmt.Errorf("unexpected result type while updating node")
}
// DeleteNode 删除节点
@@ -611,17 +611,17 @@ func (s *Neo4jService) DeleteNode(id string) error {
}
// CreateEdge 创建新边
func (s *Neo4jService) CreateEdge(req models.CreateEdgeRequest) (models.Edge, error) {
func (s *Neo4jService) CreateEdge(req model.CreateEdgeRequest) (model.Edge, error) {
ctx := context.Background()
// 检查源节点和目标节点是否存在
_, sourceExists := s.GetNodeByID(req.Source)
if !sourceExists {
return models.Edge{}, fmt.Errorf("source node with id %s not found", req.Source)
return model.Edge{}, fmt.Errorf("source node with id %s not found", req.Source)
}
_, targetExists := s.GetNodeByID(req.Target)
if !targetExists {
return models.Edge{}, fmt.Errorf("target node with id %s not found", req.Target)
return model.Edge{}, fmt.Errorf("target node with id %s not found", req.Target)
}
// 构建创建属性
@@ -663,11 +663,11 @@ func (s *Neo4jService) CreateEdge(req models.CreateEdgeRequest) (models.Edge, er
result, err := neo4j.ExecuteQuery(ctx, s.driver, query, params, neo4j.EagerResultTransformer)
if err != nil {
fmt.Printf("Error creating edge: %v\n", err)
return models.Edge{}, err
return model.Edge{}, err
}
if len(result.Records) == 0 {
return models.Edge{}, fmt.Errorf("failed to create edge")
return model.Edge{}, fmt.Errorf("failed to create edge")
}
v, _ := result.Records[0].Get("r")
@@ -678,7 +678,7 @@ func (s *Neo4jService) CreateEdge(req models.CreateEdgeRequest) (models.Edge, er
return edge, nil
}
return models.Edge{}, fmt.Errorf("unexpected result type while creating edge")
return model.Edge{}, fmt.Errorf("unexpected result type while creating edge")
}
// DeleteEdge 删除边
-23
View File
@@ -1,23 +0,0 @@
package models
type NodeResponse struct {
ID string `json:"id" example:"1"`
Label string `json:"label" example:"人工智能"`
Type string `json:"type,omitempty" example:"概念"`
Properties map[string]interface{} `json:"properties,omitempty"`
}
type NeighborResponse struct {
Nodes []Node `json:"nodes"`
Edges []Edge `json:"edges"`
}
type SearchResponse struct {
Results []Node `json:"results"`
Count int `json:"count"`
}
type ErrorResponse struct {
Error string `json:"error"`
Message string `json:"message"`
}
-47
View File
@@ -1,47 +0,0 @@
package models
// CreateNodeRequest 创建节点的请求结构
type CreateNodeRequest struct {
ID string `json:"id" binding:"required" example:"node_123"` // 节点唯一标识
Label string `json:"label" binding:"required" example:"人工智能"` // 节点显示标签
Type string `json:"type" binding:"required" example:"概念"` // 节点类型
X float64 `json:"x" example:"100"` // X坐标(可选)
Y float64 `json:"y" example:"200"` // Y坐标(可选)
Properties map[string]interface{} `json:"properties,omitempty"` // 自定义属性
}
// UpdateNodeRequest 更新节点的请求结构
type UpdateNodeRequest struct {
Label string `json:"label,omitempty" example:"机器学习"` // 节点显示标签
Type string `json:"type,omitempty" example:"工具"` // 节点类型
X *float64 `json:"x,omitempty" example:"150"` // X坐标
Y *float64 `json:"y,omitempty" example:"250"` // Y坐标
Properties map[string]interface{} `json:"properties,omitempty"` // 自定义属性(更新)
}
// DeleteResponse 删除操作的响应结构
type DeleteResponse struct {
Success bool `json:"success" example:"true"` // 是否成功
Message string `json:"message" example:"节点已成功删除"` // 消息
ID string `json:"id,omitempty" example:"node_123"` // 被删除的实体ID(可选)
}
// CreateEdgeRequest 创建边的请求结构
type CreateEdgeRequest struct {
ID string `json:"id" binding:"required" example:"edge_123"` // 边的唯一标识
Source string `json:"source" binding:"required" example:"node_1"` // 源节点ID
Target string `json:"target" binding:"required" example:"node_2"` // 目标节点ID
Label string `json:"label" binding:"required" example:"包含"` // 边的显示标签
Type string `json:"type" example:"CONTAINS"` // 边的类型(可选,默认为关系类型)
Properties map[string]interface{} `json:"properties,omitempty"` // 自定义属性
}
// EdgeResponse 边的响应结构
type EdgeResponse struct {
ID string `json:"id" example:"edge_123"` // 边的ID
Source string `json:"source" example:"node_1"` // 源节点ID
Target string `json:"target" example:"node_2"` // 目标节点ID
Label string `json:"label" example:"包含"` // 边的显示标签
Type string `json:"type" example:"CONTAINS"` // 边的类型
Properties map[string]interface{} `json:"properties,omitempty"` // 自定义属性
}
-161
View File
@@ -1,161 +0,0 @@
package services
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"os"
"strings"
"sync"
"knowledge-graph-backend/models"
)
type DataService struct {
data models.GraphData
mutex sync.RWMutex
filePath string
}
func NewDataService(filePath string) (*DataService, error) {
ds := &DataService{
filePath: filePath,
mutex: sync.RWMutex{},
}
if err := ds.loadData(); err != nil {
return nil, fmt.Errorf("failed to load data: %w", err)
}
return ds, nil
}
func (ds *DataService) loadData() error {
ds.mutex.Lock()
defer ds.mutex.Unlock()
file, err := os.Open(ds.filePath)
if err != nil {
return fmt.Errorf("failed to open data file: %w", err)
}
defer file.Close()
byteValue, err := ioutil.ReadAll(file)
if err != nil {
return fmt.Errorf("failed to read data file: %w", err)
}
if err := json.Unmarshal(byteValue, &ds.data); err != nil {
return fmt.Errorf("failed to parse data file: %w", err)
}
log.Printf("Loaded %d nodes and %d edges from %s",
len(ds.data.Nodes), len(ds.data.Edges), ds.filePath)
return nil
}
func (ds *DataService) GetGraphData() models.GraphData {
ds.mutex.RLock()
defer ds.mutex.RUnlock()
return ds.data
}
func (ds *DataService) GetNodeByID(id string) (models.Node, bool) {
ds.mutex.RLock()
defer ds.mutex.RUnlock()
for _, node := range ds.data.Nodes {
if node.ID == id {
return node, true
}
}
return models.Node{}, false
}
func (ds *DataService) SearchNodes(query string) []models.Node {
ds.mutex.RLock()
defer ds.mutex.RUnlock()
if query == "" {
return []models.Node{}
}
searchLower := strings.ToLower(query)
var results []models.Node
for _, node := range ds.data.Nodes {
labelMatch := strings.Contains(strings.ToLower(node.Label), searchLower)
idMatch := strings.Contains(strings.ToLower(node.ID), searchLower)
typeMatch := node.Type != "" && strings.Contains(strings.ToLower(node.Type), searchLower)
if labelMatch || idMatch || typeMatch {
results = append(results, node)
}
}
return results
}
func (ds *DataService) GetNeighbors(nodeID string) (models.NeighborResponse, bool) {
ds.mutex.RLock()
defer ds.mutex.RUnlock()
_, exists := ds.GetNodeByID(nodeID)
if !exists {
return models.NeighborResponse{}, false
}
var neighborIDs []string
var relatedEdges []models.Edge
for _, edge := range ds.data.Edges {
if edge.Source == nodeID {
neighborIDs = append(neighborIDs, edge.Target)
relatedEdges = append(relatedEdges, edge)
} else if edge.Target == nodeID {
neighborIDs = append(neighborIDs, edge.Source)
relatedEdges = append(relatedEdges, edge)
}
}
var neighborNodes []models.Node
for _, node := range ds.data.Nodes {
for _, neighborID := range neighborIDs {
if node.ID == neighborID {
neighborNodes = append(neighborNodes, node)
break
}
}
}
return models.NeighborResponse{
Nodes: neighborNodes,
Edges: relatedEdges,
}, true
}
func (ds *DataService) ReloadData() error {
return ds.loadData()
}
func (ds *DataService) GetStats() map[string]int {
ds.mutex.RLock()
defer ds.mutex.RUnlock()
typeCounts := make(map[string]int)
for _, node := range ds.data.Nodes {
if node.Type != "" {
typeCounts[node.Type]++
}
}
return map[string]int{
"totalNodes": len(ds.data.Nodes),
"totalEdges": len(ds.data.Edges),
"conceptNodes": typeCounts["概念"],
"toolNodes": typeCounts["工具"],
"applicationNodes": typeCounts["应用"],
}
}
-20
View File
@@ -1,20 +0,0 @@
package services
import "knowledge-graph-backend/models"
type GraphService interface {
GetGraphData() models.GraphData
GetSimpleGraphData() models.SimpleGraphData
GetNodeByID(id string) (models.Node, bool)
SearchNodes(query string) []models.Node
GetNeighbors(nodeID string) (models.NeighborResponse, bool)
GetStats() map[string]int
// 新增增删改接口
CreateNode(req models.CreateNodeRequest) (models.Node, error)
UpdateNode(id string, req models.UpdateNodeRequest) (models.Node, error)
DeleteNode(id string) error
CreateEdge(req models.CreateEdgeRequest) (models.Edge, error)
DeleteEdge(id string) error
}