My CSV structure is as follows:
Origin City Destination City Route Sales
A B XYZ $5
B C ZED $50
C A FGH $15
Origin and destination cities are from the same bucket i.e. there should be only 3 nodes in this case (A, B, and C) whereas relationship will have 2 properties: sales and route.
When I use the:
LOAD CSV WITH HEADERS FROM 'file:///C:/citylist2.csv' as line fieldterminator ','
MERGE (c:City {id: line.`Origin City`})
MERGE (c)-[r:SALES{id: line.Route, sales: line.Sales}]->(c)
code then it creates a self-referencing flower graph. How d I solve this? I need 3 nodes and intra-node relationships with sales and route as properties.
What about this :
LOAD CSV WITH HEADERS FROM 'file:///C:/citylist2.csv' as line fieldterminator ','
MERGE (c1:City {id: line.`Origin City`})
MERGE (c2:City {id: line.`Destination City`})
MERGE (c1)-[r:SALES{id: line.Route, sales: line.Sales}]->(c2);
Hope this helps,
Regards,
Tom
Related
This is regarding neo4j csv import using LOAD csv. Suppose my csv file format is as following.
Id, OID, name, address, Parents , Children
1, mid1, ratta, hello#aa, ["mid250","mid251","mid253"], ["mid60","mid65"]
2, mid2, butta, ado#bb, ["mid350","mid365","mid320", "mid450","mid700"], ["mid20","mid25","mid30"]
3, mid3, natta, hkk#aa, ["mid50","mid311","mid543"], []
So the parents and children columns consists of mids basically..while importing csv into neo4j using LOAD CSV.. I want to create following nodes and relationships.
NODES for each rows (for each id column in csv)
[:PARENT] relationship by matching the OID property in each row and OID properties inside parents column. So as a example when processing the first row...there should be four nodes (mid1, mid250,mid 251 and mid 253) and 3 PARENT relationship between mid1 and other 3 nodes.
[: CHILD ] relationship by matching the OID property in each row and OID properties inside children column.
Please help!!
Tried doing it with for each function but the results didn't come correctly. Im doing it through a python script. just need to edit the cypher query.
def create_AAA(tx):
tx.run(
"LOAD CSV WITH HEADERS FROM 'file:///aaa.csv' AS row MERGE (e:AAA {id: row._id,OID: row.OID,address: row.address,name: row.name})"
)
def create_parent(tx):
tx.run(
"LOAD CSV WITH HEADERS FROM 'file:///aaa.csv' AS row MERGE (a:AAA {OID: row.OID}) FOREACH (t in row.parents | MERGE (e:AAA {OID:t}) MERGE (a)-[:PARENT]->(e) )"
)
def create_child(tx):
tx.run(
"LOAD CSV WITH HEADERS FROM 'file:///aaa.csv' AS row MERGE (a:AAA {OID: row.OID}) FOREACH (t in row.children | MERGE (e:AAA {OID:t}) MERGE (a)-[:CHILD]->(e) )"
)
with driver.session() as session:
session.write_transaction(create_AAA)
session.write_transaction(create_parent)
session.write_transaction(create_child)
Please follow the instructions below:
Change the column names of Parents and Children into parents and children since neo4j is case sensitive.
Remove the spaces in your csv file so that you don't need to do trim () on each columns in the csv.
In your parents and children columns, remove the commas on the string list because it is causing an error. OR use another delimiter and not comma. In my example, I used space as delimiter.
Below script will remove the quotes and [] characters then convert the string list into a list (using split() function)
Do the same for create child function.
LOAD CSV WITH HEADERS FROM 'file:///aaa.csv' AS row
MERGE (a:AAA {OID: row.OID})
FOREACH (t in split(replace(replace(replace(row.parents,'[', ''),']', ''),'"', ''), ' ') |
MERGE (e:AAA {OID:t}) MERGE (a)-[:PARENT]->(e) )
See sample csv here:
Id,OID,name,address,parents,children
1,mid1,ratta,hello#aa,["mid250" "mid251" "mid253"],["mid60" "mid65"]
2,mid2,butta,ado#bb,["mid350" "mid365" "mid320" "mid450" "mid700"],["mid20" "mid25" "mid30"]
3,mid3,natta,hkk#aa,["mid50" "mid311" "mid543"],[]
See sample result here:
LOAD CSV WITH HEADERS FROM 'file:///aaa.csv' AS row
WITH row WHERE row.children <>"[]"
MERGE (a:AAA {OID: row.OID})
FOREACH (t in split(replace(replace(replace(row.children,'[', ''),']', ''),'"', ''), ' ') |
MERGE (e:AAA {OID:t}) MERGE (a)-[:CHILD]->(e) )
Now it works fine.
I can load CSV into Neo4j for a specific label (say PERSON) and the nodes are created under the label PERSON.
I also have another CSV to illustrate the relationships between the person and it looks like:
name1, relation, name2
a, LOVE, b
a, HATE, c
I want to create a relationship between these pairs and the relationship thus created should be "LOVE", "HATE", etc, instead of a rigid RELATION as done by the below script:
load csv with headers from "file:///d:/Resources/Neo4j/person-rel.csv" as p
match (a:PERSON) where a.name=p.name1
match (b:PERSON) where b.name=p.name2
merge (a)-[r:REL {relation: p.REL}]->(b)
By doing this, I have a bunch of REL-type relations but not LOVE- and HATE-relations.
In another word, I want the REL in the last line of the script to be dynamically assigned. And then I can query out all the relationship types using Neo4j API.
Is this possible?
You can install the APOC library and then use apoc.merge.relationship
apoc.merge.relationship(startNode, relType, {key:value, ...}, {key:value, ...}, endNode) - merge relationship with dynamic type
load csv with headers from "file:///d:/Resources/Neo4j/person-rel.csv" as p
match (a:PERSON) where a.name=p.name1
match (b:PERSON) where b.name=p.name2
call apoc.merge.relationship(a,p.REL,{},{},b) yield rel
return count(*);
I have a CSV file that have information in the form:
Col1,Col2
A,B;C;D
I'm trying to generate relationships between A and each of B, C, D. In my particular case, B, C, D have already been created by importing another CSV file. Therefore, I do not need to create these nodes, but I do need to match them to get the node to form the relationship.
LOAD CSV WITH HEADERS FROM 'file:///file.csv' AS line
WITH line
MERGE (a:Item {name: line.Col1})
FOREACH (x IN SPLIT(line.Col2, ';') |
MATCH (s:Item {name: x})
CREATE UNIQUE (s)-[:rel]->(a));
Nodes B, C, D have multiple properties, only one of which is in the second CSV, like:
B: {id: 123, name: B}
Is there a way to do this with Cypher? Currently, I get the error: "Invalid use of MATCH inside FOREACH". Using MERGE instead of MATCH results in new, unwanted nodes.
Simple use MERGE instead MATCH:
LOAD CSV WITH HEADERS FROM 'file:///file.csv' AS line
WITH line
MERGE (a:Item {name: line.Col1})
FOREACH (x IN SPLIT(line.Col2, ';') |
MERGE (s:Item {name: x})
MERGE (s)-[:rel]->(a));
If a match is more complicated, then you can first make a selection, and then walk on it:
LOAD CSV WITH HEADERS FROM 'file:///file.csv' AS line
MERGE (a:Item {name: line.Col1})
WITH a, SPLIT(line.Col2, ';') as names
UNWIND names as x
MATCH (t:Item {name: x})
WITH a, collect(t) as sc
FOREACH (x IN sc |
CREATE UNIQUE (x)-[:rel]->(a));
I need to split a field in different values and store each value in a different node. For each created node I want to store the position.
Example:
Sentence Words
My car is red My;car;is;red
Using:
FOREACH (w IN SPLIT(line.TWords, ";") |
MERGE (wd:Word {word: w})
I can split the field and store the different words, but I'd like to store the position on the relationship.
My car is red -[HAS_WORD {position:1}]-> My
My car is red -[HAS_WORD {position:2}]-> car
My car is red -[HAS_WORD {position:3}]-> is
My car is red -[HAS_WORD {position:4}]-> red
How can I get this?
SOLUTION
USING PERIODIC COMMIT LOAD CSV WITH HEADERS FROM 'file:///output_2016-05-06_0203_Neo4jImport.csv' AS line FIELDTERMINATOR "\t"
MERGE (s:Segment{text: line.Source})
MERGE (ta:Segment{text: line.Target})
WITH SPLIT(line.SWords, ";") AS SWords, line, s, ta
UNWIND RANGE(0, SIZE(SWords)-1) as i
MERGE (s)-[r:HAS_WORD {position:i+1}]->(w:Word {word: SWords[i]})
WITH SPLIT(line.TWords, ";") AS TWords, line, ta
UNWIND RANGE(0, SIZE(TWords)-1) as i
MERGE (ta)-[r:HAS_WORD {position:i+1}]->(w:Word {word: TWords[i]})
Be sure that the fist WITH has the variable references necessary in second WITH: WITH SPLIT(line.SWords, ";") AS SWords, line, s, ta
You can use a range based on the size of the split, assuming the node containing the sentence is identified with sentence :
WITH split(line.TWords, ';') as splitted
UNWIND range(0, size(splitted) -1) as i
MERGE (w:Word {word: splitted[i]})
MERGE (sentence)-[:HAS_WORD {position: i}]->(w)
Update
USING PERIODIC COMMIT LOAD CSV WITH HEADERS
FROM 'file:///output_2016-05-06_0203_Neo4jImport.csv'
AS line FIELDTERMINATOR "\t"
MERGE (s:Segment{text: line.Source})
WITH SPLIT(line.SWords, ";") AS SWords, line
UNWIND RANGE(0, SIZE(SWords)-1) as i
MERGE (s)-[r:HAS_WORD {position:i+1}]->(w:Word {word: SWords[i]})
Use range:
MERGE (S:Sentence {text:"My car is red"})
WITH S, SPLIT(S.text, " ") as words
UNWIND RANGE(0,SIZE(words)-1) as i
MERGE (S)-[r:HAS_WORD {position:i+1}]->(w:Word {word: words[i]})
RETURN S, r, w
Hello I was trying to import some data in csv file to neo4j in my ubuntu 12.04.
The csv file is a two column data file with no header its format is like:
12ffew3213,232rwe13
12ffew3213,5yur2ru2r
rwerwerw3,432rwe13
rwerwerw3,5yur2ru2r
the thing is the data in row 0 and row 1 is not unique, for example the data may be 3000 lines and only has 100 unique row0 value and 300 unique row1 value.
And I want to build a graph with unique 100 row0 nodes and 300 row1 nodes and 3000 relationships between those nodes(if 12ffew3213,232rwe13 appears twice there are 2 edges).
Since I am new to neo4j and Cypher. After I tried with CREATE and MERGE for a while I still cannot build UNIQUE nodes. I used something like
LOAD CSV FROM 'file:///home/nate/Downloads/file.csv' AS line
MERGE (:A { number: toString(line[0])})-[:LIKES]->(:B { ID: toString(line[1])})
Any ideas??Thanks ahead!
Here's what you do.
LOAD CSV FROM 'file:///home/nate/Downloads/file.csv' AS line
MERGE (n:A {number : line[0]})
WITH line, n
MERGE (m:B {ID : line[1]})
WITH m,n
MERGE (n)-[:LIKES]->(m);
You first create or match the :A node, then create or match the :B node, then create or match the relationship. The WITH clauses collect the results at each point in the sequence to use in the next. To find out more about WITH clauses, read Section 9.5 in the Neo4j Manual.
The same for csv with header. If our header is 'head1','head2' our code will be:
LOAD CSV WITH HEADERS FROM 'file:///home/nate/Downloads/file.csv' AS line
MERGE (n:A {number : line.head1})
WITH line, n
MERGE (m:B {ID : line.head2})
WITH m,n
MERGE (n)-[:LIKES]->(m);