cancel
Showing results for 
Search instead for 
Did you mean: 

Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.

How to create relationship using FOREACH

I have Person and Course nodes. How I can create the relationships from one Person to many Courses using FOREACH? I tried the following as the example but it returns two new empty nodes,  two  new nodes with Courses and one new relationship between each pair of nodes. 
 

Match  (r: Course ), (p:Person {role:'Student', firstname:'John',lastname:’Smith'})  

with ["Chemistry", "Physics"] as rid_array

 foreach (i in range(0,size(rid_array)-1)| 

 merge out = (p)-[req:HAS_COURSE]->(r {course_name: rid_array[i]}))

 return out

8 REPLIES 8

ameyasoft
Graph Maven
The variables 'r' and 'p' are not being passed on. Add these varibles in line 2 and try.
with ["Chemistry", "Physics"] as rid_array, r, p

Can't create node `r` with labels or properties here. The variable is already declared in this context

ameyasoft
Graph Maven
Try this:

merge (p:Person {role:'Student', firstname:'John', lastname:'Smith'})

with ["Chemistry", "Physics"] as rid_array, p
 foreach (i in range(0,size(rid_array)-1)|
 merge (r:Course {course_name: rid_array[i]})
 merge (p)-[req:HAS_COURSE]->(r)
 )

@ameyasoft is absolutely correct, but it can be simplified, as you can iterate over the array directly.

with ["Chemistry", "Physics"] as rid_array
merge (p:Person {role:'Student', firstname:'John', lastname:'Smith'})
foreach (i in rid_array |
    merge (r:Course {course_name: i})
    merge (p)-[req:HAS_COURSE]->(r)
)

@glilienfield  Thanks but this query creates two new nodes 'Chemistry' and 'Physics' and then creates two relationships from Person to these new nodes. I need to create just relationships from node Person ('John Smith') to existing two nodes 'Chemistry' and 'Physics' in the loop,      

 two new nodes have been created and the relationships have been added to them. I need to create just relationship from one existing node Person (John Smith) to two existing courses.   

That is odd, as the merge will look for an existing node before it creates a new one. Also, the merge on the relationship is referencing node variables so, it shouldn't create new ones as well. We can change the merge to a match, but match is not allowed in a foreach loop, so we will need to refactor the code. 

 

with ["Chemistry", "Physics"] as rid_array
merge (p:Person {role:'Student', firstname:'John', lastname:'Smith'})
with rid_array, p
unwind rid_array as rid
match (r:Course {course_name: rid})
merge (p)-[req:HAS_COURSE]->(r)

 

Screen Shot 2023-02-06 at 10.13.49 AM.png

Screen Shot 2023-02-06 at 10.14.35 AM.png

BTW- you can have multiple labels on a node. It may be a better approach to add a label for your 'role' instead of a property. 

ameyasoft
Graph Maven
If you want to use FOREACH, try this: A slight modification of @gillienfield code.

with ["Chemistry", "Physics"] as rid_array
match (p:Person {role:'Student', firstname:'John', lastname:'Smith'})
foreach (i in rid_array |
    merge (r:Course {course_name: i})
    merge (p)-[req:HAS_COURSE]->(r)
)