考虑这个有 5 个顶点的图,其中包含一个循环 B -> D -> E -> B:
没有唯一性限制的出站遍历会跑到这个循环中,在一条路径上多次访问一些顶点和边,直到达到最大遍历深度:
FOR v,e,p IN 1..10 OUTBOUND "vert/A" edge
OPTIONS { uniqueVertices: "none", uniqueEdges: "none" }
RETURN CONCAT_SEPARATOR(" --> ", p.vertices[*]._key)
[
"A --> B",
"A --> B --> C",
"A --> B --> D",
"A --> B --> D --> E",
"A --> B --> D --> E --> B",
"A --> B --> D --> E --> B --> C",
"A --> B --> D --> E --> B --> D",
"A --> B --> D --> E --> B --> D --> E",
"A --> B --> D --> E --> B --> D --> E --> B",
"A --> B --> D --> E --> B --> D --> E --> B --> C",
"A --> B --> D --> E --> B --> D --> E --> B --> D",
"A --> B --> D --> E --> B --> D --> E --> B --> D --> E",
"A --> B --> D --> E --> B --> D --> E --> B --> D --> E --> B"
]
默认情况下,uniqueVertices 是 "none",uniqueEdges 是 "path"。这些选项避免了同一条边沿一条路径走两次。这可以防止遍历第二次进入循环(从 B 到 D 的边),但后两条路径仍然包含 B 两次:
FOR v,e,p IN 1..10 OUTBOUND "vert/A" edge
OPTIONS { uniqueVertices: "none", uniqueEdges: "path" }
RETURN CONCAT_SEPARATOR(" --> ", p.vertices[*]._key)
[
"A --> B",
"A --> B --> C",
"A --> B --> D",
"A --> B --> D --> E",
"A --> B --> D --> E --> B",
"A --> B --> D --> E --> B --> C"
]
通过将顶点和边的唯一性限制为"path",每个路径都不会访问顶点或边两次。跟随从 E 到 B 的边,因为这是在路径上第一次遇到这条边(uniqueEdges 是 "none" 还是 "path" 与这个特定的图无关)。但是顶点 B 一开始已经被访问过(A --> B --> D),所以遍历到这里就停止了,第二次不包括 B:
FOR v,e,p IN 1..10 OUTBOUND "vert/A" edge
OPTIONS { uniqueVertices: "path", uniqueEdges: "path" }
RETURN CONCAT_SEPARATOR(" --> ", p.vertices[*]._key)
[
"A --> B",
"A --> B --> C",
"A --> B --> D",
"A --> B --> D --> E"
]
需要一个不同的示例图来显示uniqueVertices: "global" 的效果,4 个顶点呈菱形:
从 F 开始的出站遍历通过 G 和 H 通向同一个顶点 I。任何顶点或边不可能被访问两次,但每个发现的路径可能包括 I:
FOR v,e,p IN 1..10 OUTBOUND "vert/F" edge
OPTIONS { bfs: true, uniqueVertices: "path", uniqueEdges: "path" }
RETURN CONCAT_SEPARATOR(" --> ", p.vertices[*]._key)
[
"F --> G",
"F --> H",
"F --> G --> I",
"F --> H --> I"
]
如果我们现在将顶点的唯一性更改为"global",则只有一条路径可以以 I 结尾。采用哪条路径(通过 G 或 H)未定义:
FOR v,e,p IN 1..10 OUTBOUND "vert/F" edge
OPTIONS { bfs: true, uniqueVertices: "global", uniqueEdges: "path" }
RETURN CONCAT_SEPARATOR(" --> ", p.vertices[*]._key)
[
"F --> G",
"F --> H",
"F --> G --> I"
]
请注意,uniqueVertices: "global" 需要 bfs: true(广度优先搜索)。虽然它不会使遍历确定性,但它确实使它更可预测。使用深度优先搜索,它会沿着一条路径直到结束(或直到达到最大深度),然后才会跟随相同深度的其他边缘。如果某些路径包含已访问的顶点,则遍历将在某些路径上提前停止,但发现路径的顺序未定义,这可能导致为同一查询返回不同的顶点集。另一方面,广度优先搜索确保返回相同的顶点集,即使所遵循的边在运行之间可能会有所不同。