0

我有以下图表:

(Boxer)-[:STARTS]->(Round)-[:CONTINUES]->(Round)-[:CONTINUES]->(Round)-[:CONTINUES]->(Round)

我想在名为 prevRound 的指定回合之后插入一个新回合。现在我正在这样做:

MERGE (round:Round {uuid: $round.uuid})
MERGE (prevRound:Round {uuid: $prevRound.uuid})
MERGE (prevRound)-[oldRel:CONTINUES]->(nextRound)
MERGE (prevRound)-[:CONTINUES]->(round)-[:CONTINUES]->(nextRound)
DELETE oldRel

这可行,但当我尝试在列表末尾插入一个节点时,它实际上会创建一个空节点。我知道这是因为:

MERGE (prevRound)-[oldRel:CONTINUES]->(nextRound)

实际上,这将在 nextRound 节点不存在时创建它。

我怎样才能防止这种情况?我尝试了可选匹配,但效果不佳。

4

1 回答 1

1

MERGE 不是在这里使用的正确子句,因为如您所见,如果模式不存在,它将创建模式,为您提供一个空白节点以及与它的关系prevRound。OPTIONAL MATCH 是用于该行的正确子句(尽管您确实需要在它和前面的 MERGE 之间使用 WITH 子句)...但实际上更好的方法是稍微重新排列您的查询(参见最后一段)。

您还应该拆分最后一个 MERGE,因为在某些情况下,像这样的较长模式可能不会像您期望的那样做。阅读我们的知识库文章,了解 MERGE 如何处理一些更精细的细节,否则这些细节可能会让您感到困惑。

我们实际上可以通过重新排列查询的某些部分来相当简单地完成您想要的。

MERGE (round:Round {uuid: $round.uuid})
MERGE (prevRound:Round {uuid: $prevRound.uuid})
WITH round, prevRound
OPTIONAL MATCH (prevRound)-[oldRel:CONTINUES]->(nextRound)
DELETE oldRel
MERGE (prevRound)-[:CONTINUES]->(round)
WITH round, nextRound, oldRel
WHERE nextRound IS NOT NULL
MERGE (round)-[:CONTINUES]->(nextRound)

我们通过前面的 WHERE 子句保护 round 和 nextRound 之间的 MERGE,该子句过滤掉任何 nextRound 不存在的行。

一种可能更简单的方法,虽然效率稍低,但首先处理您知道存在的节点,round 和 prevRound,然后处理可能存在或可能不存在的模式,MATCH 到旧节点,尽管您会需要做一些过滤,因为 MATCH 也会选择你刚刚创建的关系来四舍五入:

MERGE (round:Round {uuid: $round.uuid})
MERGE (prevRound:Round {uuid: $prevRound.uuid})
MERGE (prevRound)-[:CONTINUES]->(round)
WITH round, prevRound
MATCH (prevRound)-[oldRel:CONTINUES]->(nextRound)
WHERE nextRound <> round
DELETE oldRel
MERGE (round)-[:CONTINUES]->(nextRound)

您还可以考虑是否有任何地方您知道这种关系不存在,如果是,请使用 CREATE 而不是 MERGE。我有一种感觉,这里的最后一个 MERGE 可能是一个 CREATE。

于 2020-02-13T08:30:10.570 回答