You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Cypher高效查找递归树子路径(图查询vs正则)

基于Neo4j的围棋SGF游戏树图模式搜索实践

游戏树结构与建模

我尝试通过Cypher在Neo4j中重现围棋SGF游戏树,以实现图模式搜索。该游戏树基于Sabaki的SGF Parser,结构定义如下:

type GameTree = {
  id: number;
  data: { [key: string]: string[] };
  parentId: number | null;
  children: GameTree[];
};

目前已完成游戏树建模,结构与围棋编辑器一致,在Neo4j Desktop中可呈现层级清晰的游戏树结构。

字段说明:

  • B和W分别代表黑棋、白棋的落子
  • AB和AW指"添加黑/白棋",用于编辑棋盘位置
  • 本场景仅需关注move字段,其值对应B或W的落子坐标,坐标由两个字母组成(例如列m、行r对应字符串'rm')

目标功能与现有查询

功能目标

当找到指定连续子路径时,返回从根节点开始的完整路径(仅返回根节点亦可)。

基础可行查询

目前已实现可行的Cypher查询语句:

MATCH p=(g:GameNode)-[:NEXT_MOVE*]->()

WITH g, p,
     [m in TAIL(NODES(p)) | m.move] AS moves

WITH g, p,
     REDUCE(path = '', move in moves | path + move) AS joined_moves

WHERE joined_moves CONTAINS "rmro"

RETURN g, p, joined_moves

索引优化后的查询

参考相关思路,可通过创建索引让Neo4j明确使用m.move字段的索引,先执行索引创建语句:

CREATE INDEX move_node_move_idx FOR (m:MoveNode) ON (m.move)

优化后的查询语句如下:

MATCH p=(g:GameNode)-[:NEXT_MOVE*]->(m1:MoveNode)-[:NEXT_MOVE*]->()

WHERE m1.move = HEAD(['rm', 'ro'])

WITH g, p,
     [m in TAIL(NODES(p)) | m.move] AS moves

WITH g, p,
     REDUCE(path = '', move in moves | path + move) AS joined_moves

WHERE joined_moves CONTAINS "rmro"

RETURN g, p, joined_moves

效率分析与替代方案

效率疑问

不确定这类模式搜索在Neo4j或其他图数据库中的效率是否足够。不过结合围棋游戏的特性,多数对局虽有200+落子节点,但分支数量通常不多,且分析针对顺序固定的单向分支(不可跳过节点),这会进一步缩小搜索范围,理论上效率可控。

替代思路

另一种方案是在每个落子节点中存储到该节点的全路径字符串,通过正则表达式实现查询(正则逻辑也可建模为图结构)。此方案用SQL数据库即可满足需求,但仍倾向于使用Neo4j,因为图建模方式在未来可扩展更多实用功能。

内容的提问来源于stack exchange,提问作者psygo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 02:10:55