Search code examples
graphneo4jcyphergraph-databases

Relating nodes in csv with column names in Neo4J


I have a csv file in below format, ![enter image description here

  1. There are n location columns of various locations.
  2. There's Token column at the end where each location row is associated with a different token.

TASK

Associate each token to each location column such that the relationship is named after the column name.

Example

enter image description here

My cypher code

load csv with headers from "file:///locations.csv" as row with row where row is not null
merge (l1:locations {name:row.LOC_1})
merge (t:tokens {name:row.Token})
merge (l1) -[:LOC_1]->(t)

As you can see, This code loads each column and relates them to tokens manually which is a tedious task. In reality, there are 67 columns and doing this manually takes a lot of time.


Solution

  • To create relationship types dynamically, you will need the apoc library. And a bit of list comprehension. That allows you to do this:

    load csv with headers from "file:///locations.csv" AS row 
    with row where row is not null
    
    // create an array of maps, using the keys() function
    with row.Token AS token,
         [key IN keys(row) WHERE key<>'Token' | {relType:key,location:row[key]}] as relTypeLocs
    unwind relTypeLocs AS relTypeLoc
    merge (l:locations {name:COALESCE(relTypeLoc.location,'Unknown')})
    merge (t:tokens {name:token})
    WITH l,t,
         relTypeLoc.relType AS relType
    // use apoc to create the rels
    CALL apoc.create.relationship(t,relType,{}, l) YIELD rel
    RETURN rel
    

    To remove the 'Unknown':

    MATCH (l:locations {name:'Unknown'})
    DETACH DELETE l
    

    That said, two things to consider:

    • you can also set the LOC_1 .. LOC_N as a property on the relationship. Then you can do this in pure cypher.
    • You use plurals for the node labels. Since labels are kind of tags, consider using the singular.