Hello,
I am playing with apoc triggers and would like to ask for an explanation regarding
how cypher and apoc work in this particular case.
I start out with the following nodes:
CREATE (:Base:Element {layer: 0, position: 0})
CREATE (:Input {data: "111"})
CREATE (:BaseTemporaryValues)
This is the trigger code:
CALL apoc.trigger.add('createInputRelationshipStructure', "UNWIND apoc.trigger.propertiesByKey({assignedNodeProperties}, 'data') as input
WITH input.node as i
MATCH (previous:Element) WHERE NOT EXISTS((previous)-[:NEXT_LAYER]->())
WITH i, previous limit 1
MATCH (temp:BaseTemporaryValues)
SET temp.position=1
WITH *
FOREACH ( element in split(i.data, '') |
CREATE (e:Element {value: toInteger(element), position: temp.position, layer: previous.layer+1})
SET temp.position = temp.position+1 )
WITH temp, previous
CALL apoc.cypher.doIt(\"UNWIND [1,2,3] as pos
SET temp.next_position=CASE WHEN pos<3 THEN pos+1 ELSE 1 END
WITH *
MATCH (e1:Element {position: pos, layer: previous.layer+1})
MATCH (e2:Element {position: temp.next_position, layer: previous.layer+1})
MERGE (e1)-[:NEXT_VALUE]->(e2)
RETURN 0\", {temp: temp, previous: previous}) yield value
WITH temp, previous
REMOVE temp.position
REMOVE temp.next_position
WITH temp, previous
MATCH (e:Element {layer: previous.layer+1})
MATCH (prev:Element {layer: previous.layer}) WHERE NOT EXISTS((prev)-[:NEXT_LAYER]->())
CALL apoc.do.when(prev.position<>0, 'WITH prev, e WHERE prev.position=e.position
MERGE (prev)-[:NEXT_LAYER]->(e) RETURN 0',
'MERGE (prev)-[:NEXT_LAYER]->(e) RETURN 0',
{prev: prev, e: e}) yield value RETURN value",
{phase: "after"})
This code does what was intended, however, i don't understand exactly why this code doesn't:
CALL apoc.trigger.add('createInputRelationshipStructure', "UNWIND apoc.trigger.propertiesByKey({assignedNodeProperties}, 'data') as input
WITH input.node as i
MATCH (previous:Element) WHERE NOT EXISTS((previous)-[:NEXT_LAYER]->())
MATCH (temp:BaseTemporaryValues)
SET temp.position=1
WITH *
CALL apoc.cypher.doIt(\"UNWIND split(i.data, '') as element
CREATE (e:Element {value: toInteger(element), position: temp.position, layer: previous.layer+1})
SET temp.position = temp.position+1
RETURN 0\", {temp: temp, i: i, previous: previous}) yield value
WITH temp, previous
CALL apoc.cypher.doIt(\"UNWIND [1,2,3] as pos
SET temp.next_position=CASE WHEN pos<3 THEN pos+1 ELSE 1 END
WITH *
MATCH (e1:Element {position: pos, layer: previous.layer+1})
MATCH (e2:Element {position: temp.next_position, layer: previous.layer+1})
MERGE (e1)-[:NEXT_VALUE]->(e2)
RETURN 0\", {temp: temp, previous: previous}) yield value
WITH temp, previous
REMOVE temp.position
REMOVE temp.next_position
WITH previous
MATCH (e:Element {layer: previous.layer+1})
CALL apoc.do.when(previous.position<>0, 'WITH previous, e WHERE previous.position=e.position
MERGE (previous)-[:NEXT_LAYER]->(e) RETURN 0',
'MERGE (previous)-[:NEXT_LAYER]->(e) RETURN 0',
{previous: previous, e: e}) yield value RETURN value",
{phase: "after"})
The intention is the following:
The data property is a 3-character string with digits. the trigger makes it so that on setting this property repeatedly a chain is constructed, starting from the Base node, with each digit being a node. Each digit node is connected to it's right hand neighbour via a :NEXT_VALUE relationship, and it's circular so the :NEXT_VALUE node of the rightmost digit is the leftmost digit. in addition to this, each time the input.data property is set the previous digit nodes are connected to the next one via a :NEXT_LAYER relationship.
The question is the following:
Using the second form of the trigger generates additional nodes. The first time the data property is set, the trigger works correctly. The second time it generates 3 nodes for each digit (with position properties x, x+3, x+6) instead of 1 node per digit. i fixed the code by limiting the result set of 'previous' nodes at the start of the trigger, but i do not understand why the number of nodes set to the 'previous' variable would change anything since none of the unwind clauses are based on that variable.
I hope the question is posed clearly enough. I am thankful for any explanations of this, as well as any corrections or optimizations you might think of.
Oh, this is my first post. Hello everyone, my name is Gal. Hopefully i can start answering questions more than i ask them soon :).