Neo4j Cypher:仅在终端节点存在时才创建关系

时间:2017-05-24 18:29:09

标签: neo4j cypher

在此similar question的基础上,我希望以最高效的方式处理这种情况。

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不能用于匹配或找到唯一的节点。

  • 我无法使用OPTIONAL MATCH,因为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 s才能实现CREATE UNIQUE RELATION if start and end node exist(并且在计划中有一个渴望)。有可能做得更好吗? (使用Cypher 3.1)

1 个答案:

答案 0 :(得分:1)

你可以简化一下:

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

(单个)WITH子句用于将查询拆分为2&#34;子查询&#34;。

因此,如果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;