我正在尝试使用 Cypher 在 Neo4j 上复制 SGF 游戏树。这棵树是这样的形状:
type GameTree = {
id: number;
data: { [key: string]: string[] };
parentId: number | null;
children: GameTree[];
};
这是我正在尝试解决的创建查询:
UNWIND $moves AS move
MATCH (parent)
WHERE ((parent:GameNode) OR (parent:MoveNode))
AND parent.game_id = $gameId
AND parent.id = move.parentId
CREATE (parent)
-[:NEXT_MOVE]
->(:MoveNode{
game_id: $gameId,
id: move.id
})
最初,树的根是
GameNode
,我单独创建它,因为它包含有趣的元数据。无论如何,这不会像这样工作,因为在 UNWIND
和 MATCH
子句时,只存在一个父级,其余的将/应该递归创建。
有没有办法在 Cypher 中进行这种递归创建?也许有一些我似乎找不到的递归关键字(这似乎是一个常见的问题......)?也许某处有有用的 APOC 程序?
作为解决方法,我正在考虑首先创建所有
MoveNode
,然后使用上面的查询将它们重新串在一起。它看起来像这样:
// 1. Create All The Move Nodes
UNWIND $moveNodes AS move
CREATE (:MoveNode{
game_id: move.game_id,
id: move.id
})
// 2. Tie them to their Parents
WITH move
MATCH (parent{
game_id: move.game_id,
id: move.parentId
}),
(m:MoveNode{
game_id: move.game_id,
id: move.id
})
WHERE parent:GameNode
OR parent:MoveNode
CREATE (parent)-[:NEXT_MOVE]->(m)
如果每个查询执行都是针对按游戏顺序排列的单个移动链,并且父级
GameNode
已经存在,那么您可以使用以下命令:
UNWIND $moveNodes AS move
CALL {
WITH move
MATCH (parent:GameNode|MoveNode {game_id: $gameId, id: move.parentId})
CREATE (parent)-[:NEXT_MOVE]->(m:MoveNode {game_id: $gameId, id: move.id})
}