简体   繁体   English

ArangoDB:查找所有最短路径

[英]ArangoDB: Find all shortest paths

i want to get all shortest paths between 2 vertex. 我想获得2个顶点之间的所有最短路径。

Example: Give me all shortest path between node A and B should only return the 2 blue paths 示例:给我所有节点A和B之间的最短路径应仅返回2条蓝色路径

示例图

this is what i have got so far: 这是到目前为止我得到的:

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

Problems: 1. it is very slow (took 18 seconds on a graph with like 70 mio nodes) 2. it finds every path, but i want only all shortest path 问题:1.速度非常慢(在具有70个mio节点的图形上花了18秒)2.找到了所有路径,但是我只想所有最短的路径

UPDATE i tried the 2-step query solution from the comments. 更新我尝试了从注释的两步查询解决方案。 the problem is that the second query is also very slow 问题是第二个查询也很慢

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

First of all you need a hash index on field objectID in collection Entity to avoid the full collection scans, which heavily slows down your performance. 首先,您需要在集合Entity字段objectID上使用哈希索引,以避免完整的集合扫描,这会严重降低性能。

To get all shortest path I would first search for one shortest path with the AQL SHORTEST_PATH and return the number of visited vertices. 为了获得所有最短路径,我首先要使用AQL SHORTEST_PATH搜索一条最短路径,然后返回访问的顶点数。 There is also no need of subqueries (like in your query). 也不需要子查询(例如查询中的子查询)。

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

After that I would execute another query with the result from the first query as bind parameter @depth , which is used to limit the depth of the traversal. 之后,我将执行另一个查询,并将第一个查询的结果作为绑定参数@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

Note : To filter the last vertex in the path you don't have to use LAST(path.vertices) , you can simply use node because it is already the last vertex (the same applies for edge ). 注意 :要过滤路径中的最后一个顶点,您不必使用LAST(path.vertices) ,您可以简单地使用node因为它已经是最后一个顶点了( edge也是一样)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM