yuchengwei 5 місяців тому
батько
коміт
ab84803067

+ 60 - 28
src/main/java/com/qizhen/healsphere/repository/neo4j/BaseNodeRepository.java

@@ -10,6 +10,7 @@ import org.neo4j.driver.v1.Session;
 import org.neo4j.driver.v1.StatementResult;
 import org.neo4j.driver.v1.Values;
 import org.neo4j.driver.v1.types.Node;
+import org.neo4j.driver.v1.types.Relationship;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Repository;
 
@@ -190,36 +191,67 @@ public class BaseNodeRepository {
      */
     public Map<String, Object> mergeNode(MergeNodeParam mergeNodeParam) {
 
-        String query = String.format("MATCH (a:`%s`), (b:`%s`)\n" +
-                "WHERE id(a) = $firstId AND id(b) = $secondId\n" +
-                "// 创建一个新的节点 MergedNode 并合并属性\n" +
-                "MERGE (m:`%s` {name: $newName})\n" +
-                "// 合并节点 A 和节点 B 的所有关系到新的节点\n" +
-                "// 从 A 到其他节点的关系\n" +
-                "WITH a, b, m\n" +
-                "MATCH (a)-[rA]->(target)\n" +
-                "MERGE (m)-[rAMerged]->(target)\n" +
-                "SET rAMerged = rA\n" +
-                "\n" +
-                "// 从 B 到其他节点的关系\n" +
-                "MATCH (b)-[rB]->(target2)\n" +
-                "MERGE (m)-[rBMerged]->(target2)\n" +
-                "SET rBMerged = rB\n" +
-                "\n" +
-                "// 删除原有的两个节点\n" +
-                "WITH m, a, b\n" +
-                "DETACH DELETE a, b\n" +
-                "RETURN m\n", mergeNodeParam.getFirstLabel(), mergeNodeParam.getSecondLabel(), mergeNodeParam.getNewLabel());
-
         try(Session session = neo4jUtil.getSession()) {
-            StatementResult result = session.run(query,Values.parameters("firstId", mergeNodeParam.getFirstId(),"secondId", mergeNodeParam.getSecondId(),"newName", mergeNodeParam.getNewName()));
-            Map<String,Object> map = new HashMap<>();
-            if(result.hasNext()) {
-                Node node = result.single().get("m").asNode();
-                map.put("id", node.id());
-                map.put("labels", node.labels());
-                map.put("properties", node.asMap());
+            // 找到要合并的两个节点
+            String firstQuery = String.format("MATCH (a:`%s`) WHERE id(a) = $firstId RETURN a", mergeNodeParam.getFirstLabel());
+            String secondQuery = String.format("MATCH (b:`%s`) WHERE id(b) = $secondId RETURN b", mergeNodeParam.getSecondLabel());
+            StatementResult aResult = session.run(firstQuery,Values.parameters("firstId", mergeNodeParam.getFirstId()));
+            Record aRecord = aResult.single();
+            Node a = aRecord.get("a").asNode();
+            StatementResult bResult = session.run(secondQuery,Values.parameters("secondId", mergeNodeParam.getSecondId()));
+            Record bRecord = bResult.single();
+            Node b = bRecord.get("b").asNode();
+
+            // 创建新节点
+            Map<String, Object> newNodeProps = new HashMap<>();
+            newNodeProps.put("name", mergeNodeParam.getNewName());
+            // 合并属性
+            for (String key : a.keys()) {
+                newNodeProps.put(key, a.get(key).asObject());
+            }
+            for (String key : b.keys()) {
+                if (!newNodeProps.containsKey(key)) {
+                    newNodeProps.put(key, b.get(key).asObject());
+                }
             }
+            StatementResult newNodeResult = session.run(String.format("MERGE (n:`%s` $props) RETURN n", mergeNodeParam.getNewLabel()), Values.parameters("props", newNodeProps));
+            Node newNode = newNodeResult.single().get("n").asNode();
+            long newNodeId = newNode.id();
+
+            // 合并关系
+            String firstRelationQuery = String.format("MATCH (a:`%s`)-[aR]-(aOther) WHERE id(a) = $firstId RETURN a,aR,aOther", mergeNodeParam.getFirstLabel());
+            String secondRelationQuery = String.format("MATCH (b:`%s`)-[bR]-(bOther) WHERE id(b) = $secondId RETURN b,bR,bOther", mergeNodeParam.getSecondLabel());
+            StatementResult aRelationResult = session.run(firstRelationQuery,Values.parameters("firstId", mergeNodeParam.getFirstId()));
+            StatementResult bRelationResult = session.run(secondRelationQuery,Values.parameters("secondId", mergeNodeParam.getSecondId()));
+            while (aRelationResult.hasNext()) {
+                Record record = aRelationResult.next();
+                Relationship relationship = record.get("aR").asRelationship();
+                String relType = relationship.type();
+                Node aOtherNode = record.get("aOther").asNode();
+                session.run("MATCH (a), (other) WHERE id(a) = $newNodeId and id(other) = $otherId " +
+                                "MERGE (a)-[newRel:$relType]->(other) SET newRel = $relProps",
+                        Values.parameters("newNodeId", newNodeId,"otherId", aOtherNode.id(), "relType", relType, "relProps", relationship.asMap()));
+
+            }
+            while (bRelationResult.hasNext()) {
+                Record record = aRelationResult.next();
+                Relationship relationship = record.get("bR").asRelationship();
+                String relType = relationship.type();
+                Node bOtherNode = record.get("bOther").asNode();
+                session.run("MATCH (a), (other) WHERE id(a) = $newNodeId and id(other) = $otherId " +
+                                "MERGE (a)-[newRel:$relType]->(other) SET newRel = $relProps",
+                        Values.parameters("newNodeId", newNodeId,"otherId", bOtherNode.id(), "relType", relType, "relProps", relationship.asMap()));
+
+            }
+
+            // 删除原始节点
+            session.run(String.format("MATCH (a:`%s`) WHERE id(a) = $firstId  DETACH DELETE a", mergeNodeParam.getFirstLabel()),Values.parameters("firstId", mergeNodeParam.getFirstId()));
+            session.run(String.format("MATCH (a:`%s`) WHERE id(a) = $secondId  DETACH DELETE a", mergeNodeParam.getSecondLabel()),Values.parameters("secondId", mergeNodeParam.getSecondId()));
+
+            Map<String,Object> map = new HashMap<>();
+            map.put("id", newNode.id());
+            map.put("labels", newNode.labels());
+            map.put("properties", newNode.asMap());
             return map;
         }
     }