Pierre
Pierre

Reputation: 953

How to set property name and value on csv load?

How can one set both the property name and its value loading a tall skinny csv file? The csv file would contain only 3 columns, node name (id), property name (p) and property value (v). A node with to properties would therefore correspond to 2 lines.

LOAD CSV... row
MERGE (n) WHERE n.Name = row.id
SET n.{row.p} = row.v

This syntax doesn't exit it's just to explain what I'd like to do. Is there a way to do such a thing in cypher? That be really useful rather than having to pivot data first.

A file contains definitions for person nodes:

Name,Age
A,25
B,34

A second file contains properties for specific nodes, one property per line

Name,property_name,property_value
A,weight,64
A,height,180
B,hair color,blond

I'd like to update nodes A and B and set additional properties based on the second file.

As mentioned below, one possibility is to create (:Data) nodes containing one property each, and link them person nodes

CREATE (p) -[:hasProperty]-> (:Data {Name: row.property_name, Value: row.property_value})

However, this might not be very efficient and extracting person nodes and properties gets much more complex.

MATCH (p:Person) --> (d:Data)
RETURN {name: p.name, age: p.age, property_names: collect(d.Name), property_values: collect(d.Value)}

Graal could either be to set property name dynamically on load, or a pivot function to return data properties on nodes.

Upvotes: 0

Views: 2121

Answers (1)

Christophe Willemsen
Christophe Willemsen

Reputation: 20185

You can not assign a property key dynamically from parameters, however since the row is a map, you can set all the row as properties on the node if it is ok for you :

LOAD CSV ... AS row
MERGE (n:Label {Name: row.id})
SET n += row

EDIT

Based on your edit, for your second file, if you don't have too much different values like weight, height, etc.. you can create a conditional collection, example :

LOAD CSV WITH ... AS row
WITH row, CASE row.property_name WHEN weight THEN [1] ELSE [] END as loopW
UNWIND loopW as w
MATCH (p:Person {name: row.Name})
SET p.weight = row.property_value
WITH row, CASE row.property_name WHEN height THEN [1] ELSE [] END as loopH
UNWIND loopH as h
MATCH (p:Person {name: row.Name})
SET p.height = row.property_value
...

Upvotes: 0

Related Questions