我们需要具有一些AQL,以验证到实体的特定路径。由于需要扫描整个集合,因此当前解决方案的性能非常差。
例如在这里,我们有3种实体“类型”:a,b,c(尽管它们都在一个集合中)以及它们之间的特定边缘集合,我们想确定_key“ 123”和_key“之间是否存在连接234”正好通过a-> b-> c。
FOR a IN entities FILTER e._key == "123"
FOR b IN 1..1 OUTBOUND e edges_a_to_b
FOR c IN 1..1 INBOUND e_1 edges_c_to_b
FILTER e_2._key == "234"
...
这可以很快散开!
我们还有另一种解决方案,其中我们使用最短路径并指定适当的方向和边缘集合,这要快得多(> 100倍)。但是请担心,这种方法不能完全满足我们的一般情况……边缘的顺序未得到强制执行,并且我们可能必须多次通过相同的边缘集合,而我们无法使用该语法。
还有另一种方法,可能涉及遍历中的路径吗?
谢谢! 丹。
答案 0 :(得分:0)
如果我正确理解,您将始终知道两个顶点之间所需的确切路径。
因此以您的示例a -> b -> c
为例,有效结果将为:
path.vertices == [a, b, c]
因此,我们可以使用此路径对其进行过滤,仅当您使用单个遍历步骤而不是多个遍历步骤时,该路径才有效。
因此,我们尝试使用的是以下模式:
FOR c,e, path IN <pathlength> <direction> <start> <edge-collections>
FILTER path.vertices[0] == a // This needs to be formulated correctly
FILTER path.vertices[1] == b // This needs to be formulated correctly
FILTER path.vertices[2] == c // This needs to be formulated correctly
LIMIT 1 // We only net exactly one path, so limit 1 is enough
[...]
因此,借助此提示,可以通过以下方式编写查询:
FOR a IN entities
FILTER a._key == "123"
FOR c, e, path IN 2 OUTBOUND a edges_a_to_b, INBOUND edges_b_to_c
FILTER path.vertices[1] == /* whatever identifies b e.g. vertices[1].type == "b" */
FILTER path.vertices[2]._key == "234"
LIMIT 1 /* This will stop as soon as the first match is found, so very important! */
/* [...] */
这将使优化程序尽可能早地应用过滤条件,und(几乎)将使用与最短路径实现相同的算法。 诀窍是使用一次遍历而不是多次遍历以节省内部开销并允许更好的优化。
还要考虑到朝相反的方向搜索可能会更好:
例如而不是a -> b -> c
来检查c <- b <- a
可能会更快。
这取决于每个节点的边缘数量。
我假设医生有很多手术,但是一个病人很可能只有少量手术,因此最好是从病人那里开始并向后检查,而不是从医生那里开始并进行检查。
请让我知道它已经对您有所帮助,否则我们可以讨论更多详细信息,并查看是否可以找到进一步的优化方法。
免责声明:我是ArangoDB的Core-Dev团队的成员