Neo4j 正在使用同一个密码创建多个节点和关系

Neo4j is creating multiple nodes and relationships with the same cypher

我正在尝试动态生成密码以在 Neo4j (v3.0.4) 上创建节点和关系,但我得到了一些奇怪的结果。

我使用密码查询已经有一段时间了,我在这里看不出我的查询有什么问题

所以我有一个 Neo4j 数据库,它对 :Individuals

的唯一 id 有约束
CREATE CONSTRAINT ON (i:Individual) ASSERT i.id IS UNIQUE

鉴于此,我运行宁以下密码查询:

MERGE (parent:Individual {id:"334717eb182371a126e46d44bde3ef6b"}) 
SET parent.name = "SOME PARENT NAME"
WITH parent 
OPTIONAL MATCH (parent)<-[del:IS_RELATIVE]-(n)

WITH parent, n, del 
DELETE del 
WITH parent 

CREATE (c1:Individual {name:"CHILD 1"}) 
CREATE (parent)<-[r1:IS_RELATIVE {birth:"2017-02-24"}]-(c1) 

CREATE (c2:Individual {name:"CHILD 2"}) 
CREATE (parent)<-[r2:IS_RELATIVE {birth:"2015-01-23"}]-(c2)

我第一次 运行 结果是:

Added 3 labels, created 3 nodes, set 7 properties, created 2 relationships, statement executed in 1201 ms

太棒了!预期的结果。
但是如果我 运行 same 再次查询,结果是

Added 4 labels, created 4 nodes, set 11 properties, deleted 2 relationships, created 4 relationships, statement executed in 540 ms.

如果我再次 运行 相同的查询:

Added 8 labels, created 8 nodes, set 21 properties, deleted 4 relationships, created 8 relationships, statement executed in 192 ms.

然后

Added 16 labels, created 16 nodes, set 41 properties, deleted 8 relationships, created 16 relationships, statement executed in 583 ms.

并注意第一个节点没有被复制,只有 "child" 个节点及其关系...

我不知道我错过了什么...
谢谢

我认为修复查询的更简单方法是将所有 CREATE 语句更改为 MERGE,如下所示:

MERGE (parent:Individual {id:"334717eb182371a126e46d44bde3ef6b"}) 
SET parent.name = "SOME PARENT NAME"
WITH parent 
OPTIONAL MATCH (parent)<-[del:HAS_CHILDREN]-(n)

WITH parent, n, del 
DELETE del 
WITH parent 

MERGE (c1:Individual {name:"CHILD 1"}) 
MERGE (parent)<-[r1:HAS_CHILDREN {birth:"2017-02-24"}]-(c1) 

MERGE (c2:Individual {name:"CHILD 2"}) 
MERGE (parent)<-[r2:HAS_CHILDREN {birth:"2015-01-23"}]-(c2)

这样就可以运行多次查询上面的内容,不会再创建节点了。

您只有一个唯一性约束是针对 Individual 个节点的 id 属性。

因为 name 属性 没有唯一性约束,您的 CREATE (c1:Individual {name: "CHILD x"}) 子句将始终创建新节点。您需要在创建这些节点时指定 id 属性,以便在您尝试 re-use 现有 id.

时看到约束错误

此外,您应该使用 MERGE 而不是 CREATE,这样您就不必在违反约束时处理错误,并且您的查询也不会中止。

例如:

MERGE (parent:Individual {id:"334717eb182371a126e46d44bde3ef6b"}) 
SET parent.name = "SOME PARENT NAME"
WITH parent 
OPTIONAL MATCH (parent)<-[del:IS_RELATIVE]-()

DELETE del 
WITH parent 

MERGE (c1:Individual {id: "1234567890"})
SET c1.name = "CHILD 1"
CREATE (parent)<-[r1:IS_RELATIVE {birth:"2017-02-24"}]-(c1) 

MERGE (c2:Individual {id: "2345678901"}) 
SET c2.name = "CHILD 2"
CREATE (parent)<-[r2:IS_RELATIVE {birth:"2015-01-23"}]-(c2)

如果 child 的节点已经存在(具有相同的 id),但它没有您要分配给它的名称,上面的查询将名称设置为一个单独的 SET 子句。 (如果您在 MERGE 子句中保留 name 属性,如果具有相同 id 的节点已经存在,但它具有不同的名称,您将得到一个错误。 )

注意:如果 child 已经有 IS_RELATIVE 不再合适的关系,您可能还需要考虑该怎么做。