我想要一个查询,它将删除特定节点中的所有现有关系,然后创建一个新关系。这是我目前所看到的:
MATCH (m:Movie {
_id: 'test/55de0539eb1e14f26a04'
})
MATCH (existingNode:Person {
_id: 'test/41126fc03289a05d8621'
})
MATCH (existingNode)-[existingRelationships]->()
DELETE existingRelationships
WITH existingNode, m
CREATE (existingNode)-[:ACTED_IN]->(m)
RETURN existingNode;
当existingNode至少有一个现有关系时,这就像我想的那样工作。但是,如果在运行此查询时existingNode没有existingRelationships,则不会创建新关系。这就好像在DELETE语句运行之后没有任何东西可以删除。
我怎么能在CREATE上链接,即使没有什么要删除的?
尝试使用OPTIONAL
和distinct
。
:根据neo4j的基数概念,如果我们有几个匹配,我们将为每个匹配获得一行。因此,如果几个节点连接到existingNode
,我们将得到几行,每个连接的节点一个。existingNode
将在所有这些中重复,导致关于它的后续步骤被重复。在我们的示例中,新的连接步骤将执行多次。
如果没有OPTIONAL
,如果有0个节点连接到它,我们将得到0行,这是另一个问题。
因此,当使用OPTIONAL
时,在DELETE
步骤之后,我们有多个existingNode
作为existingRelationships
的数量,但至少有一个,多亏了OPTIONAL
。我们仍然需要使用distinct
来避免创建到m
的多个关系:
MATCH (existingNode:Person {
key: 'A'
})
WITH existingNode
OPTIONAL MATCH (existingNode)-[existingRelationships]->()
DELETE existingRelationships
WITH distinct existingNode as existingNode
MATCH (m:Movie {key: 'B'})
WITH existingNode, m
CREATE (existingNode)-[:ACTED_IN]->(m)
RETURN existingNode, m
对于要删除的关系的样例数据效果很好:
MERGE (a:Person{key: 'A'})
MERGE (b:Movie{key: 'B'})
MERGE (c:Node{key: 'C'})
MERGE (d:Node{key: 'D'})
MERGE (e:Node{key: 'E'})
MERGE (a)-[:POINTS]-(c)
MERGE (a)-[:POINTS]-(d)
MERGE (a)-[:POINTS]-(e)
和另一个没有要删除的关系:
MERGE (a:Person{key: 'A'})
MERGE (b:Movie{key: 'B'})
对于这两种情况,它都返回:
╒══════════════╤═══════════╕
│"existingNode"│"m" │
╞══════════════╪═══════════╡
│{"key":"A"} │{"key":"B"}│
└──────────────┴───────────┘
解决方案是在DELETE之前使用一个OPTIONAL MATCH,例如
MATCH (m:Movie {
_id: 'test/55de0539eb1e14f26a04'
})
MATCH (existingNode:Person {
_id: 'test/41126fc03289a05d8621'
})
OPTIONAL MATCH (existingNode)-[existingRelationships]->()
DELETE existingRelationships
WITH existingNode, m
CREATE (existingNode)-[:ACTED_IN]->(m)
RETURN existingNode;
我相信Neo4j的行为是,如果任何MATCH语句未能返回任何项,则中断查询。可选的MATCH允许查询继续,即使没有条目匹配:
https://neo4j.com/docs/cypher-manual/current/clauses/optional-match/