MichaelE
MichaelE

Reputation: 767

Neo4j - WHERE negation on path not working

MATCH (n:Owner) MATCH (v:Vehicles)
WHERE NOT (n)-[:OWNS]->(v)
RETURN  DISTINCT n.email, n.name ORDER BY n.name

and

MATCH (n:Owner) MATCH (v:Vehicles)
WHERE  (n)-[:OWNS]->(v)
RETURN  DISTINCT n.email, n.name ORDER BY n.name

is giving me the same result...What am I missing here?

On the other hand this works:

MATCH (n:Owner) MATCH (v:Vehicles)
WHERE NOT (n)-[:OWNS]-()
RETURN  DISTINCT n.email

Upvotes: 1

Views: 86

Answers (2)

MissingNumber
MissingNumber

Reputation: 1182

Note: This is an extension of @raj Answer, with more focus on the explaining issue.

This query is wrong and may return undesired results.

To understand take following example as data-set:

Owner       Vehicle
P1          V1
P2          V2
P3          V3

Since you are doing

MATCH (n:Owner) MATCH (v:Vehicles)

This results in Cartesian product for the two matches like this first 2 columns

Owner   Vehicle         NOT (n)-[:OWNS]->(v)    (n)-[:OWNS]->(v)

P1      V1              -                       P1
P2      V1              P2                      -
P3      V1              P3                      -
P1      V2              P1                      -
P2      V2              -                       P2
P3      V2              P3                      -
P1      V3              P1                      -
P2      V3              P2                      -
P3      V3              -                       P3

Now on filtering with NOT (n)-[:OWNS]->(v) gives (P1,P2,P3,P1,P2,P3)

Now on filtering with (n)-[:OWNS]->(v) gives (P1,P2,P3)

Now on returning distinct with NOT (n)-[:OWNS]->(v) gives (P1,P2,P3)

Now on returning distinct with (n)-[:OWNS]->(v) gives (P1,P2,P3)

Clearly these two are ending up being same right??

But note that this would only be true when all owners has at-least a vehicle and no owner owns all vehicle.

So this is what you can do to find owners without vehicles.

MATCH (a:Owner)
WHERE SIZE((a)-[:OWNS]->(:Vehicles)) = 0 
RETURN a

Upvotes: 4

Rajendra Kadam
Rajendra Kadam

Reputation: 4052

It looks fine to me.

It's recommended I think both WHERE and Negation are working as expected. And there is a high probability that both will give the same results.

Let me tell you when both give the same results:

Both of these queries will give the same results when all of the Owners have at least one Vehicle and None of the Owner owns all the Vehicle in the database And There is a high probability that this will be true in your case.

I assume you want to find users who don't own any Vehicle and return their name and email. And in the second query, you want user who owns a Vehicle and return their name and email.

If that's the case here are queries for same:

1. Find Owner who don't own any Vehicle

MATCH (n:Owner)
WHERE NOT (n)-[:OWNS]->(:Vehicles)
RETURN  DISTINCT n.email, n.name 
ORDER BY n.name

2. Owner who owns a Vehicle

MATCH (n:Owner)
WHERE (n)-[:OWNS]->(:Vehicles)
RETURN  DISTINCT n.email, n.name 
ORDER BY n.name

Upvotes: 3

Related Questions