如何计算跳数在 (1,5) (neo4j) 范围内的两个节点之间的路径?

How can I calculate the path between two nodes with hops in range (1,5) (neo4j) ?

我试图找到两个节点之间的所有可能路径。我使用了很少的密码查询来完成所需的工作,但是如果跃点增加,它会花费很多时间。这是查询

match p = (n{name:"Node1"})-[:Route*1..5]-(b{name:"Node2"}) return p

此外,如果我使用 shortestpath,如果找到具有最小跳数的路径,它会限制结果。因此,如果在节点之间发现直接连接(1 跳),我不会获得 2 跳或多于 2 跳的结果。

match p = shortestpath((n{name:"Node1"})-[:Route*1..5]-(b{name:"Node2"})) return p

如果我将跳数增加到 2 或更多,它会抛出异常。

shortestPath(...) does not support a minimal length different from 0 or 1 

是否有任何其他替代框架或算法以最短时间获取所有路径?

P.S。我正在寻找 ms 顺序的东西。目前,所有跳数大于 3 的查询都需要几秒钟才能完成。

根据您的描述,我假设您希望根据某些权重获得最短路径,例如 :Route 关系上的 duration 属性。

如果这是真的,在 cypher 中使用 shortestPath 没有帮助,因为它只考虑了跳数。 Cypher 中尚未以有效的方式提供加权最短路径。

Java API 通过 dijekstra 或 astar 通过 GraphAlgoFactory class. For the simple case that your cost function is just the value of a relationship property (as mentioned above) you can also use an existing REST endpoint 支持加权最短路径。

我了解到您正在尝试加快涉及可变长度路径的原始查询。 shortestpath 函数不适合您的查询,因为它确实试图找到 最短 路径——而不是 all 路径一定长度。

您的原始查询(使用示例数据)的执行计划如下所示:

+-----------------------+----------------+------+---------+-------------------+---------------------------------------------+
| Operator              | Estimated Rows | Rows | DB Hits | Identifiers       | Other                                       |
+-----------------------+----------------+------+---------+-------------------+---------------------------------------------+
| +ProduceResults       |              0 |    1 |       0 | p                 | p                                           |
| |                     +----------------+------+---------+-------------------+---------------------------------------------+
| +Projection           |              0 |    1 |       0 | anon[30], b, n, p | ProjectedPath(Set(anon[30], n),) |
| |                     +----------------+------+---------+-------------------+---------------------------------------------+
| +Filter               |              0 |    1 |       2 | anon[30], b, n    | n.name == {  AUTOSTRING0}                   |
| |                     +----------------+------+---------+-------------------+---------------------------------------------+
| +VarLengthExpand(All) |              0 |    2 |       7 | anon[30], b, n    | (b)<-[:Route*]-(n)                          |
| |                     +----------------+------+---------+-------------------+---------------------------------------------+
| +Filter               |              0 |    1 |       3 | b                 | b.name == {  AUTOSTRING1}                   |
| |                     +----------------+------+---------+-------------------+---------------------------------------------+
| +AllNodesScan         |              3 |    3 |       4 | b                 |                                             |
+-----------------------+----------------+------+---------+-------------------+---------------------------------------------+

因此,您的原始查询正在扫描 每个节点 以查找与 b 模式匹配的节点。然后,它扩展 all 个从 b 开始的可变长度路径。然后它过滤这些路径以找到以与 n.

的模式匹配的节点结尾的路径

这里有一些可以加快查询速度的建议,但您必须在数据上对其进行测试以查看速度:

  1. 给每个节点一个标签。例如,Foo.
  2. 创建一个索引可以加快搜索您的端节点。例如:

    CREATE INDEX ON :Foo(name);
    
  3. 修改您的查询以强制在两端节点上使用索引。例如:

    MATCH p =(n:Foo { name:"Node1" })-[:Route*1..5]-(b:Foo { name:"Node2" })
    USING INDEX n:Foo(name)
    USING INDEX b:Foo(name)
    RETURN p;
    

经过以上改动后,执行计划为:

+-----------------+------+---------+-----------------------------+-----------------------------+
| Operator        | Rows | DB Hits | Identifiers                 | Other                       |
+-----------------+------+---------+-----------------------------+-----------------------------+
| +ColumnFilter   |    1 |       0 | p                           | keep columns p              |
| |               +------+---------+-----------------------------+-----------------------------+
| +ExtractPath    |    1 |       0 | anon[33], anon[34], b, n, p |                             |
| |               +------+---------+-----------------------------+-----------------------------+
| +PatternMatcher |    1 |       3 | anon[33], anon[34], b, n    |                             |
| |               +------+---------+-----------------------------+-----------------------------+
| +SchemaIndex    |    1 |       2 | b, n                        | {  AUTOSTRING1}; :Foo(name) |
| |               +------+---------+-----------------------------+-----------------------------+
| +SchemaIndex    |    1 |       2 | n                           | {  AUTOSTRING0}; :Foo(name) |
+-----------------+------+---------+-----------------------------+-----------------------------+

此查询计划使用索引直接获取 bn 节点 -- 无需扫描。这本身应该可以提高速度。然后该计划使用 "PatternMatcher" 来查找这些端节点之间的可变长度路径。您将不得不尝试此查询以查看 "PatternMatcher" 执行此操作的效率。