0
votes

New to Neo4j. I realize this question has a similar title (Creating nodes and relationships at the same time in neo4j) but I believe I'm trying to do something different. Also I would like to avoid using plugins if possible.

Basically I have a 1000 row CSV that looks something like this

FromNodeID  ToNodeID   type    attribute1   attribute2   
   1          2       1        1234      1235
   3          2       1        1234      1235
  ...

So I want to create the nodes and their relationships. FromNodes and ToNodes have just one property each (ID) and the relationship has 3 properties (type, attribute1 and attribute2). I want each node to be unique but each node can have many relationships (in the example above, node 2 should have 2 relationships).

Here's what I tried to make that work:

load csv with headers from "file:///file.csv" as row
MERGE (FromNode {id:toInteger(row.FromNode)})-[:communicates 
{Type:toInteger(row.Type), attribute1:toInteger(row.attribute1), 
attribute2:toInteger(row.attribute2)}]->(ToNode 
{id:toInteger(row.ToNode)})

I did put a uniqueness constraint on FromNode and ToNode IDs prior to this query.

I expected it to create each node (and not create new nodes when one with the same ID already exists) and create each relationship (with more than one relationship from/to nodes that are specified to have more than one relationship in the CSV).

What actually happened: It seems to have created all the unique nodes. It also created relationships between the nodes but it only put one relationship per node, NOT accounting for some of the nodes which have communications with more than one other node.

I'm confused because it was my understanding that with MERGE it would create a relationship if it did not occur in the database yet so I thought it would create all relationships specified in the CSV

1

1 Answers

1
votes

Your MERGE clause, as written, is not specifying a label for either node. Since a uniqueness constraint is associated with both a node label and a node property, if you do not specify a node label during node creation neo4j cannot enforce any uniqueness constraints. So the MERGE is actually creating some duplicate nodes (with no labels). This is also why all the new nodes only have a single relationship.

In Cypher, a node's label must be preceded by a colon. For example, (:Foo {abc:123}) instead of (Foo {abc:123}).

Also, to avoid potential constraint violation errors, you should have separate MERGE clauses for each node.

If the relevant labels are FromNode and ToNode, try this:

LOAD CSV WITH HEADERS FROM "file:///file.csv" AS row
MERGE (f:FromNode {id:toInteger(row.FromNode)})
MERGE (t:ToNode {id:toInteger(row.ToNode)})
MERGE (f)-[:communicates {
    Type:toInteger(row.Type), attribute1:toInteger(row.attribute1),
    attribute2:toInteger(row.attribute2)}
  ]->(t)