Cracoras
Cracoras

Reputation: 367

Persisting variable values to other parts of the cypher query

I am having a problem with my query where the variables defined inside a FOREACH clause is not available to a subsequent MERGE. In the snippet below, I check the existence of a value for each field before I create the Nodes. In some cases these fields can missing, so I don't want to create nodes for them. Then in the last FOREACH, assuming that the reference to those nodes is stored in the variables I try to create their relationships.

FOREACH(ignoreMe IN CASE WHEN "${record:value('/11')}" <> "" THEN [1] ELSE [] END |
  MERGE (company:Company{name:"${record:value('/11')}"}))

FOREACH(ignoreMe IN CASE WHEN "${record:value('/1')}" <> "" THEN [1] ELSE [] END |
  MERGE (cloudSuite:CloudSuite{name:"${record:value('/1')}"}))

FOREACH(ignoreMe IN CASE WHEN "${record:value('/18')}" <> "" THEN [1] ELSE [] END |
  MERGE (application:Application{name:"${record:value('/18')}"}))

FOREACH(ignoreMe IN CASE WHEN "${record:value('/8')}" <> "" THEN [1] ELSE [] END |
  MERGE (applicationInstance:ApplicationInstance{applicationId:"${record:value('/8')}"}))

FOREACH(ignoreMe IN CASE WHEN "${record:value('/9')}" <> "" THEN [1] ELSE [] END |
  MERGE (screen:Screen{name:"${record:value('/9')}"}))

FOREACH(ignoreMe IN CASE WHEN "${record:value('/19')}" <> "" THEN [1] ELSE [] END |
  MERGE (screenInstance:ScreenInstance{screenId:"${record:value('/19')}"}))

FOREACH(ignoreMe IN CASE WHEN ("${record:value('/0')}" IN ["Accessed"])THEN [1] ELSE [] END |
    MERGE (screenInstance)-[:INSTANCE_OF]->(screen)
    MERGE (screenInstance)-[:VIEWED_ON]->(applicationInstance)
    MERGE (application)-[:IMPLEMENTS]->(screen)
    MERGE (session)-[:ACCESSES]->(screenInstance))

However what actually is happening is that when I visualize my graph, I see the valid nodes defined as orphan nodes and the relationships created between some "phantom" nodes. So my question is, if is there a way for me to pass the reference to the valid nodes to the MERGE who creates the relationships.

Upvotes: 0

Views: 789

Answers (1)

InverseFalcon
InverseFalcon

Reputation: 30397

You won't be able to use this approach, as you discovered variables introduced in FOREACH won't be available outside of it.

You may want to look at using APOC conditional procedures (use the apoc.do.when() proc) in place of the FOREACH workaround. You can return values from the executed Cypher that are exposed via the yielded value map variable.

For example, looking at just the first snippet:

CALL apoc.do.when("${record:value('/11')}" <> "", 
"MERGE (company:Company{name:\"${record:value('/11')}\"}) RETURN company") YIELD value
WITH value.company as company
...

Keep in mind that if a query within a conditional needs to use a variable from outside the conditional, you need to pass it in via the parameter map.

Upvotes: 1

Related Questions