Find The shortest Path between Given multiple Nodes - neo4j

I am trying to find the Shortest Path between given Multiple Nodes.
Like I have an Array of locations Node and then there is a location for the user. I want to find the Nearest Location to that user between these given nodes.
I have tried this query
UNWIND
["93049","67069","90762","86156","01067","18069","52146","04356"," 42329","53113","76131","40549","50670","50678","85774","80339"] AS plz
MATCH p=Shortestpath(
(a:plzNodes {plz: plz})-[*..14]-(b:plzNodes {plz: "88400"})
) RETURN plz,collect(p);

You can use the path expander procs from APOC Procedures for this, collecting the possible end nodes, and then using the path expander from the start node to those end nodes with a limit of 1: the path to the first node encountered (which will be the shortest path, due to breadth first expansion) will be returned.
WITH ["93049","67069","90762","86156","01067","18069","52146","04356"," 42329","53113","76131","40549","50670","50678","85774","80339"] AS plzes
MATCH (a:plzNodes)
WHERE a.plz in plzes
WITH collect(a) as plzNodes
MATCH (b:plzNodes {plz: "88400"})
CALL apoc.path.subgraphNodes(b, {endNodes:plzNodes, limit:1, maxLevel:14}) YIELD node as closest
RETURN closest

Related

Neo4j -shortest path where intermediate nodes have a relationship [duplicate]

I have a graph database that consists of nodes (bus stations) with a property called “is_in_operation” which is set to “true” if the bus station is operational; otherwise it is set to “false”.
There is a relationship created between two nodes if a bus travels between the two stations.
I would like to find the path with the shortest number of stops between two nodes where all nodes in the path are operational.
There is an example in the database where there are 2 paths between 2 specified nodes. The “is_in_operation” property is set to ‘true’ for all nodes in both paths. When I run the following query, I get the correct answer
START d=node(1), e=node(5)
MATCH p = shortestPath( d-[*..15]->e ) where all (x in nodes(p) where x.is_in_operation='true')
RETURN p;
When I set the ‘is_in_operation’ property to ‘false’ for one of the intermediate nodes in the shortest path and rerun the query, I expect it to return the other path. However, I get no answer at all.
Is the query incorrect? If so, how should I specify the query?
The problem is that shortestPath can't take into account the where clause, so you're matching the shortest path, and then filtering it out with your where.
How about this one--it might not be as efficient as shortestPath, but it should return a result, if one exists:
START d=node(1), e=node(5)
MATCH p = d-[*..15]->e
where all (x in nodes(p) where x.is_in_operation='true')
RETURN p
order by len(p)
limit 1;

Neo4j ShortestPath to any node with a given property

I am trying to work with ShortestPath in Neo4j.
I want to find, for each node, its shortest path to any node with a given property.
In other words, for any node n1 I want the smallest length of the shortest paths to any node n2, n2 having a specific property.
I currently use the following query but I believe it is inefficient as it would have to compute all shortest path between n1 and n2. A smarter way would be to stop looking as soon as we find a path such that length(path)==1.
MATCH path = shortestpath((n1:Node {has_ppt: False})-[:KNOWS]-(n2:Node {has_ppt: True}))
RETURN n1,n2,length(path)
LIMIT 5
Does anyone know how to do it differently ? Thanks
Your -[:KNOWS]- pattern does not specify a variable length path (like -[:KNOWS*..5]-), so your shortestpath query is currently only trying to find paths of length 1. This is probably not what you intended.
You may want to try an iterative approach to finding a single instance of the shortest path. That is, repeatedly perform the following query (while incrementing the number in the [:KNOWS*1] pattern, to increment the desired path length) until you get a result:
MATCH path = (n1:Node {has_ppt: False})-[:KNOWS*1]-(n2:Node {has_ppt: True})
RETURN n1,n2,length(path)
LIMIT 1;

How to find a path in cypher the ungreedy way

Actually i'm modelling TEI-encoded XML-Text in a graph (words as a chain of nodes) and i want to find shortestPaths and only the very shortest path in a graph.
My query looks like
MATCH (w0:XmlWord)-[:NEXT*..6]->(n:XmlTag {_name:'lb'})-[:NEXT*..6]->(w1:XmlWord)
RETURN id(w0), id(w1);
And I need only the shortest possible path but neo4j gives me all possibilities until to the 6th step. The result should be the nodes Vorträge, über, des, and Freiherrn
Neo4j gives me back all possible combinations until to the 6th step.
If someone needs access to a sample-database just let me know.
This is a little tough when you're using multiple variable-length relationships in the same path. You can however order the results by path length and filter for the ones with the minimum length.
MATCH path = (:XmlWord)-[:NEXT*..6]->(:XmlTag {_name:'lb'})-[:NEXT*..6]->(:XmlWord)
WITH length(path) as length, collect(path) as paths
ORDER BY length ASC
LIMIT 1
UNWIND paths as path
WITH head(nodes(path)) as first, last(nodes(path)) as last
RETURN id(first), id(last);

Exclude paths with duplicated nodes

In my flight modelization, I would like to search for path with 1 stop which is equivalent in the graph to have a 4 hops relationships from the source to the destination. When searching the path with :
match (s:Airport{airportName:'CAN'}),
(d:Airport{airportName:'ICN'})
with s,d
match p = (s)<-[*4]->(d)
return nodes(p), relationships(p)
But this also give me path with airport node that are visited twice, like this : airport node
So my question is, how to exclude paths which contains duplicated nodes ?
How to detect whether there is a duplicated node within a path ?
Thank you !
If you have access to APOC Procedures, you can try using apoc.algo.allSimplePaths(), which will not contain any loops back to a previously visited node in the path.
match (s:Airport{airportName:'CAN'}),
(d:Airport{airportName:'ICN'})
call apoc.algo.allSimplePaths(s, d, '', 4) yield path
return nodes(path), relationships(path)

Neo4j - get shortest path between a specific node with id to a node with a label

I'm trying to find the closest node with a specific label to a node which i have his id.
MATCH (object{id:'1489751911095'}), (apiUser:ApiUser) ,
p = allShortestPaths((object) - [*] - (apiUser)) return p limit 1
For some reason, it doesn't stops in the first encounter of the node apiUser:ApiUser, but is continuing further on.
The allShortestPaths feature enumerates all shortest paths between two nodes. So, for your query, it takes all possible pairs of object and apiUser nodes and enumerates all shortest paths between each pair. So how do we stop that from happening?
First, you might want to simplify your original query like this:
MATCH p=allShortestPaths((object {id:'1489751911095'})-[*]-(apiUser:ApiUser))
RETURN p
LIMIT 1
Second, if you only need one path, why not use the shortestPath feature?
MATCH p=shortestPath((object {id:'1489751911095'})-[*]-(apiUser:ApiUser))
RETURN p
LIMIT 1
This will still calculate a shortest path for each apiUser, so you'd want to order the results based on the length of the path:
MATCH p=shortestPath((object {id:'1489751911095'})-[*]-(apiUser:ApiUser))
RETURN p
ORDER BY length(p) DESC
LIMIT 1
This is not the most efficient solution, as Neo4j will still calculate the shortest path for each apiUser - whether the solution is applicable to your use case depends on the number of apiUsers in your database.
When matching from a single node, a variable-length match with LIMIT 1 should work:
MATCH (object{id:'1489751911095'})-[*]-(p:ApiUser)
RETURN p limit 1
It's recommended to have a label in your match when looking up a node by property, and an index or unique constraint on the label+property so it's a fast match.
If you are unsure if there will be a node of that type close by, you may want to add an upper bound to your variable length match.

Resources