Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Merge and Optional match - how to avoid trying to link into a null node

Tags:

neo4j

cypher

I am using CSV load into my neo4j and I'm struggling constructing a query for one of my usecases. I have a file with contents like:

aNodeFoo,xNodeBar
1,5
2,10
3,
4,

There are other properties of start node in the file, but this is irrelevant to the question. What I'd like to achieve is:

  • create/merge starting node A and set its property foo to whatever is the value of the column
  • if xNodeBar is populated, create a relationship to (existing) node X with property bar equal to given value, but if the cell is empty - simply ignore it.

In other words, for this example I expect to have nodes X with property bar set to 5 and 10 already, and I'd expect 4 nodes A with property foo set to 1,2,3 and 4 created, and node A foo=1 linked to node X bar=5 and node A foo=2 linked to node X bar=10.

If all lines are guaranteed to be populated then query is fairly simple:

LOAD CSV WITH HEADERS FROM ... AS csvLine
MATCH (nodeX:X {bar: csvLine.xNodeBar})
MERGE (nodeA:A {foo: csvLine.aNodeFoo})
MERGE (nodeA) -[:R]-> (nodeX)

I tried using OPTIONAL MATCH instead (which finds nothing for nodeX if cell is empty) but then I get an error saying I'm trying to link into a null node.

Hints anyone? Is such a query possible in cypher?

like image 780
Lili Avatar asked Jul 12 '14 16:07

Lili


1 Answers

Conditionals can be handled in general using FOREACH and CASE, as shown here.

For yours, you could do

LOAD CSV WITH HEADERS FROM '/path/to/file' AS csv
MERGE (a:A {foo:TOINT(csv.aNodeFoo)})
FOREACH (xbar IN (CASE csv.xNodeBar WHEN "" THEN [] ELSE [TOINT(csv.xNodeBar)] END) |
    MERGE (x:X {bar:xbar})
    MERGE (a)-[:REL]->(x)
)
like image 140
Nicole White Avatar answered Oct 13 '22 11:10

Nicole White