Implementing Dijkstra's algorithm in Neo4j - neo4j

I am very new to Neo4j. Could someone kindly explain to me (step-by-step please) how I could implement the Dijkstra's algorithm to find the shortest path between two nodes? Is it possible to simply do it using Cypher?
I already tried the shortestPath algorithm, but it is very slow:
MATCH (from: Location {LocationName:"x"}), (to: Location {LocationName:"y"}) , path = (from)-[:CONNECTED_TO*1..5]->(to)
RETURN path AS shortestPath,
reduce(distance = 0, r in relationships(path)| distance+toInt(r.Distance))
AS totalDistance
ORDER BY totalDistance ASC
LIMIT 1
my nodes are: Location with properties LocationID and LocationName
my relationships are: CONNECTED_TO with property Distance
I have more than 6000 relationships
please note in the code above that I have limited to 1..5
when I do not define this limit, the query does not give any results (keeps on executing)
thanks

Yes it is possible with Cypher or with a dedicated endpoint of the Neo4j ReST API.
BTW, the examples from the Cypher Neo4j documentation are self explaining :
http://neo4j.com/docs/milestone/query-match.html#_shortest_path
To get the shortestPath between two nodes :
MATCH (from: Location {LocationName:"x"}), (to: Location {LocationName:"y"}) ,
path = shortestPath((from)-[:CONNECTED_TO*]->(to))
RETURN path
If you want to get all the shortest
MATCH (from: Location {LocationName:"x"}), (to: Location {LocationName:"y"}) ,
paths = allShortestPaths((from)-[:CONNECTED_TO*]->(to))
RETURN paths
If you want to order by the length (number of hops) of the paths in descending order :
MATCH (from: Location {LocationName:"x"}), (to: Location {LocationName:"y"}) ,
paths = allShortestPaths((from)-[:CONNECTED_TO*]->(to))
RETURN paths
ORDER BY length(paths) DESC
If you to to get the shortestPath + the sum of the relationship distance property :
MATCH (from: Location {LocationName:"x"}), (to: Location {LocationName:"y"}) ,
path = shortestPath((from)-[:CONNECTED_TO*]->(to))
WITH REDUCE(dist = 0, rel in rels(path) | dist + rel.distance) AS distance, p
RETURN p, distance

Another way to perform the query:
install "APOC" in neo4j
https://neo4j-contrib.github.io/neo4j-apoc-procedures/#utilities
MATCH (start:node {name:'First_node_name'}), (end:node {name: 'end_node_name'})
CALL apoc.algo.dijkstra(start, end, 'weight_property',1.0) YIELD path, weight
return path, weight
P.S.
'weight_property' this is PropertyName which must have your relationship (weight_property=225454)
returned two values:
path - this is the path that was found;
weight - summary number of weight that was colculated from each relationship

Related

How to find the shortest path with multiple nodes and multiple relationships in Neo4j

I am not an expert in Cypher but I'm in a project where I have several nodes with the following properties:
['COGAB11', 'COGAB7', 'COGAB30', 'COGAB32', 'COGAB94', 'COGAB70',
'COGAB01', 'COGAB04', 'COGAB91', 'COG1AB77', 'COGAB46', 'COGAB40',
'COGAB31', 'COGAB14']
and between them there are several relationships:
[rel:coexpression|cooccurence|database|experimental|
fusion|neighborhood|score|textmining]
which also have a property like score which is a numerical integer value of 0-1000 and I would like to find the shortest path between all these nodes and get the relationships with a score greater than and equal to 500 between them. Therefore, I would like to return the graph with these relationships and path. However, I have only found a query of the shortest path but between two nodes and not between multiple nodes and multiple relationships. Additionally, I'm not sure if I should use APOC for this.
MATCH (start:Loc{name:'A'}), (end:Loc{name:'F'})
CALL algo.shortestPath.stream(start, end, 'cost')
YIELD nodeId, cost
RETURN algo.asNode(nodeId).name AS name, cost
If you mean that you want each relationship to have a score >= 500, then this should return the shortest path:
MATCH (start:Loc {name: 'A'}), (end:Loc {name: 'F'}),
p = SHORTESTPATH((start)-[:coexpression|cooccurence|database|experimental|fusion|neighborhood|score|textmining]-(end))
WHERE ALL(r IN RELATIONSHIPS(p) WHERE r.score >= 500)
RETURN p

I try to get the shortest way between nodes, count certain nodes on the way and return the targets along with the start

