Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.
08-20-2020 01:51 PM
I would like to find the shortest path between two nodes that requires that a path be routed through a particular node type. Imagine the following situation:
From my current understanding, none of the current shortest path algorithms would support this kind of condition, and I can't seem to find a way to formulate a Cypher query. Any thoughts from the Neo4j brain-trust?
Here is a more concrete example of the problem:
CREATE (a:City {name: 'Atlanta'}),
(b:City {name: 'Boston'}),
(c:City {name: 'Chicago'}),
(m:Town {name: 'Monroe'}),
(n:Town {name: 'Napier'}),
(u:Village {name: 'Unitas'}),
(v:Village {name: 'Vincennes'}),
(u)-[:ROAD]->(m),
(m)-[:ROAD]->(b),
(m)-[:ROAD]->(v),
(b)-[:ROAD]->(a),
(b)-[:ROAD]->(c),
(b)-[:ROAD]->(n),
(a)-[:ROAD]->(c),
(c)-[:ROAD]->(n),
(n)-[:ROAD]->(v)
leads to this graph structure:
The path I'd like to return is:
Cypher is too general but guarantees inclusion of the city:
MATCH pw = (u:Village {name:'Unitas'})-[*]->(q:City)-[*]->(v:Village {name:'Vincennes'})
RETURN pw
This above query returns the entire graph as defined by the setup (1).
MATCH (u:Village {name: 'Unitas'}), (v:Village {name: 'Vincennes'})
CALL gds.alpha.shortestPath.stream({
nodeProjection: ['City','Town','Village'],
relationshipProjection: 'ROAD',
startNode: u,
endNode: v
})
YIELD nodeId, cost
RETURN gds.util.asNode(nodeId)
This just returns the actual shortest path:
(Unitas)->(Monroe)->(Vincennes)
Any thoughts and help appreciated!
BONUS:
I'd also like to be able to do something like the following pseudocode:
MATCH mypath = (startNode)-<ARBITRARY CYPHER QUERY MIDDLE>-(endNode)
CALL shortestPath {
mypath, #contains the subgraph returned from the MATCH above
startNode:startNode,
endNode:endNode
}
YIELD ...
RETURN ...
Thanks in advance to the community!
-jake
Solved! Go to Solution.
08-21-2020 04:33 AM
Hi @jaketeyjake,
This query should do what you are aiming for. You can create the paths and then look for the one with less hops (w/o library).
The condition may change according your needs (any/all/single).
MATCH path = (u:Village {name:'Unitas'})-[*]->(v:Village {name:'Vincennes'})
with nodes(path) as pw
where any(n in pw WHERE n:City)
RETURN pw, size(pw)
order by size(pw) asc limit 1
H
08-21-2020 04:33 AM
Hi @jaketeyjake,
This query should do what you are aiming for. You can create the paths and then look for the one with less hops (w/o library).
The condition may change according your needs (any/all/single).
MATCH path = (u:Village {name:'Unitas'})-[*]->(v:Village {name:'Vincennes'})
with nodes(path) as pw
where any(n in pw WHERE n:City)
RETURN pw, size(pw)
order by size(pw) asc limit 1
H
All the sessions of the conference are now available online