Reputation: 3191
I would like to match certain paths in my graph. These good paths should not contain certain subpaths, e.g. avoiding certain nodes. For example, given the graph
a->b->c->d
a->avoid1->b
c->avoid2->d
NB: There could be many more nodes in between the edges I specified, e.g. a->t0->t1->b
or a->avoid1->t2->b
.
Now I would like to get all paths from a to d which do not contain certain subpaths, to be precise, those subpaths going from a
over avoid1
to b
and from c
over avoid2
to d
.
My current (insufficient) approach is to MATCH the entire path I am looking for and then specifying the node I want to avoid:
MATCH p=(a)-[:CF*]->(b)-[:CF*]->(c)-[:CF*]->(d)
WHERE NOT (avoid1 IN nodes(p))
This is not working out for me because I actually need to "filter out" subpaths and not nodes.
I need something like this:
MATCH p=(a)-[:CF*]->(b)-[:CF*]->(c)-[:CF*]->(d)
WHERE NOT ( (a)-[:CF*]->(avoid1)->[:CF*]->(b) IN p) AND NOT ( (c)-[:CF*]->(avoid2)->[:CF*]->(d) )
This does not work, I know but it could help to explain what I need: a way to filter out paths based on the fact if they contain certain subpaths.
EDIT:
Here are the commands:
MERGE (a:MYTYPE { label:'a' })
MERGE (b:MYTYPE { label:'b' })
MERGE (c:MYTYPE { label:'c' })
MERGE (d:MYTYPE { label:'d' })
MERGE (avoid1:MYTYPE { label:'avoid1' })
MERGE (avoid2:MYTYPE { label:'avoid2' })
CREATE (a)-[:CF]->(b)
CREATE (b)-[:CF]->(c)
CREATE (c)-[:CF]->(d)
CREATE (a)-[:CF]->(avoid1)
CREATE (avoid1)-[:CF]->(b)
CREATE (c)-[:CF]->(avoid2)
CREATE (avoid2)-[:CF]->(d)
and my current try (as suggested by dave's answer):
MATCH (a:MYTYPE { label:'a' })
MATCH (b:MYTYPE { label:'b' })
MATCH (c:MYTYPE { label:'c' })
MATCH (d:MYTYPE { label:'d' })
MATCH (avoid1:MYTYPE { label:'avoid1' })
MATCH (avoid2:MYTYPE { label:'avoid2' })
MATCH p=(a)-[:CF*]->(b)-[:CF*]->(c)-[:CF*]->(d)
WHERE NOT ( (a)-[:CF*]->(avoid1 {label:'avoid1'})-[:CF*]->(b) )
RETURN p
Yet, this gives me "(no rows)".
Upvotes: 1
Views: 764
Reputation: 878
This query should allow you to filter on paths:
MATCH p=(a)-[:CF*]->(b)-[:CF*]->(c)-[:CF*]->(d)
WHERE NOT ( (a)-[:CF*]->()-[:CF*]->(b))
AND NOT ( (c)-[:CF*]->()-[:CF*]->(d) )
return p;`
You could also specify a label/property for the node that you want to filter on:
MATCH p=(a)-[:CF*]->(b)-[:CF*]->(c)-[:CF*]->(d)
WHERE NOT ( (a)-[:CF*]->(:Person {name:'Dave'})-[:CF*]->(b)) AND NOT ( (c)-[:CF*]->()-[:CF*]->(d) )
return p;
Upvotes: 1