Search code examples
neo4jcypher

Retrieve nodes where all relationships match a criteria in neo4j


I'm trying to retrieve nodes where none of the relationships to that node have a specific property value. For example, I would like the query to return foo in the following example, because both relationships to foo have prop = false.

(bar0) -[{prop:false}]-> (foo) <-[{prop:false}]- (bar1)

On the other hand, I would like the query to return null in the following example, because a subset of the relationships to foo have prop = true.

(bar0) -[{prop:false}]-> (foo) <-[{prop:true}]- (bar1)

So far, I've tried:

MATCH (foo)-[r]-(bar)
WITH collect(r) as rs, foo, bar
WHERE NONE(r in rs WHERE r.prop = True)
UNWIND rs as r
RETURN foo, bar, r

However, this still returns foo, it just removes the relationship where prop = True.

I also tried using CASE, but run into the same problem.

MATCH (foo)-[r]-(bar)
WITH collect(r) as rs, foo
RETURN
CASE 
WHEN ALL(r in rs WHERE r.prop=False)
    THEN foo
ELSE null
END

Ideally, the query would also return nodes with no relationships as well, but I can also handle that with a separate query.


Solution

  • This query uses the EXISTS() function to avoid having to scan all relationships to every Foo node to find the ones of interest. It filters out a Foo node as soon as a true relationship is found.

    MATCH (foo:Foo)
    WHERE NOT EXISTS((foo)<-[{prop: true}]-())
    MATCH (foo)<-[r]-(bar)
    RETURN foo, bar, r
    

    This query also uses a directional relationship, to conform to the stated data model.