Using IS NULL instead of NOT exists() doesn't work as expected

In the "Using WHERE to Filter Queries" chapter, the Testing with patterns - 2 example is

MATCH (p:Person)-[:WROTE]->(m:Movie)
WHERE NOT exists( (p)-[:DIRECTED]->(m) )
RETURN p.name, m.title

This works perfectly well and returns 6 results.

However, earlier in the Chapter, it is mentioned that the exists() function will be deprecated after v4.3, so I wanted to create the equivalent query using NULL instead. So I tried

MATCH (p:Person)-[:WROTE]->(m:Movie)
WHERE ( (p)-[:DIRECTED]->(m) ) IS NULL
RETURN p.name, m.title

but this returns no results. What have I done wrong?

Thanks for any help!

if you take your

MATCH (p:Person)-[:WROTE]->(m:Movie)
WHERE ( (p)-[:DIRECTED]->(m) ) IS NULL
RETURN p.name, m.title

and change to

MATCH (p:Person)-[:WROTE]->(m:Movie)
RETURN ( (p)-[:DIRECTED]->(m) ), p.name, m.title

you will see that for paths that do not exist for ( (p)-[:DIRECTED]->(m) ) this returns [] which is not the same as NULL

Hi Dana,

Thank you for the explanation; it makes sense. If I change the query to

MATCH (p:Person)-[:WROTE]->(m:Movie)
WHERE ( (p)-[:DIRECTED]->(m) ) =
RETURN p.name, m.title

I get the expected results :slight_smile:

However, this does mean that the suggestion to simply replace exists() with IS NOT NULL is not quite as straight forward as it seems!

Learning: check what's actually in the database rather than assuming it's a NULL :slightly_smiling_face:

Thank. you @ian.baker . We will make it clearer in the course how to test for the existence of a pattern.

Elaine

There are some changes coming, we don't want a pattern to evaluate to a list like this, so WHERE ( (p)-[:DIRECTED]->(m) ) = [] isn't how we want to express this restriction (plus it's really awkward and unintuitive).

I think we're keeping exists() for patterns, but we are deprecating it for property existence checks.

So WHERE NOT exists( (p)-[:DIRECTED]->(m) ) should be fine (and I think you can even go without the exists() here, so WHERE NOT (p)-[:DIRECTED]->(m) should still be fine)

But WHERE NOT exists(m.title) would be deprecated in favor of WHERE m.title IS NULL.