State of the Cypher UNION
Join the DZone community and get the full member experience.
Join For FreeNeo4j 2.0 introduced the UNION (ALL)
clause, which can join the results of 2 or more complete statements into a single result. Each of the statements is fully formed and contains result projection and pagination.
You need to have the same amount and names of columns to be joined in an UNION. UNION by default returns the distinct set of results.
Using UNION ALL
will return the full results (and will be faster and less memory intensive).
Here are two examples:
MATCH (d:Developer) RETURN d.name as name
UNION
MATCH (e:Employee) RETURN e.name as name
Most often UNION
is not needed and can be alleviated by a different graph model or query structure, but we’ll return to that later.
During a conversation with a partner of ours we found a pitfall that you might run into too. Let’s have a look at their query.
START n=node:Person(name={name})
MATCH (n)-[:MANAGES]->()-[:HAS_SKILL]->(s) RETURN s.name as name
UNION
MATCH (n)-[:HAS_SKILL]->(s) RETURN s.name as name
Looks harmless, right? The problem was it returned too much (unrelated) data.
What happened here? As we said, UNION
combines the outputs from two full statements. The two statements in this case are:
// statement one
START n=node:Person(name={name})
MATCH (n)-[:MANAGES]->()-[:HAS_SKILL]->(s) RETURN s.name as name
// statement two
MATCH (n)-[:HAS_SKILL]->(s) RETURN s.name as name
As you can see the first statement looks good, whereas the second is a full graph scan of the database, finding all HAS_SKILL
relationships. Not what we want.
The direct solution would be to just fix that:
START n=node:Person(name={name})
MATCH (n)-[:MANAGES]->()-[:HAS_SKILL]->(s) RETURN s.name as name
UNION
START n=node:Person(name={name})
MATCH (n)-[:HAS_SKILL]->(s) RETURN s.name as name
But it is much easier to just change the query structure:
START n=node:Person(name={name})
MATCH (n)-[:MANAGES*0..1]->()-[:HAS_SKILL]->(s) RETURN s.name as name
or actually:
MATCH (n:Person {name:{name}})-[:MANAGES*0..1]->
()-[:HAS_SKILL]->(s) RETURN s.name as name
We now can even represent an arbitrary managment level structure.
MATCH (n:Person {name:{name}})-[:MANAGES*0..]->
()-[:HAS_SKILL]->(s) RETURN s.name as name
Published at DZone with permission of , DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments