基于这个类似的问题,我想要最高效的方式来处理这种情况。
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))
Run Code Online (Sandbox Code Playgroud)
不幸的是,IF 不存在,并且 EXISTS 不能用于匹配或查找唯一节点。
我现在最好的解决方案是
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
Run Code Online (Sandbox Code Playgroud)
然而,这看起来有点复杂,WITH本质上需要 2秒CREATE UNIQUE RELATION if start and end node exist(并且在计划中有一个渴望)。有没有可能做得更好?(使用 Cypher 3.1)
你可以简化很多:
MERGE (a:TEST{id:1})
WITH a
MATCH (b:TEST{id:2})
CREATE UNIQUE (a)-[:HAS]->(b)
RETURN a;
Run Code Online (Sandbox Code Playgroud)
(单个)WITH子句用于将查询拆分为 2 个“子查询”。
因此,如果MATCH子查询失败,它只会中止自己的子查询(以及任何后续的子查询),但不会回滚之前成功的MERGE子查询。
但是请注意,无论何时最终子查询失败,该RETURN子句都不会返回任何内容。您必须确定这是否可以接受。
因为上面的RETURN子句只会在b存在时返回一些东西,所以它可能更有意义 returnb或路径。这是后者的示例(p即使路径已经存在,也会被分配一个值):
MERGE (a:TEST{id:1})
WITH a
MATCH (b:TEST{id:2})
CREATE UNIQUE p=(a)-[:HAS]->(b)
RETURN p;
Run Code Online (Sandbox Code Playgroud)
[更新]
在 Neo4j 4.0+ 中,CREATE UNIQUE不再支持,因此MERGE需要使用。
另外,如果你想返回a即使b不存在,你可以使用APOC功能apoc.do.when:
MERGE (a:TEST{id:1})
WITH a
OPTIONAL MATCH (b:TEST{id:2})
CALL apoc.do.when(
b IS NOT NULL,
'MERGE (a)-[:HAS]->(b)',
'',
{a: a, b: b}) YIELD value
RETURN a;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2524 次 |
| 最近记录: |