pitagoras3
pitagoras3

Reputation: 2616

How to get all unique paths between two nodes?

I'm using trek and mountaineering routing database and I try to find all possible routes between Darjeeling and Sandakphu.

That is not a problem - here is query for that:

MATCH allPaths=(town:town{name:'Darjeeling'})-[*]->(peak:peak{name:'Sandakphu'})
RETURN allPaths

But this query returns same routes multiple times, for example:

╒══════════════════════════════════════════════════════════════════════╕
│"allPaths"                                                            │
╞══════════════════════════════════════════════════════════════════════╡
│[{"name":"Darjeeling"},{"name":"Darjeeling-Rimbik","winter":"true","di│
│stance":15,"summer":"true"},{"name":"Rimbik"},{"name":"Rimbik"},{"name│
│":"Rimbik-Sirikhola","winter":"true","distance":4,"summer":"true"},{"n│
│ame":"Sirikhola"},{"name":"Sirikhola"},{"name":"Sirikhola-Gurdum","win│
│ter":"true","distance":6,"summer":"true"},{"name":"Gurdum"},{"name":"G│
│urdum"},{"name":"Gurdum-Sandakphu","winter":"true","distance":12,"summ│
│er":"true"},{"name":"Sandakphu","altitude":"12400 ft"}]               │
├──────────────────────────────────────────────────────────────────────┤
│[{"name":"Darjeeling"},{"name":"Darjeeling-Rimbik","winter":"true","di│
│stance":15,"summer":"true"},{"name":"Rimbik"},{"name":"Rimbik"},{"name│
│":"Rimbik-Sirikhola","winter":"true","distance":4,"summer":"true"},{"n│
│ame":"Sirikhola"},{"name":"Sirikhola"},{"name":"Sirikhola-Gurdum","win│
│ter":"true","distance":6,"summer":"true"},{"name":"Gurdum"},{"name":"G│
│urdum"},{"name":"Gurdum-Sandakphu","winter":"true","distance":12,"summ│
│er":"true"},{"name":"Sandakphu","altitude":"12400 ft"}]               │
├──────────────────────────────────────────────────────────────────────┤

I've tried to use DISTINCT on RETURN as it is mentioned in documentation

MATCH allPaths=(town:town{name:'Darjeeling'})-[*]->(peak:peak{name:'Sandakphu'})
RETURN DISTINCT allPaths

but unfortunately it doesn't work.

Upvotes: 0

Views: 152

Answers (2)

InverseFalcon
InverseFalcon

Reputation: 30397

Neo4j can't return the same route multiple times, that shouldn't be possible. The paths should be distinct, and the same result set when using RETURN DISTINCT allPaths proves it.

EDIT

Using the same data set I recreated this. The paths are distinct. What's throwing you off is that that there are multiple relationships between the same sets of nodes (for example, between Tumbling and Gairibus there are 3 relationships, of types :trek, :road, and :twowheeler) which all have the same properties.

In the Neo4j browser, when displaying the textual data of a relationship only the relationship properties are outputted, not the type or id, so simply doing a visual inspection of the relationship results (such as the relationships present in the path) makes it seem as if the paths are identical, but they are not.

The actual code results (if you were using a driver to call into Neo4j and fetch query results) would include ids and relationship type information, so it's just the browser's visual display that omitting the info that would differentiate the results.

There are 156 distinct paths you could use, but these will mostly be through the same nodes, just using permutations of different possible relationships to traverse the nodes.

If you want paths that ignore these relationship choices, then confine your query to :trek relationships, as these are always present when two nodes are connected:

MATCH path=(town:town{name:'Darjeeling'})-[:trek*]->(peak:peak{name:'Sandakphu'})
RETURN path

This returns only 6 possible paths.

Upvotes: 1

terryf82
terryf82

Reputation: 91

Have you tried aliasing the relationship, and then returning that (and only that) distinctly?

match (town:town{name:'Darjeeling'})-[r]->(peak:peak{name:'Sandakphu'})
return distinct r

Also while it isn't enforced, the convention in Neo4J is to create labels in UpperCamelCase (Town rather than town, Peak rather than peak).

Upvotes: 0

Related Questions