15

Given a query like the following:

START n = node(123)
MATCH p = n-[r:LIKES*..3]->x
RETURN p;

The result paths that I get with the query above contain cycles.

How can I return only simple paths?

Given this example:

  • How can I avoid paths with repeated nodes like: [Neo, Morpheus, Trinity, Morpheus, Neo]
Koedlt
  • 4,286
  • 8
  • 15
  • 33
Marsellus Wallace
  • 17,991
  • 25
  • 90
  • 154

3 Answers3

16

Specifying the uniqueness of paths is a planned feature of cypher.

So right now we have to ascertain that no node is a duplicate in the path.

There is an ALL predicate that must hold true for all elements of a collection (which a path is). And with filter you can extract the elements of an collection for that a certain condition holds true.

START neo=node(1) 
MATCH path= neo-[r:KNOWS*..4]->other 
WHERE ALL(n in nodes(path) where 
          1=length(filter(m in nodes(path) : m=n))) 
RETURN neo, LENGTH(path) AS length, EXTRACT(p in NODES(path) : p.name), other 
ORDER BY length

So what I did was:

  • For all nodes of the path n
  • Filter the path for the nodes that are equal to n
  • determine the length of that collection
  • assert with ALL that it has to be ONE for each n

see: http://console.neo4j.org/r/dpalbl

Michael Hunger
  • 41,339
  • 3
  • 57
  • 80
  • Hi Michael, Is there any other better way to identify cycles in path. The solution shared above by you, works fine but, is costly in terms of time & db hits. Can u please check? – Hemant Apr 30 '15 at 06:20
  • While working with Neo4j 2.2.5 I had to change the filter part to `filter(m in nodes(path) WHERE m=n))` – Daniel Olszewski Oct 08 '15 at 14:45
  • 1
    Hi. Does anyone know of any updates on this in the 3.0 release? – imran arshad Jun 15 '16 at 00:30
  • 1
    For graph:`create (n:ent {id:'a'})-[:rel]->(:ent {id:'b'})-[:rel]->(o:ent {id:'c'})-[:rel]->(p:ent {id:'d'})-[:rel]->(:ent {id:'e'})-[:rel]->(n),(p)-[:rel]->(o)`, the query `MATCH path=(ent{id:'a'})-[:rel*0..]->(ent) WHERE ALL(n in nodes(path) WHERE 1=length(filter(m in nodes(path)WHERE m=n))) RETURN path` gives `key not found: UNNAMED25` error!!! – Mahesha999 Jun 29 '17 at 11:05
3

my workaround for this:

START n = node(123), x=node(*)
MATCH p = shortestPath(n-[r:LIKES*..3]->x)
RETURN p;

see the example in console

ulkas
  • 5,748
  • 5
  • 33
  • 47
  • 1
    This might work in the given example but I'm actually interested in all possible paths (not only the shortest one/s) within a given length with no nodes repeated along the way. thanks – Marsellus Wallace Dec 14 '12 at 14:35
2

In 2.3.0, use the following:

MATCH path = (start {id:2})<-[*1..]-(end {id:3}) 
WHERE ALL(n in nodes(path) where 
          1 = size(filter(m in nodes(path) where m=n))) 
RETURN start, LENGTH(path) AS length, EXTRACT(p in NODES(path) | p.id), end
ORDER BY length
Roger Collins
  • 1,188
  • 1
  • 8
  • 12