diff --git a/doc-test/src/test/java/org/neo4j/gds/doc/syntax/DagLongestPathSyntaxTest.java b/doc-test/src/test/java/org/neo4j/gds/doc/syntax/DagLongestPathSyntaxTest.java new file mode 100644 index 0000000000..e3f6b9ff20 --- /dev/null +++ b/doc-test/src/test/java/org/neo4j/gds/doc/syntax/DagLongestPathSyntaxTest.java @@ -0,0 +1,38 @@ + /* + * Copyright (c) "Neo4j" + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.gds.doc.syntax; + +import java.util.List; + +import static org.neo4j.gds.doc.syntax.SyntaxMode.STREAM; + + class DagLongestPathSyntaxTest extends SyntaxTestBase { + + protected Iterable syntaxModes() { + return List.of( + SyntaxModeMeta.of(STREAM) + ); + } + + @Override + protected String adocFile() { + return "pages/algorithms/dag/longest-path.adoc"; + } + } diff --git a/doc/modules/ROOT/pages/algorithms/dag/longest-path.adoc b/doc/modules/ROOT/pages/algorithms/dag/longest-path.adoc index 5d7e150a28..172dd01282 100644 --- a/doc/modules/ROOT/pages/algorithms/dag/longest-path.adoc +++ b/doc/modules/ROOT/pages/algorithms/dag/longest-path.adoc @@ -20,7 +20,7 @@ Finding the longest path that leads to a node in a graph is possible to do in li GDS implementation for this algorithm is based on topological sort and takes linear time. If the graph is not a DAG, the runtime is still linear, but the results cannot be trusted. You can use xref:algorithms/dag/topological-sort.adoc[topological sort] to make sure the graph is a DAG. -The algorithm supports unweighted graphs and graphs with non negative weights. +The algorithm supports weighted and unweighted graphs. Negative weights are currently unsupported. === Usage @@ -46,7 +46,13 @@ CALL gds.dag.longestPath.stream( graphName: String, configuration: Map ) YIELD - nodeId: Integer + index: Integer, + sourceNode: Integer, + targetNode: Integer, + totalCost: Float, + nodeIds: List of Integer, + costs: List of Float, + path: Path ---- include::partial$/algorithms/common-configuration/common-parameters.adoc[] @@ -62,9 +68,15 @@ include::partial$/algorithms/common-configuration/common-stream-stats-configurat .Results [opts="header"] |=== -| Name | Type | Description -| targetNodeId | Integer | The ID of the node for which the path is computed -| distance | Double | The distance of the longest path that ends in the target node +| Name | Type | Description +| index | Integer | 0-based index of the found path. +| sourceNode | Integer | Source node of the path. +| targetNode | Integer | Target node of the path. +| totalCost | Float | Total cost from source to target. +| nodeIds | List of Integer | Node ids on the path in traversal order. +| costs | List of Float | Accumulated costs for each node on the path. +| path | Path | The path represented as Cypher entity. + |=== // include-with-stream @@ -73,9 +85,6 @@ include::partial$/algorithms/common-configuration/common-stream-stats-configurat // tabbed-example ==== -[NOTE] -Current result does not contain the longest path itself, but only the distance of the path. - == Examples @@ -91,7 +100,7 @@ CREATE (n0:Goods {name: 'Timber'}), (n1:Goods {name: 'Lumber'}), (n2:Goods {name: 'Screws'}), - (n3:Workshop {name: 'Table Maker Inc.'}), + (n3:Workshop {name: 'Table Maker'}), (n4:Product {name: 'Table'}), (n0)-[:Processing {time: 1}]->(n1), @@ -127,19 +136,27 @@ For more details on the stream mode in general, see xref:common-usage/running-al [source, cypher, role=noplay setup-query] ---- CALL gds.dag.longestPath.stream("g", {relationshipWeightProperty: "time"}) -YIELD targetNodeId as target, distance -RETURN gds.util.asNode(target).name, distance +YIELD index, sourceNode, targetNode, totalCost, nodeIds, costs, path +RETURN + index, + gds.util.asNode(sourceNode).name AS sourceNode, + gds.util.asNode(targetNode).name AS targetNode, + totalCost, + [nodeId IN nodeIds | gds.util.asNode(nodeId).name] AS nodeNames, + costs, + nodes(path) as path +ORDER BY index ---- We use the utility function asNode to return the name of node instead of its ID to make results more readable. .Results [opts="header"] |=== -| name | distance -|"Timber" | 0.0 -|"Screws" | 0.0 -|"Lumber" | 1.0 -|"Table Maker" | 3.0 -|"Table" | 4.0 +| index | sourceNode | targetNode | totalCost | nodeNames | costs | path +| 0 | "Timber" | "Timber" | 0.0 | ["Timber"] | [0.0] | [Node[0]] +| 1 | "Timber" | "Lumber" | 1.0 | ["Timber", "Lumber"] | [0.0, 1.0] | [Node[0], Node[1]] +| 2 | "Screws" | "Table Maker" | 3.0 | ["Screws", "Table Maker"] | [0.0, 3.0] | [Node[2], Node[3]] +| 3 | "Screws" | "Screws" | 0.0 | ["Screws"] | [0.0] | [Node[2]] +| 4 | "Screws" | "Table" | 4.0 | ["Screws", "Table Maker", "Table"] | [0.0, 3.0, 4.0] | [Node[2], Node[3], Node[4]] |=== --