Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.
07-18-2022 02:45 AM - edited 07-18-2022 02:59 AM
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!
Solved! Go to Solution.
07-18-2022 04:46 AM
The answer is obvious after a little bit of pondering.
Instead of this:
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
I just do this:
WHERE n.age > 50 OR (EXISTS {
MATCH (n)-[:HAS_AUTOGRAPH]->()-[:IS_NICKNAME_OF*0..1]->({name:'Joseph Quinn'})
} AND EXISTS {
MATCH (n)-[:LIVES_NEARBY]->()-[:IS_NICKNAME_OF*0..1]->({name:'Joseph Quinn'})
}) RETURN n.name
Which does generalize to all cases that my application needs to handle.
07-18-2022 04:46 AM
The answer is obvious after a little bit of pondering.
Instead of this:
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
I just do this:
WHERE n.age > 50 OR (EXISTS {
MATCH (n)-[:HAS_AUTOGRAPH]->()-[:IS_NICKNAME_OF*0..1]->({name:'Joseph Quinn'})
} AND EXISTS {
MATCH (n)-[:LIVES_NEARBY]->()-[:IS_NICKNAME_OF*0..1]->({name:'Joseph Quinn'})
}) RETURN n.name
Which does generalize to all cases that my application needs to handle.
07-18-2022 05:10 AM
MATCH (n) WHERE
n.age > 50
OR
(EXISTS ((n)-[:HAS_AUTOGRAPH]->()-[:IS_NICKNAME_OF*0..1]->({name:'Joseph Quinn'}))
AND
EXISTS ((n)-[:LIVES_NEARBY]->()-[:IS_NICKNAME_OF*0..1]->({name:'Joseph Quinn'})))
RETURN n.name
07-18-2022 06:04 AM
This does seem to be similar to what I typed, but you used parentheses "()" instead of curly brackets "{}". Is there any reason why you prefer parentheses over curly brackets in the exists clause?
07-18-2022 07:41 AM
The curly brackets represent a subquery. Your subquery contains a 'match'. In my syntax, I am using the 'exists' as a method and passing it a pattern expression as a parameter. My syntax works for a single pattern match. You would need a subquery if the 'existence' requires serval match statements. They should realize the same result.
All the sessions of the conference are now available online