I have 3 labels, A, B, and Z. A & B both have a relationship to Z. I want to find all the A nodes that do not have share any of nodes Z in common with B
Currently, doing a normal query where the relationship DOES exist, works.
MATCH (a:A)-[:rel1]->(z:Z)<-[:rel2]-(b:B { uuid: {<SOME ID>} })
RETURN DISTINCT a
But when I do
MATCH (a:A)
WHERE NOT (a)-[:rel1]->(z:Z)<-[:rel2]-(b:B { uuid: {<SOME ID>} }))
RETURN DISTINCT a
It throws an error
Neo4j::Server::CypherResponse::ResponseError: z not defined
Not sure if the syntax for this is incorrect, I tried WHERE NOT EXIST()
but no luck.
The query is part of a larger one called through a rails app using neo4jrb / (Neo4j::Session.query)
This is a problem to do with the scope of your query. When you describe a node in a MATCH
clause like the below
MATCH (n:SomeLabel)
You're telling cypher to look for a node with the label SomeLabel
, and assign it to the variable n
in the rest of the query, and at the end of the query, you can return the values stored in this node using RETURN n
(unless you drop n
by not including it in a WITH
clause).
Later on in you query, if you want to MATCH
another node, you can do it in reference to n
, so for example:
MATCH (m:SomeOtherLabel)-[:SOME_RELATIONSHIP]-(n)
Will match a variable connected (in any direction) to the node n
, with a label SomeOtherLabel
, and assign it to the variable m
for the rest of the query.
You can only assign nodes to variables like this in MATCH
, OPTIONAL MATCH
, MERGE
, CREATE
and (sort of) in WITH
and UNWIND
clauses (someone correct me here if I've missed one, I suppose you also do this in list comprehensions and FOREACH
clauses).
In your second query, you are trying to find a node with the label A
, which is not connected to a node with the label Z
. However, the way you have written the query means that you are actually saying find a node with label A
which is not connected via a rel1
relationship to the node stored as z
. This will fail (and as shown, neo complains that z
is not defined), because you can't create a new variable like this in the WHERE
clause.
To correct your error, you need to remove the reference to the variable z
, and ensure you have also defined the variable b
containing your node before the WHERE
clause. Now, you keep the label in the query, like the below.
MATCH (a:A)
MATCH (b:B { uuid: {<SOME ID>} })
WHERE NOT (a)-[:rel1]->(:Z)<-[:rel2]-(b) // changed this line
RETURN DISTINCT a
And with a bit of luck, this will now work.