ArangoDB:查找所有最短路径

时间:2017-03-24 13:16:18

标签: arangodb aql

我希望获得2个顶点之间的所有最短路径。

示例:给我节点A和B之间的所有最短路径应该只返回2条蓝色路径

example graph

这是我到目前为止所得到的:

LET source = (FOR x IN Entity FILTER x.objectID == "organization_1"
    return x)[0]
LET destination = (FOR x IN Entity FILTER x.objectID == "organization_129"
    return x)[0]
FOR node, edge, path IN 1..2 ANY source._id GRAPH "m" 
    FILTER LAST(path.vertices)._id == destination._id
    LIMIT 100
RETURN path

问题: 1.它非常慢(在70 mio节点的图形上花了18秒) 2.它找到每条路径,但我只想要所有最短路径

更新 我从评论中尝试了两步查询解决方案。 问题是第二个查询也很慢

Query string:
 FOR source IN Entity FILTER source.objectID == "organization_1"
 LIMIT 1
 FOR node, edge, path 
   IN 1..@depth ANY source._id 
   GRAPH "m" 
   OPTIONS {uniqueVertices: "path"}
   FILTER node.objectID == "organization_129"
   RETURN path

Execution plan:
 Id   NodeType          Est.   Comment
  1   SingletonNode        1   * ROOT
 11   IndexNode            1     - FOR source IN Entity   /* hash index scan */
  5   LimitNode            1       - LIMIT 0, 1
  6   CalculationNode      1       - LET #6 = source.`_id`   /* attribute expression */   /* collections used: source : Entity */
  7   TraversalNode      346       - FOR node  /* vertex */, path  /* paths */ IN 1..2  /* min..maxPathDepth */ ANY #6 /* startnode */  GRAPH 'm'
  8   CalculationNode    346       - LET #10 = (node.`objectID` == "organization_129")   /* simple expression */
  9   FilterNode         346       - FILTER #10
 10   ReturnNode         346       - RETURN path

Indexes used:
 By   Type   Collection      Unique   Sparse   Selectivity   Fields                       Ranges
 11   hash   Entity          false    false       100.00 %   [ `objectID` ]   (source.`objectID` == "organization_1")
  7   edge   ACTIVITYPARTY   false    false       100.00 %   [ `_from`, `_to` ]           base INBOUND
  7   edge   ACTIVITYPARTY   false    false       100.00 %   [ `_from`, `_to` ]           base OUTBOUND
  7   edge   ACTIVITY_LINK   false    false       100.00 %   [ `_from`, `_to` ]           base INBOUND
  7   edge   ACTIVITY_LINK   false    false       100.00 %   [ `_from`, `_to` ]           base OUTBOUND
  7   edge   ENTITY_LINK     false    false        70.38 %   [ `_from`, `_to` ]           base INBOUND
  7   edge   ENTITY_LINK     false    false        70.38 %   [ `_from`, `_to` ]           base OUTBOUND
  7   edge   RELATION        false    false        20.49 %   [ `_from`, `_to` ]           base INBOUND
  7   edge   RELATION        false    false        20.49 %   [ `_from`, `_to` ]           base OUTBOUND
  7   edge   SOFT_LINK       false    false       100.00 %   [ `_from`, `_to` ]           base INBOUND
  7   edge   SOFT_LINK       false    false       100.00 %   [ `_from`, `_to` ]           base OUTBOUND

Traversals on graphs:
 Id   Depth   Vertex collections                      Edge collections                                                 Options                                   Filter conditions
  7   1..2    Activity, Entity, SOFT_LINK, Property   ACTIVITYPARTY, ENTITY_LINK, SOFT_LINK, RELATION, ACTIVITY_LINK   uniqueVertices: path, uniqueEdges: path   

Optimization rules applied:
 Id   RuleName
  1   move-calculations-up
  2   move-filters-up
  3   move-calculations-up-2
  4   move-filters-up-2
  5   use-indexes
  6   remove-filter-covered-by-index
  7   remove-unnecessary-calculations-2
  8   optimize-traversals
  9   move-calculations-down

1 个答案:

答案 0 :(得分:0)

首先,您需要在集合objectID中的字段Entity上使用哈希索引,以避免完整的集合扫描,这会严重降低您的性能。

要获得所有最短路径,我首先使用AQL SHORTEST_PATH搜索一条最短路径,然后返回访问顶点的数量。也不需要子查询(例如在您的查询中)。

FOR source IN Entity FILTER source.objectID == "organization_1"
LIMIT 1
FOR destination IN Entity FILTER destination.objectID == "organization_129"
LIMIT 1
RETURN sum(
  FOR v, e
  IN ANY
  SHORTEST_PATH source._id TO destination._id
  GRAPH "m"
  RETURN 1)-1

之后,我将使用第一个查询的结果执行另一个查询作为绑定参数@depth,用于限制遍历的深度。

FOR source IN Entity FILTER source.objectID == "organization_1"
LIMIT 1
FOR node, edge, path 
  IN 1..@depth ANY source._id 
  GRAPH "m" 
  OPTIONS {uniqueVertices: "path"}
  FILTER node.objectID == "organization_129"
  RETURN path

注意:要过滤路径中的最后一个顶点,您不必使用LAST(path.vertices),只需使用node,因为它已经是最后一个顶点(这同样适用于edge)。