Neo4j Cypher:只有存在末端节点时才创建关系

问题描述:

建立在此similar question上,我想要最高效的方式来处理这种情况。Neo4j Cypher:只有存在末端节点时才创建关系

MERGE (n1{id:<uuid>}) 
SET n1.topicID = <unique_name1> 
IF (EXISTS((a:Topic{id:<unique_name1>})) | CREATE UNIQUE (n1)-[:HAS]->(a)) 

MERGE (n2{id:<uuid>}) 
SET n2.topicID = <unique_name2> 
IF (EXISTS((a:Topic{id:<unique_name2>})) | CREATE UNIQUE (n2)-[:HAS]->(a)) 

不幸的是,IF不存在,EXISTS不能用于匹配或找到唯一的节点。

  • 我不能使用可选的匹配,因为那时的CREATE UNIQUE将抛出一个空的异常(就像我希望它会忽略空参数)
  • 我不能使用MATCH,因为如果没有按主题不存在,我会放松我所有的行。
  • 我不能使用MERGE,因为如果它不存在,我不想创建该节点。
  • 我无法使用APOC,因为我不能保证它可以在我们的Neo4j服务器上使用。

最好的解决方案我现在所拥有的是

MERGE (a:TEST{id:1}) 
WITH a 
OPTIONAL MATCH (b:TEST{id:2}) 
// collect b so that there are no nulls, and rows aren't lost when no match 
WITH a, collect(b) AS c 
FOREACH(n IN c | CREATE UNIQUE (a)-[:HAS]->(n)) 
RETURN a 

然而,这似乎有点复杂,需要2点WITH作什么本质上是CREATE UNIQUE RELATION if start and end node exist(并在该计划有一个渴望)。有没有可能做得更好? (使用暗号3.1)

可以简化颇有几分:

MERGE (a:TEST{id:1}) 
WITH a 
MATCH (b:TEST{id:2}) 
CREATE UNIQUE (a)-[:HAS]->(b) 
RETURN a; 

(单个)WITH子句用于查询分成2个“子查询”。

因此,如果MATCH子查询失败,它只会中止自己的子查询(以及后续的子查询),但不会回滚先前成功的MERGE子查询。

但是,请注意,每当最终的子查询失败时,RETURN子句将不会返回任何内容。你将不得不确定这是否可以接受。

因为上述RETURN子句只会返回一些东西,如果b存在,它可能更有意义的是它返回b,或路径。这里是后者的一个例子(即使路径已经存在,p也会被分配一个值):

MERGE (a:TEST{id:1}) 
WITH a 
MATCH (b:TEST{id:2}) 
CREATE UNIQUE p=(a)-[:HAS]->(b) 
RETURN p;