I’m new to Neo4j/Cypher and apologize upfront if there is a simple newbie mistake going on. I’m looking to accept feeds of multiple records (from Kafka), where subsequent records can change or remove relationships from previous records. I’m seeing different results depending upon whether there is a single record in the set for UNWIND or multiple records in the set. I’m looking for a way for the multiple record results to be the same as multiple single record runs.
This is a simplified example that seems to illustrate the issue encountered in a more complex scenario.
WITH [{namespace:"proj3", person:"joe",role:"admin" }
] AS events
UNWIND events AS event
WITH event, randomUUID() AS uuid
MERGE (namespace:Namespace {Name:event.namespace})
MERGE (who:Person {Name:event.person})
MERGE (who)-[r:hasAccess]->(namespace)
ON CREATE set r.Runid = uuid, r.Role = event.role
ON MATCH set r.Runid = uuid, r.Role = event.role
WITH namespace, uuid
MATCH ()-[rd1:hasAccess]->(namespace) WHERE rd1.Runid <> uuid DELETE rd1
Added 2 labels, created 2 nodes, set 4 properties, created 1 relationship, completed after 3 ms.
When run with this first record. It creates a Namespace node “proj3” and a person node “joe” and creates a hasAccess relationship between them with a Role property set to admin and a Runid UUID value of this run.
This is run again with a second transaction:
WITH [{namespace:"proj3", person:"bill",role:"admin" }
] AS events
UNWIND events AS event
WITH event, randomUUID() AS uuid
MERGE (namespace:Namespace {Name:event.namespace})
MERGE (who:Person {Name:event.person})
MERGE (who)-[r:hasAccess]->(namespace)
ON CREATE set r.Runid = uuid, r.Role = event.role
ON MATCH set r.Runid = uuid, r.Role = event.role
WITH namespace, uuid
MATCH ()-[rd1:hasAccess]->(namespace) WHERE rd1.Runid <> uuid DELETE rd1
Added 1 label, created 1 node, set 3 properties, deleted 1 relationship, created 1 relationship, completed after 3 ms.
This time a Person node “bill” is created and a hasAccess relationship with a roleAttribute of admin and Runid UUID value of this run. The hasAccess relationship between the Person node joe and the namespace has been removed.
This is all as expected. However, when both records are include in the set in a single run. Different results occur. Start with a clean database (match (n) detach delete n) and run them both together.
WITH [{namespace:"proj3", person:"joe",role:"admin" },
{namespace:"proj3", person:"bill",role:"admin" }
] AS events
UNWIND events AS event
WITH event, randomUUID() AS uuid
MERGE (namespace:Namespace {Name:event.namespace})
MERGE (who:Person {Name:event.person})
MERGE (who)-[r:hasAccess]->(namespace)
ON CREATE set r.Runid = uuid, r.Role = event.role
ON MATCH set r.Runid = uuid, r.Role = event.role
WITH namespace, uuid
MATCH ()-[rd1:hasAccess]->(namespace) WHERE rd1.Runid <> uuid DELETE rd1
Added 3 labels, created 3 nodes, set 7 properties, deleted 2 relationships, created 2 relationships, completed after 8 ms.
The end result is that the two Person nodes “joe” and “bill” are created and the Namespace node proj3 is created. But there are no relationships in this final result. There is also the interesting stats that 2 relationships were created and 2 were deleted.
Why isn’t the end result the same as when the two are run separately? What can be done so the same result is received when the two transactions are present as a set in the unwind?