refactor: 重构neo4j服务
This commit is contained in:
@@ -0,0 +1,194 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
|
||||
|
||||
"knowledge-graph-backend/internal/model"
|
||||
)
|
||||
|
||||
func (s *Neo4jService) GetGraphData() model.GraphData {
|
||||
ctx := context.Background()
|
||||
var nodes []model.Node
|
||||
var edges []model.Edge
|
||||
|
||||
nodeResult, err := neo4j.ExecuteQuery(ctx, s.driver,
|
||||
"MATCH (n) RETURN n",
|
||||
map[string]any{},
|
||||
neo4j.EagerResultTransformer,
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Printf("Error querying nodes: %v\n", err)
|
||||
return model.GraphData{}
|
||||
}
|
||||
for _, record := range nodeResult.Records {
|
||||
if v, ok := record.Get("n"); ok {
|
||||
if n, ok := v.(neo4j.Node); ok {
|
||||
nodes = append(nodes, neo4jNodeToModel(n))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
edgeResult, err := neo4j.ExecuteQuery(ctx, s.driver,
|
||||
"MATCH (a)-[r]->(b) RETURN a.id AS source, b.id AS target, r",
|
||||
map[string]any{},
|
||||
neo4j.EagerResultTransformer,
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Printf("Error querying edges: %v\n", err)
|
||||
return model.GraphData{Nodes: nodes}
|
||||
}
|
||||
for _, record := range edgeResult.Records {
|
||||
source, _ := record.Get("source")
|
||||
target, _ := record.Get("target")
|
||||
v, _ := record.Get("r")
|
||||
if rel, ok := v.(neo4j.Relationship); ok {
|
||||
edge := neo4jRelToModel(rel)
|
||||
if s, ok := source.(string); ok {
|
||||
edge.Source = s
|
||||
}
|
||||
if t, ok := target.(string); ok {
|
||||
edge.Target = t
|
||||
}
|
||||
edges = append(edges, edge)
|
||||
}
|
||||
}
|
||||
|
||||
return model.GraphData{Nodes: nodes, Edges: edges}
|
||||
}
|
||||
|
||||
func (s *Neo4jService) GetNodeByID(id string) (model.Node, bool) {
|
||||
node, found, err := s.fetchNodeByID(id)
|
||||
if err != nil || !found {
|
||||
return model.Node{}, false
|
||||
}
|
||||
return node, true
|
||||
}
|
||||
|
||||
func (s *Neo4jService) SearchNodes(query string) []model.Node {
|
||||
if query == "" {
|
||||
return []model.Node{}
|
||||
}
|
||||
ctx := context.Background()
|
||||
result, err := neo4j.ExecuteQuery(ctx, s.driver,
|
||||
`MATCH (n)
|
||||
WHERE toLower(n.label) CONTAINS toLower($query)
|
||||
OR toLower(n.id) CONTAINS toLower($query)
|
||||
OR (n.type IS NOT NULL AND toLower(n.type) CONTAINS toLower($query))
|
||||
RETURN n`,
|
||||
map[string]any{"query": query},
|
||||
neo4j.EagerResultTransformer,
|
||||
)
|
||||
if err != nil {
|
||||
return []model.Node{}
|
||||
}
|
||||
var nodes []model.Node
|
||||
for _, record := range result.Records {
|
||||
v, _ := record.Get("n")
|
||||
if n, ok := v.(neo4j.Node); ok {
|
||||
nodes = append(nodes, neo4jNodeToModel(n))
|
||||
}
|
||||
}
|
||||
return nodes
|
||||
}
|
||||
|
||||
func (s *Neo4jService) GetNeighbors(nodeID string) (model.NeighborResponse, bool) {
|
||||
ctx := context.Background()
|
||||
|
||||
if _, exists := s.GetNodeByID(nodeID); !exists {
|
||||
return model.NeighborResponse{}, false
|
||||
}
|
||||
|
||||
result, err := neo4j.ExecuteQuery(ctx, s.driver,
|
||||
`MATCH ({id: $id})-[r]-(m)
|
||||
RETURN m, r, startNode(r).id AS source, endNode(r).id AS target`,
|
||||
map[string]any{"id": nodeID},
|
||||
neo4j.EagerResultTransformer,
|
||||
)
|
||||
if err != nil {
|
||||
return model.NeighborResponse{Nodes: []model.Node{}, Edges: []model.Edge{}}, true
|
||||
}
|
||||
|
||||
neighborMap := make(map[string]model.Node)
|
||||
edgeMap := make(map[string]model.Edge)
|
||||
|
||||
for _, record := range result.Records {
|
||||
if v, ok := record.Get("m"); ok {
|
||||
if n, ok := v.(neo4j.Node); ok {
|
||||
modelNode := neo4jNodeToModel(n)
|
||||
neighborMap[modelNode.ID] = modelNode
|
||||
}
|
||||
}
|
||||
|
||||
if v, ok := record.Get("r"); ok {
|
||||
if rel, ok := v.(neo4j.Relationship); ok {
|
||||
edge := neo4jRelToModel(rel)
|
||||
if source, ok := record.Get("source"); ok {
|
||||
if s, ok := source.(string); ok {
|
||||
edge.Source = s
|
||||
}
|
||||
}
|
||||
if target, ok := record.Get("target"); ok {
|
||||
if t, ok := target.(string); ok {
|
||||
edge.Target = t
|
||||
}
|
||||
}
|
||||
edgeMap[edge.ID] = edge
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var neighborNodes []model.Node
|
||||
for _, n := range neighborMap {
|
||||
neighborNodes = append(neighborNodes, n)
|
||||
}
|
||||
|
||||
var relatedEdges []model.Edge
|
||||
for _, e := range edgeMap {
|
||||
relatedEdges = append(relatedEdges, e)
|
||||
}
|
||||
|
||||
return model.NeighborResponse{Nodes: neighborNodes, Edges: relatedEdges}, true
|
||||
}
|
||||
|
||||
func (s *Neo4jService) GetStats() map[string]int {
|
||||
ctx := context.Background()
|
||||
result, err := neo4j.ExecuteQuery(ctx, s.driver,
|
||||
`MATCH (n)
|
||||
RETURN count(n) AS totalNodes,
|
||||
sum(CASE WHEN n.type = '概念' THEN 1 ELSE 0 END) AS conceptNodes,
|
||||
sum(CASE WHEN n.type = '工具' THEN 1 ELSE 0 END) AS toolNodes,
|
||||
sum(CASE WHEN n.type = '应用' THEN 1 ELSE 0 END) AS applicationNodes`,
|
||||
map[string]any{},
|
||||
neo4j.EagerResultTransformer,
|
||||
)
|
||||
if err != nil || len(result.Records) == 0 {
|
||||
return map[string]int{}
|
||||
}
|
||||
|
||||
record := result.Records[0]
|
||||
totalNodes := getInt(record, "totalNodes")
|
||||
conceptNodes := getInt(record, "conceptNodes")
|
||||
toolNodes := getInt(record, "toolNodes")
|
||||
applicationNodes := getInt(record, "applicationNodes")
|
||||
|
||||
totalEdges := 0
|
||||
edgeResult, err := neo4j.ExecuteQuery(ctx, s.driver,
|
||||
"MATCH ()-[r]->() RETURN count(r) AS totalEdges",
|
||||
map[string]any{},
|
||||
neo4j.EagerResultTransformer,
|
||||
)
|
||||
if err == nil && len(edgeResult.Records) > 0 {
|
||||
totalEdges = getInt(edgeResult.Records[0], "totalEdges")
|
||||
}
|
||||
|
||||
return map[string]int{
|
||||
"totalNodes": totalNodes,
|
||||
"totalEdges": totalEdges,
|
||||
"conceptNodes": conceptNodes,
|
||||
"toolNodes": toolNodes,
|
||||
"applicationNodes": applicationNodes,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user