Question on how to call shortest path

Hi!
I have read the documentation, and tried things, but seem unable to find the answer to the following (quite simple) questions.
I want to call shortestPath, have no property on nodes or links with a cost and want to restrict what nodes that should be traversed. How do I do that?
If I have a cost function, I think i could use the nodeQuery config to restrict to one label, but I have a couple of choices so I want to OR them..
Also since I have no cost function I dont really know how to pass the config parameters as it complains that it wants a string not a Map.

So I want a: call algo.shortestPath(start, end, {nodeQuery: "label1|label2"}).
Is this possible?

Thanks

What are you trying to achieve that you think requires "shortestPath" rather than a MATCH? The "shortestPath" requires a "cost" otherwise how can it calculate the shortest path? Do you mean fewest edges?

yeah.. fewest edges.. so having a constant cost for each edge.

You can use APOC path expander procs for this. By default it does a bfs expansion, and if you provide a limit and supply the labels of nodes you want whitelisted in the labelFilter you can get what you want:

MATCH (start:label1 {id:1234}), (end:label2 {id:5678})
CALL apoc.path.spanningTree(start, {endNodes:[end], limit:1, labelFilter:'label1|label2'}) YIELD path
RETURN path

Note that the labels in the labelFilter that you're whitelisting must include a label on your end node (it will not apply the filter to the start node by default, so the start node's label doesn't need to be in there.

That said, if the end node has a label that you don't want whitelisted for traversal, you can use an end label filter in the labelFilter, which is the label prefixed with >.

So if both the start and end node were :Node labeled, but you only wanted the middle nodes in the traversal to be :label1 or :label2 nodes, then you could use this:

MATCH (start:Node {id:1234}), (end:Node {id:5678})
CALL apoc.path.spanningTree(start, {endNodes:[end], limit:1, labelFilter:'label1|label2|>Node'}) YIELD path
RETURN path

As far as the "why spanningTree()?", it's a bit oddly named, but it uses NODE_GLOBAL uniqueness during traversal, meaning a node will only ever be visited once, so there will ever only be a single path to each node (no cycles), so the collection of returned paths (if you don't have an end node, or any restriction on end nodes) takes the form of a spanning tree. The point is that with bfs expansion and NODE_GLOBAL uniqueness and the label filter (and supplying your end node) you get a shortest path using only the labels you want during the traversal.

Thanks! That works.. I do think that the graph algorithms should allow for just a constant weight though :slight_smile:

I think you can do that too.

Under the documentation for the algo.shortestPath parameter weightProperty:

The property name that contains weight. If null, treats the graph as unweighted. Must be numeric.

See if that works for you.