ArangoDB:获取与所选节点有任何关系的每个节点

ArangoDB: Get every node, which is in any way related to a selected node

我在 ArangoDB 中有一个简单的节点链接图。如何从 1 个预选节点遍历 return 所有与其相关的节点?[​​=10=]

例如: A→B, B→C, C→D, C→E, F→B, F→E

选择其中任何一个都应该return相同的结果(所有)。

我是 ArangoDB 的新手。

你需要的是 AQL graph traversal,自 ArangoDB 2.8 起可用。老版本提供了一组图相关的函数,但原生AQL遍历更快、更灵活,从3.0开始不再提供图函数。


AQL 遍历让您跟随连接到起始顶点的边,直至可变深度。可以访问每个遇到的顶点,例如用于过滤或构造结果,以及引导您到达该顶点的边以及从开始到结束的完整路径,包括顶点和边。

在您的情况下,只需要 returned 访问过的顶点的名称。您可以 运行 以下 AQL 查询,假设有一个文档集合 node 和一个边集合 links 并且它们包含此图的数据:

// follow edges ("links" collection) in outbound direction, starting at A
FOR v IN OUTBOUND "node/A" links
    // return the key (node name) for every vertex we see
    RETURN v._key

这只会return[ "B" ],因为遍历深度隐式为1..1(min=1,max=1)。如果我们增加最大深度,那么我们也可以包括间接连接的节点:

FOR v IN 1..10 OUTBOUND "node/A" links
    RETURN v._key

这会给我们 [ "B", "C", "D", "E"]。如果我们看一下图,这是正确的:我们只沿着从我们来自的顶点指向另一个顶点(箭头的方向)的边。要进行相反的操作,我们可以使用 INBOUND,但在您的情况下,我们希望忽略边的方向并始终遵循:

FOR v IN 1..10 ANY "node/A" links
    RETURN v._key

起初结果可能有点令人惊讶:
[ "B", "C", "D", "E", "F", "B", "F", "E", "C", "D", "B" ]

我们看到重复的节点 returned。原因是例如从 A 到 C 有多个路径(通过 B 和 B-F-E),并且查询 return 是每条路径的最后一个节点作为变量 v。 (它实际上并不处理 所有 最大深度 10 的可能路径,但您可以设置遍历选项 OPTIONS {uniqueEdges: "none"} 来这样做。)

它可以帮助 return 格式化遍历路径以更好地理解正在发生的事情(即如何到达节点):

FOR v, e, p IN 1..10 ANY "node/A" links OPTIONS {uniqueEdges: "path"}
    RETURN CONCAT_SEPARATOR(" - ", p.vertices[*]._key)

结果:

[
  "A - B",
  "A - B - C",
  "A - B - C - D",
  "A - B - C - E",
  "A - B - C - E - F",
  "A - B - C - E - F - B",
  "A - B - F",
  "A - B - F - E",
  "A - B - F - E - C",
  "A - B - F - E - C - D",
  "A - B - F - E - C - B"
]

图中有一个循环,但不能无限循环,因为10跳后超过了最大深度。但是正如您在上面看到的那样,它甚至没有达到 10 的深度,而是停止了,因为(默认)选项是不跟随每条路径两次边缘(uniqueEdges: "path")。

总之,这不是你想要的结果。一个廉价的技巧是使用 RETURN DISTINCTCOLLECT 或类似的东西来删除重复项。但是我们最好调整遍历选项,不要不必要地跟随边缘。

uniqueEdges: "global" 仍会包含 B 节点两次,但 uniqueVertices: "global" 会给出所需的结果。另外,这种情况下可以使用bfs: true进行广度优先搜索。不同之处在于到 F 节点的路径更短(A-B-F 而不是 A-B-C-E-F)。一般来说,您应该使用的确切选项在很大程度上取决于数据集和您的问题。

还有一个问题需要解决:遍历不包括起始顶点(除了 p.vertices[0] 中的每条路径)。通过将最小深度设置为 0,可以使用 ArangoDB 3.0 或更高版本轻松解决此问题:

FOR v IN 0..10 ANY "node/A" links OPTIONS {uniqueVertices: "global"}
    RETURN v._key

[ "A", "B", "C", "D", "E", "F" ]

为了验证从 A 到 F 的所有节点都是 returned,无论起始顶点如何,我们可以发出以下测试查询:

FOR doc IN node
    RETURN (
        FOR v IN 0..10 ANY doc links OPTIONS {uniqueVertices: "global"}
            SORT v._key
            RETURN v._key
    )

所有子数组应该看起来一样。如果您希望按遍历顺序 returned 节点名称,请删除 SORT 操作。希望这有帮助 =)