Neo4j: MATCH/CREATE order matters

We recently had made some changes in which a node might have two or more connected nodes that get pulled in where it was always a single node before. We added some OPTIONAL MATCHes to pull in the data we need, but did not think about the ordering in queries that would ultimately CREATE nodes. This wrecked some of our queries and tests.

MATCH (me:user {uuid: $uid})-[:allowed_to {create_cases: true}]->(c:company {uuid: $cid})
MATCH (ct:case_type {uuid: $case_type})<-[:allows]-(c)
MATCH (cl:client {uuid: $client})<-[:allows]-(c)
OPTIONAL MATCH (cl)-[:owns]->(e:email_address) // added
OPTIONAL MATCH (cl)-[:owns]->(p:phone)  // added
CREATE (ca:case $data)<-[:owns]-(me)
CREATE (c)-[:allows]->(ca)
CREATE (ct)-[:defines]->(ca) // case type defines the case
CREATE (cl)-[:has]->(ca) // client has a case
RETURN ...

The issues here is that the optional match would end up creating a cartesian of multiple results and so the CREATE would end up creating multiple identical nodes.

This was no bueno.

Simply moving the OPTIONAL MATCH to the end solved the problem. Another lesson about planning queries and remembering how Neo4j executes queries.

Leave a Comment

Sign in to post your comment or sign-up if you don't have any account.