Unable to create relation with FOREACH clause

Hi, I'm trying to create relation to link event

MATCH (c:Car {carID:car_ID})-[:takePlace]->(e:Event)
with e ORDER BY e.start_time
with collect(e) as events
FOREACH(i in RANGE(0, size(events)-2) |
     create (events[i])-[:NEXT]->(events[i+1]))

And I got the fullowing error


Anyone knows why would this happen?

Thanks,
Oli

Hello @oli :slight_smile:

You cannot use a list item to match a node, you must do like this:

MATCH (c:Car {carID: car_ID})-[:takePlace]->(e:Event)
WITH e
ORDER BY e.start_time
WITH collect(e) AS events
UNWIND RANGE(0, size(events)-2) AS i
MATCH (a:Event) WHERE a.your_property = events[i].your_property 
MATCH (b:Event) WHERE b.your_property = events[i+1].your_property
CREATE (a)-[:NEXT]->(b)

Regards,
Cobra

Hello Cobra,
Thanks for your reply, my purpose is that I wish to link all my nodes inside the list without searching outside. If I'm not understanding wrong, neo4j doesn't support event[i] to represent a node even if it does a node?(I tried like "with event[i] as e1", and it works, but the with clause cannot be inside FOREACH clause)

Yes, that's why you must use a MATCH clause, do you have a unique property for your Event nodes?

Yes, I do. I have a generated eventID(combined with several properties), May I ask that what if I would to use FOREACH, how could I deal with the event[i]?

According to the documentation: within the FOREACH parentheses, you can do any of the updating commands — SET , REMOVE , CREATE , MERGE , DELETE , and FOREACH. So in your case, I don't see how you can use it since you need to match both nodes.

The best solution is this one:

MATCH (c:Car {carID: car_ID})-[:takePlace]->(e:Event)
WITH e
ORDER BY e.start_time
WITH collect(e) AS events
UNWIND RANGE(0, size(events)-2) AS i
MATCH (a:Event {eventID: events[i].eventID})
MATCH (b:Event {eventID: events[i+1].eventID})
CREATE (a)-[:NEXT]->(b)
1 Like

Thanks Cobra,
I'm just wandering that what if I don't match the event but just iterate the node and link it?

MATCH (c:Car {carID: car_ID})-[:takePlace]->(e:Event)
WITH e
ORDER BY e.start_time
WITH collect(e) AS events
UNWIND RANGE(0, size(events)-2) AS i
WITH events[i] AS a,  events[i+1] AS b
CREATE (a)-[:NEXT]->(b)

If I wrote the code in this way, it will be no problem (use WITH...AS... instead events[i] directly)
I don't know if this will be more efficient since there is no extra matching cost?
Hope to discuess with you

Yes, your solution with the WITH clause should be more efficient, I did not have to wake up fully :sweat_smile:. You can compare both queries with the PROFILE keyword.