Reputation: 1121
Similar to Cypher query to find nodes that are not related to other node by property, but different enough to stump me so far.
A Person is eligible for a Task if they meet the Language requirement and doesn't already have a relationship to it (e.g., doing or rejected).
Tasks can depend on each other and 'inherit' their language through 0 or more DEPENDS_ON
rels and the 'root' Task's REQUIRES
.
I'm trying to create a query that will find that…
p1
is eligible for t2
and t4
p2
is eligible for all 4p3
is not eligible for anyNot even worrying about t1
's done-ness yet, I don't think I'm getting through/past the Language 'inheritance.'
For example, for p2
:
MATCH (p:Person {name: 'p2'})-[:SPEAKS]->(lang)
WITH p, collect(lang) AS langs
MATCH (t:Task)-[:DEPENDS_ON*0]->(:Task)-[:REQUIRES]->(lang:Language)
WHERE lang IN langs
RETURN t
finds 0 rows
MATCH (p:Person {name: 'p2'})-[:SPEAKS]->(lang)
RETURN lang
gets both Languages, so I'm (pretty?) sure that collect(lang) as langs
is what I want.
Removing the :DEPENDS_ON*
links
MATCH (p:Person {name: 'p2'})-[:SPEAKS]->(lang)
WITH p, collect(lang) AS langs
MATCH (t:Task)-[:REQUIRES]->(lang:Language)
WHERE lang in langs
RETURN t
gets me t1
, t2
, and t3
.
How can I get t4
, too?
TIA!
Upvotes: 0
Views: 149
Reputation: 2507
You can traverse paths much more flexibly than that. Finding the path from a person to a task through a shared language node is all one path pattern, even if different instances of the path can route through separate languages. You can then extend it using a 0+ variable length path to find tasks that depend on a given task. Finally, filter out any paths where the task relates back to the person using one of the invalid. relationships.
MATCH (p:Person) - [:SPEAKS] -> (:Language) <- [:REQUIRES] - (:Task) <- [:DEPENDS_ON*0..] - (t:Task)
WHERE NOT (t) <- [:IS_DOING|:REJECTED] - (p)
RETURN p, COLLECT(DISTINCT t)
Upvotes: 2