How to create dynamic relations from csv with apoc?

Hi all,
I have a csv file containing:

"FromNode","RelationType","ToNode"
"Cybersecurity knowledge","CONNECTED","Vulnerabilities"
"Cybersecurity knowledge","RELATED","Mitigations"

Trying to load from csv I used this (wrong) statement:

LOAD CSV WITH HEADERS FROM "file:///relations.csv" AS row
MATCH (f:Node), (s:Node)
WHERE f.Name = row.FromNode
AND s.Name = row.ToNode
CREATE (f)-[:TOSTRING(row.RelationType)]->(s)

I found that the apoc procedure

"apoc.create.relationship(person1,'KNOWS',{key:value,...}, person2) create relationship with dynamic rel-type"

should do thework; but I was unable to find the correct syntax.

How can I create these differently labelled relationships from csv?

UPDATE:
Tryed this

LOAD CSV WITH HEADERS FROM "file:///relations.csv" AS row
MATCH (f:Node), (s:Node)
WHERE f.Name = row.FromNode
AND s.Name = row.ToNode
CALL apoc.create.relationship(f, row.RelationType,{}, s)

(taken from Can I use this CSV to load a neo4j graph with cypher? - Stack Overflow )

But obtained the error:

SyntaxError: Query cannot conclude with CALL (must be RETURN or an update clause) (line 5, column 1 (offset: 135)) 

Unless the CALL is the only thing in the query, you need to explicitly YIELD variables from the call (using call apoc.help('create.rel') shows us this procedure yields arel` variable), and as in the message you can't end the query with a CALL, it needs to be a writing clause or a return. If you need the equivalent of a no-op then you can remove a non-existent property from a node or relationship:

LOAD CSV WITH HEADERS FROM "file:///relations.csv" AS row
MATCH (f:Node), (s:Node)
WHERE f.Name = row.FromNode
AND s.Name = row.ToNode
CALL apoc.create.relationship(f, row.RelationType,{}, s) YIELD rel
REMOVE rel.noOp
3 Likes

Thanks a lot: it worked.

Please, can you explain

If you need the equivalent of a no-op then you can remove a non-existent property from a node or relationship

I don't understand when and how

REMOVE rel.noOp

works

The comment was with regards to the requirement that a Cypher statement (unless consisting only of a single CALL) must end with either a RETURN or a writing clause (MERGE, CREATE, SET, REMOVE, DELETE).

Basically, you cannot end your statement on a CALL, that won't compile. If you don't need to return anything, then you can use a REMOVE on a nonexistent property.

REMOVE rel.noOp

This assumes that relationship doesn't have a noOp property, so this REMOVE won't actually do anything, but it will work as the last part of the query, since you can't end on the CALL.

3 Likes

Thanks for the explanation

I am trying to do the same, but along with creating the nodes as well.
I tried this:

LOAD CSV WITH HEADERS FROM "file:///COVID_Edges.csv" AS row
MERGE (src:Character {name: row.Source})
MERGE (tgt:Character {name: row.Target})
CALL apoc.create.relationship(src, row.Relation,{}, tgt) YIELD rel
REMOVE rel.noOp
ON CREATE SET r.weight = toInteger(row.weight)

But, it says:

WITH is required between MERGE and CALL (line 4, column 1 (offset: 142))
"CALL apoc.create.relationship(src, row.Relation,{}, tgt) YIELD rel"

Could you please help?

Use
WITH src, tgt before the CALL statement