I have a problem in with cypher and could not solve it by myself. What I want seems to be very complex:
I have specified a node by ID. Then I want the shortest route to other nodes of the same type, but under certain conditions. Then I want to count certain nodes on the way. Finally, I want to return the starting node along with the goals.
My query so far looks like this:
MATCH path=(location:Location)-[:CanTravel*1..4]-(property:Gate)<-[:CanTravel]-(destination:Location)
WHERE property.size IN ['medium', 'large'] AND location.name = 'Ellis'
RETURN nodes(path)
The actual result looks like this:
enter image description here
The result have to look like this:
locations: [
{
name: abc,
travels: 0
},
{ name: def,
travels: 1
},
and so far
]
Hope anyone can help me :/
Regards, Cavez
EDIT:
result:
MATCH path=(location:Solarsystem)-[:CanTravel*1..6]-(property:JumpPoint)<-[:CanTravel]-(destination:Solarsystem)
WHERE property.size IN ['large'] AND location.name = 'Ellis'
WITH location, destination, min(size([node in nodes(path) where
node:JumpPoint])) as travels
WITH location, collect({name:destination, travels:travels}) as locations,
Collect(destination) + location as nodes
WITH locations + {name:location, travels:0} as locations, nodes
UNWIND nodes as n
RETURN n, locations
EDIT 2:
I still have one more thing: I find it confusing that the following result comes out with this query. Again a look at the picture I attached:
MATCH path=(location:Solarsystem)-[:CanTravel*1..6]-(jumpPoint:JumpPoint)<-[:CanTravel]-(destination:Solarsystem)
WHERE jumpPoint.size IN ['small'] AND location.name = 'Ellis'
RETURN path
https://www.instpic.de/g2yycmgQZOGKmEsIOEeI.PNG
My expected result is: No results, because I have only filtered a path with small sizes and the start 'Ellis' is not connected with any Gate with the size of small...
You should be able to get the number of :Gate nodes in the path with a simple filtering of path nodes:
MATCH path=(location:Location)-[:CanTravel*1..4]-(property:Gate)<-[:CanTravel]-(destination:Location)
WHERE property.size IN ['medium', 'large'] AND location.name = 'Ellis'
RETURN location.name as start, collect({name:destination.name, travels:size([node in nodes(path) where node:Gate])}) as locations
EDIT
Okay, so let's make sure we have only the shortest path to each destination, and then add in the current location to the collection too, with travels:0
MATCH path=(location:Location)-[:CanTravel*1..4]-(property:Gate)<-[:CanTravel]-(destination:Location)
WHERE property.size IN ['medium', 'large'] AND location.name = 'Ellis'
WITH location as start, destination, min(size([node in nodes(path) where node:Gate])) as travels
WITH start, collect({name:destination.name, travels:travels}) as locations
WITH locations + {name:start.name, travels:0} as locations
RETURN locations
EDIT 2
Regarding your jumppoint query, the reason you're getting that result is because you aren't filtering all :JumpPoints in the path, you're only filtering on the last :JumpPoint before your destination. If you want to filter all :JumpPoints, you'll need to do that explicitly, with something like:
WHERE all(jump in [node in nodes(path) where node:JumpPoint] WHERE jump.size in ['small']) and ...

Cypher set where condition only one relation can show of each node in the path

I got a graph with circular type relationship. So there may have two different direction relationships (outgoing and incoming) between each node in my graph. I am trying to find the path between two nodes without using shortestpath(). How to give the condition to set only 1 relationship will show between each node in the path? Here is my query:
Match p = (A)-[r*]-(b) return p
What should I write for where part?
So what yo really want is shortest weighted path. Cypher doesn't directly support this yet, but you can query it like this
MATCH (start:Point {id: '1'}), (end:Point {id: '2'})
MATCH p=(start)-[:GO_TO*1..25]->(end)
WITH p,reduce(s = 0, r IN rels(p) | s + r.myValueProp) AS dist
RETURN p, dist ORDER BY dist DESC LIMIT 1

Filtering nodes and edges neo4j on shortest path

Is there a way to run the shortest path algorithm in Neo4J whilst filtering on the edges or nodes with a > operator.
Say filtering on nodes with a higher of something timestamp?
Cheers
To some extent, you can use query predicates for this (http://neo4j.com/docs/3.0.1/query-predicates.html).
Here is an example using the built-in example movie graph. The query finds shortest paths from one Movie to another and filters paths which go through Kevin Bacon.
MATCH p = shortestPath((m1:Movie)-[*]-(m2:Movie))
WHERE m1.title = 'The Birdcage' AND m2.title = 'Sleepless in Seattle'
AND ANY(x in nodes(p) WHERE x.name = 'Kevin Bacon')
RETURN p

Find paths covering all nodes in neo4j

How do we find out paths in neo4j which will cover all the selected set of nodes.
This will be used for solving a tsp of sorts. to find path which covers all the given set of cities, later will sort on the basis of total distance covered by the path.
You can find all paths between two nodes like this.
match p=(:startNode)-->(:endNode)
return p;
or you can try like
match p=(:startNode)-->(:endNode)
return nodes(p) as node, relationships(p) as rels
You can get all paths like this
match p = ()-->()
return p
limit 100 // Apply limit according to nodes

Resources