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 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 https://stackoverflow.com/questions/48606320/can-i-use-this-csv-to-load-a-neo4j-graph-with-cypher )

But obtained the error:

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

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

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

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.

Thanks for the explanation

ibrahim
Node Link

Below is the way for two csv files MIP_nodes.csv and MIP_edges.csv:

//Load csv data into the database - with dynamic label(s)
WITH "file:///MIP_nodes.csv" AS uri
LOAD CSV WITH HEADERS FROM uri AS row
WITH * WHERE row.label <> ""
call apoc.merge.node ([row.label],{nodeId:row.nodeId, name: row.name, type: row.type, created: row.created, property1: row.property1, property2: row.property2})
YIELD node as n1
//RETURN n1
WITH * WHERE row.label = ""
call apoc.merge.node (['DefaultNode'],{nodeId:row.nodeId, name: row.name, type: row.type, created: row.created, property1: row.property1, property2: row.property2})
YIELD node as n2
RETURN n1, n2

//Load csv data into the database - with dynamic relationship(s)
//:auto USING PERIODIC COMMIT 500
LOAD CSV WITH HEADERS FROM 'file:///MIP_edges.csv' AS row
MATCH (s)  
WHERE s.nodeId = row.sourceId
//RETURN s
MATCH (d)
WHERE d.nodeId = row.destinationId
//RETURN d
CALL apoc.merge.relationship(s, row.label,{type:row.type, created: row.created, property1: row.property1, property2: row.property2},{}, d,{}) 
YIELD rel
//REMOVE rel.noOp;
RETURN rel;MIP_edges.csv.PNGMIP_nodes.csv.PNG