I am building an application that should accept quite general input and be able to generate quite elaborate Cypher queries. I get stuck on the following:
Suppose we have the following example database:
CREATE (John {name:'John Doe', age:30})-[:HAS_AUTOGRAPH]->(Joe {name:'Joe'})-[:IS_NICKNAME_OF]->({name:'Joseph Quinn'}), (John)-[:LIVES_NEARBY]->(Joe)
I would now like to find all persons that either (have age > 50) or (live near Joseph and have Joseph's autograph), for which I thought of building the following query:
MATCH (n) WHERE
n.age > 50 OR EXISTS {
MATCH
(n)-[:HAS_AUTOGRAPH]->()-[:IS_NICKNAME_OF*0..1]->({name:'Joseph Quinn'}),
(n)-[:LIVES_NEARBY]->()-[:IS_NICKNAME_OF*0..1]->({name:'Joseph Quinn'})
} RETURN n.name
which should return John Doe. However, it does not, because the IS_NICKNAME_OF relationship cannot be used more than once in the EXISTS match. (Yes I did think of implementing the IS_NICKNAME_OF in a different way but that gave other difficulties)
The standard way to circumvent this (in this case unwanted) effect of relationship isomorphism is by using extra matches: Instead of
MATCH
(n)-[:HAS_AUTOGRAPH]->()-[:IS_NICKNAME_OF*0..1]->({name:'Joseph Quinn'}),
(n)-[:LIVES_NEARBY]->()-[:IS_NICKNAME_OF*0..1]->({name:'Joseph Quinn'})
RETURN n
one writes
MATCH (n)-[:HAS_AUTOGRAPH]->()-[:IS_NICKNAME_OF*0..1]->({name:'Joseph Quinn'})
MATCH (n)-[:LIVES_NEARBY]->()-[:IS_NICKNAME_OF*0..1]->({name:'Joseph Quinn'})
RETURN n
to obtain the result without the use of relationship isomorphism.
However, this does not work in an EXISTS clause, and the following gives a syntax error:
MATCH (n) WHERE
n.age > 50 OR EXISTS {
MATCH (n)-[:HAS_AUTOGRAPH]->()-[:IS_NICKNAME_OF*0..1]->({name:'Joseph Quinn'})
MATCH (n)-[:LIVES_NEARBY]->()-[:IS_NICKNAME_OF*0..1]->({name:'Joseph Quinn'})
} RETURN n.name
Any suggestions on how to do this are very much appreciated!