Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

State of the Cypher UNION

DZone's Guide to

State of the Cypher UNION

· Java Zone
Free Resource

Download Microservices for Java Developers: A hands-on introduction to frameworks and containers. Brought to you in partnership with Red Hat.

Neo4j 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

Download Modern Java EE Design Patterns: Building Scalable Architecture for Sustainable Enterprise Development.  Brought to you in partnership with Red Hat

Topics:
java ,nosql ,architecture ,tips and tricks ,neo4j ,cypher ,union ,union all ,tools & methods

Published at DZone with permission of Michael Hunger, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}