Bob Mazanec
Bob Mazanec

Reputation: 1121

Cypher query to find nodes with some relationship(s), but not others

Similar to Cypher query to find nodes that are not related to other node by property, but different enough to stump me so far.

Persons, Languages, and Tasks

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…

Not 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

Answers (1)

Tore Eschliman
Tore Eschliman

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

Related Questions