Reputation: 1651
Is it possible to write a Cypher query with a variable-length patter, that specifies that nodes between the start and end node can only be nodes with a certain property?
I think that a query like the following would match all of the below patterns:
MATCH p=(n:Node {foo:"True"})<-[:REL*0..2]-(:Node)<-[:REL]-(:Node {bar:"True"})
(n:Node {foo:"True"}) <-[:REL]-(:Node {bar:"True"})
(n:Node {foo:"True"}) <-[:REL]-(:Node) <-[:REL]-(:Node {bar:"True"})
(n:Node {foo:"True"}) <-[:REL]-(:Node) <-[:REL]-(:Node) <-[:REL]-(:Node {bar:"True"})
I imagine it "copying" the <-[:REL]-(:Node)
part of the query 0 to 2 times in between the (n:Node {foo:"True"})
and <-[:REL]-(:Node {bar:"True"})
query parts and constructing some kind of UNION of the matches.
Is this the right way to think about it? And how would i make the variable-lenght query match only paths where the middle nodes have the property {bar:"True"}
in the middle nodes like so:
(n:Node {foo:"True"}) <-[:REL]-(:Node {bar:"True"})
(n:Node {foo:"True"}) <-[:REL]-({bar:"True}) <-[:REL]-(:Node {bar:"True"})
(n:Node {foo:"True"}) <-[:REL]-({bar:"True}) <-[:REL]-({bar:"True}) <-[:REL]-(:Node {bar:"True"})
Would the query below be the right approach?
MATCH p=(n:Node {foo:"True"})<-[:REL*0..2]-(:Node {bar:"True"})<-[:REL]-(:Node {bar:"True"})
It appears to me that this is not the case. Can somebody clearify on where I am going wrong in my thinking process?
Upvotes: 0
Views: 639
Reputation: 1125
MATCH path=(:Node {foo:True})-[:REL*0..2]-(n:Node {bar:True})
WHERE all(x in nodes(path) WHERE x.bar=True OR x.foo=True)
RETURN n.name
Upvotes: 1
Reputation: 1125
I think it'd be easy if foo were a relationship property, instead of a node property.
Create a simple example:
MERGE (a:Node {name:"a", foo:True})
MERGE (b:Node {name:"b", bar:True})
MERGE (c:Node {name:"c", bar:True})
MERGE (d:Node {name:"d", bar:False})
MERGE (e:Node {name:"e", bar:True})
MERGE (a)<-[:REL]-(b)
MERGE (b)<-[:REL]-(c)
MERGE (a)<-[:REL]-(d)
MERGE (d)<-[:REL]-(e)
I think you want to match nodes b and c, but not e because we'd have to traverse d which has foo:False.
Make bar a property on the relationships:
MATCH ()<-[r:REL]-(n:Node)
SET r.bar = n.bar
Now you can write:
MATCH (:Node {foo:True})<-[:REL*0..2 {bar:True}]-(n:Node)
RETURN n.name
Which returns b and c as required.
Upvotes: 0