Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Merge statement to match multiple properties

Tags:

neo4j

cypher

I am trying to figure out how to efficiently add a new node using a cypher query. I am trying to merge multiple data sources, so need to look for possible matching data. I have 3 data points that may or may not exist. If any of the data points match, I want do reuse the existing node. If none of the data points match, I want to create a new node.

Creating the node if it does not exist is the exact use case for MERGE. MERGE does not allow a WHERE clause otherwise this would be pretty simple. Since I am matching data-point-a OR data-point-b OR data-point-c, I can't figure out how to use MERGE as it AND's all the properties.

This is not valid, but should express my goal:

MERGE (n:TYPE)
WHERE n.propertyA = "A" OR n.propertyB = "B" OR n.propertyC = "C"
ON MATCH SET n.propertyA = "A", n.propertyB = "B", n.propertyC = "C"  
ON CREATE SET n.timestamp = <now>, n.propertyA = "A", n.propertyB = "B", n.propertyC = "C"
RETURN n;

I was thinking I might be able to use a batch or transaction. I would appreciate any insight or guidance as I am still learning Cypher.

like image 379
Brian Bauman Avatar asked Oct 27 '15 04:10

Brian Bauman


1 Answers

Not sure if you can do it in a single statement, I'll be following this question to see if there is a more optimal route. You can do it in two where first will find and update existing nodes, and the second will find and create the missing ones:

OPTIONAL MATCH (existing:TYPE) WHERE existing.propertyA = 'A' OR existing.propertyB = 'B' OR existing.propertyC = 'C'
WITH existing
WHERE existing IS NOT NULL SET existing.propertyA = 'A', existing.propertyB = 'B', existing.propertyC = 'C'
RETURN existing;

OPTIONAL MATCH (existing:TYPE) WHERE existing.propertyA = 'ZZ' OR existing.propertyB = 'ZZ' OR existing.propertyC = 'ZZ'
WITH existing
WHERE existing IS NULL MERGE (newNode:TYPE {propertyA: 'ZZ', propertyB: 'ZZ', propertyC: 'ZZ'})
RETURN newNode

However, note that this does not preserve existing values - e.g. if you load from one source properties A & B (and C is null) and then you load from second source and A is null but B & C are set, then the update statement would match the node, but would reset A to null (unless, of course, you make sure your update only sets the values which are not-null).

like image 165
Lili Avatar answered Nov 02 '22 03:11

Lili