Neo4j Cypher - creating nodes and setting labels with LOAD CSV

6.4k Views Asked by At

I’m trying to use LOAD CSV to create nodes with the labels being set to values from the CSV. Is that possible? I’m trying something like:

LOAD CSV WITH HEADERS FROM 'file:///testfile.csv' AS line
CREATE (x:line.label)

...but I get an invalid syntax error. Is there any way to do this?

5

There are 5 best solutions below

0
On BEST ANSWER

bicpence,

First off, this is pretty easy to do with a Java batch import application, and they aren't hard to write. See this batch inserter example. You can use opencsv to read your CSV file.

If you would rather stick with Cypher, and if you have a finite set of labels to work with, then you could do something like this:

USING PERIODIC COMMIT 1000
LOAD CSV WITH HEADERS FROM 'file:///testfile.csv' AS LINE
CREATE (n:load {lab:line.label, prop:line.prop});

CREATE INDEX ON :load(lab);

MATCH (n:load {lab:'label1'})
SET n:label1
REMOVE n:load
REMOVE n.lab;

MATCH (n:load {lab:'label2'})
SET n:label2
REMOVE n:load
REMOVE n.lab;

Grace and peace,

Jim

2
On

you can do a workaround - create all nodes and than filter on them and create the desired nodes, than remove those old nodes

LOAD CSV WITH HEADERS FROM 'file:///testfile.csv' AS line
CREATE (tmp:line[1])
WITH tmp
CREATE (x:Person {name: labels(tmp)[0]})
WITH tmp
REMOVE tmp

paste this into http://console.neo4j.org to see example:

LOAD CSV 
WITH HEADERS FROM "http://docs.neo4j.org/chunked/2.1.2/csv/import/persons.csv" AS csvLine
CREATE (p:tmp { id: toInt(csvLine.id), name: csvLine.name })
WITH p
CREATE (pp:Person { name: labels(p)[0]})
WITH p, pp
DELETE p
RETURN pp
0
On

Unfortunately not, parameterized labels are not supported

Chris

0
On

Jim Biard's answer works but uses PERIODIC COMMIT which is useful however deprecated.

I was able to write a query that:

  1. Loads from CSV
  2. Uses multiple transactions
  3. Creates nodes
  4. Appends labels
  5. Will work for 4.5 and onwards
:auto LOAD CSV WITH HEADERS FROM 'file:///nodes_build_ont_small.csv' AS row
CALL { 
        with row
        call apoc.create.node([row.label], {id: row.id})
        yield node
        return null
} IN TRANSACTIONS of 100 rows 
return null

Seems that apoc procedures are more useful then the commands themselves since this is not possible (at least in my attempts) with CREATE.

1
On

I looked around at a few questions like this, and came to the conclusion that a nice concise way to handle these kinds of complex frustrations of not being able to easily add dynamic labels through 'LOAD CSV', is simply use your favorite programming language to read CSV lines, and produce a text output file of Cypher statements that will produce the Neo4j node/edge structure that you want. Then you will also be able to edit the text file directly, to alter whatever you want to further customize your commands.

I personally used Java given I am most comfortable with Java. I read each line of the CSV into a custom object that represents a row in my CSV file. I then printed to a file a line that reflects the Cypher statement I wanted. And then all I had to do was cut and paste those commands into Neo4j browser command line.

This way you can build your commands however you want, and you can completely avoid the limitations of 'LOAD CSV' commands with Cypher