# Cypher: How can I find all the strings of simple nodes that are not repeated?

advertisements

I want to find ALL the paths starting and ending from/to a specific node. I would like that each node in a path appears only once.

For example, in a graph like this:

``````(a)-[:REL]->(b)-[:REL]->(c)-[:REL]->(a)
(a)-[:REL]->(e)-[:REL]->(f)-[:REL]->(a)
(e)-[:REL]->(b)
```
```

grafically:

``````  e → b
↙ ↖ ↗ ↘
f → a ← c
```
```

Cypher code:

``````CREATE (a { name:'A' })-[:REL]->(b {name:'B'})-[:REL]->(c { name:'C' })
-[:REL]->(a)-[:REL]->(e {name:'E'})-[:REL]->(f {name:'F'})-[:REL]->(a),
(e)-[:REL]->(b)
```
```

I would like that the research of chains starting from (a) returns

``````(a)->(b)->(c)->(a)

(a)->(e)->(f)->(a)

(a)->(e)->(b)->(c)->(a)
```
```

while starting from (f) returns only

``````(f)->(a)->(e)->(f)
```
```

and NOT

``````(f)->(a)->(b)->(c)->(a)->(e)->(f)
```
```

because it passes twice through the node (a).

I tryied:

``````MATCH p=(a {name:'F'})-[:REL*1..]->(a)
WHERE SINGLE(e1 IN TAIL(NODES(p)) WHERE SINGLE(e2 IN TAIL(NODES(p)) WHERE e1=e2))
RETURN p
```
```

but I've got no result. The best I've been able to reach is to have no repetition of just the start node with this query:

``````MATCH p=(a {name:'F'})-[:REL*1..]->(a)
WHERE SINGLE(e IN TAIL(NODES(p)) WHERE e=a)
RETURN p
```
```

but obviously it's not what I want because it returns also

``````(f)->(a)->(b)->(c)->(a)->(e)->(f)
```
```

that is a path involving the node (a) twice.

Can someone suggest me a solution?

Thank you in advance.

P.S. The version of Neo4j that I use is 2.0

On the shoulders of those who came before I have come up with:

``````MATCH (a { name:'A' })
MATCH (a)-[p:REL]->(s)
WITH a, s
MATCH p = s-[r:REL*]->a
WITH [a] + nodes(p) AS ns
WHERE ALL (n IN ns
WHERE 1=LENGTH(FILTER(m IN TAIL(ns)
WHERE m = n)))
RETURN ns
```
```

It utilises the idea from @FrobberOfBits to perform the initial steps and then the query linked from Michael to perform the filter on the paths. I suppose that the TAIL could be left out, if you also left out:

``````WITH [a] + nodes(p) AS ns
```
```

Which would make the query this maybe:

``````MATCH (a { name:'A' })
MATCH (a)-[p:REL]->(s)
WITH a, s
MATCH p = s-[r:REL*]->a
WITH a, nodes(p) AS ns
WHERE ALL (n IN ns
WHERE 1=LENGTH(FILTER(m IN ns
WHERE m = n)))
RETURN [a] + ns
```
```

The complicated or at least slightly hard to read part of the query is the `ALL` in combination with the `FILTER` which "basically" for all values in ns `(WHERE ALL (n in ns)` counts the number of occurences by comparing to all other values in the array (`m IN ns WHERE m = n`) and filters the result out completely if the resultant array does not contain a single element (`1=LENGTH`).

I added your example in the console here.