Cypher: Matching nodes at arbitrary depth via a st

2019-09-13 06:04发布

问题:

I'm quite new to Cypher but struggling to find how to do this. I want to generalise the following so that it will match at an arbitrary depth.

MATCH (:start)-[:a]-()-[:b]-(:end) //Depth1
MATCH (:start)-[:a]-()-[:b]-()-[:a]-()-[:b]-(:end) //Depth2
MATCH (:start)-[:a]-()-[:b]-()-[:a]-()-[:b]-()-[:a]-()-[:b]-(:end) //Depth3
MATCH (:start)-[:a]-()-[:b]-()-[:a]-()-[:b]-()-[:a]-()-[:b]-()-[:a]-()-[:b]-(:end) //Depth4

In other words, the path needs to pass through any number of a-node-b in strict alternation; a-node-a etc. will not work. So I can't do this, as per Neo4J: find a sub-graph of arbitrary depth with nodes connected by a given set of relations?

MATCH (:start)-[:a|b*]-(:end)

because that would match things like this:

MATCH (:start)-[:a]-()-[:a]-(:end)
MATCH (:start)-[:b]-()-[:b]-(:end)

Does anyone know how to solve this? I'm using Cypher with Neo4j 2.x if it matters.

Thanks!

回答1:

The strict answer is no, this is not possible in Cypher. The stretched answer is: it's possible to determine whether such a path exists, and to return the nodes on either end of the path, but it's slow and you won't get to keep some of the information along the path.

MATCH (first) - [:a] -> () - [:b] -> (third)
MERGE (first) - [temp:c] -> (third)
WITH COLLECT(temp) AS temps
MATCH p = (:start) - [:c*] -> (:end)
WITH temps, COLLECT(p) AS ps
FOREACH(temp IN temps)|DELETE temp)
UNWIND ps AS p
RETURN DISTINCT p

This does require you to have a :c or other relationship type that you can use as a temp here.