If my CSV file consists of headers with dots:
column1.name, column2.age, column3.city ...
How can I read them? Should I avoid dots?
LOAD CSV FROM "URL..." AS row RETURN row.`column1.name`, toInteger(row.`column2.age`)
Importing form csv is usually something you do for initial creation of the graph. So I would not worry too much about what looks pretty as long as it gets the job done.
It is absolutely fine to have dots in the headers and you can use:
RETURN row.`column1.name` as name, row.`column.age` as age
If you want to avoid using back ticks use:
RETURN row['column1.name'] as name, row['column.age'] as age
Related
I am new to Neo4j and graph database. While trying to import a few relationships from a CSV file, I can see that there are no records, even when the file is filled with enough data.
LOAD CSV with headers FROM 'file:/graphdata.csv' as row WITH row
WHERE row.pName is NOT NULL
MERGE(transId:TransactionId)
MERGE(refId:RefNo)
MERGE(kewd:Keyword)
MERGE(accNo:AccountNumber {bName:row.Bank_Name, pAmt:row.Amount, pName:row.Name})
Followed by:
LOAD CSV with headers FROM 'file/graphdata.csv' as row WITH row
WHERE row.pName is NOT NULL
MATCH(transId:TransactionId)
MATCH(refId:RefNo)
MATCH(kewd:Keyword)
MATCH(accNo:AccountNumber {bName:row.Bank_Name, pAmt:row.Amount, pName:row.Name})
MERGE(transId)-[:REFERENCE]->(refId)-[:USED_FOR]->(kewd)-[:AGAINST]->(accNo)
RETURN *
Edit (table replica):
TransactionId Bank_Name RefNo Keyword Amount AccountNumber AccountName
12345 ABC 78 X 1000 5421 WE
23456 DEF X 2000 5471
34567 ABC 32 Y 3000 4759 HE
Is it likely the case that the Nodes and relationships are not created at all? How do I get all these desired relationships?
Neither file:/graphdata.csv nor file/graphdata.csv are legal URLs. You should use file:///graphdata.csv instead.
By default, LOAD CSV expects a "csv" file to consist of comma separated values. You are instead using a variable number of spaces as a separator (and sometimes as a trailer). You need to either:
use a single space as the separator (and specify an appropriate FIELDTERMINATOR option). But this is not a good idea for your data, since some bank names will likely also contain spaces.
use a comma separator (or some other character that will not occur in your data).
For example, this file format would work better:
TransactionId,Bank_Name,RefNo,Keyword,Amount,AccountNumber,AccountName
12345,ABC,78,X,1000,5421,WE
23456,DEF,,X,2000,5471
34567,ABC,32,Y,3000,4759,HE
Your Cypher query is attempting to use row properties that do not exist (since the file has no corresponding column headers). For example, your file has no pName or Name headers.
Your usage of the MERGE clause is probably not doing what you want, generally. You should carefully read the documentation, and this answer may also be helpful.
I want to create a simple DB using some CSV files, like this:
attore.csv, film.csv, recita.csv.
I created successfully the nodes with the label Attore and Film, simple files like this:
attore.csv:
nome
nome1
nome2
nome3
film.csv
titolo
titolo1
titolo2
titolo3
and I was trying to create the relationship between them using recita.csv, in which each row is:
attore, film
Obv my primary key should be Attore(nome) and Film(titolo).
I've been looking for so much time, I found many codes but no one is working, every try I made just run for something like an hour.
This is what I did:
I created the film nodes:
USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM "file:///film.csv" AS row
CREATE (n:Film)
SET n = row, n.titolo = (row.titolo), n.durata = (row.durata),
n.genere = (row.genere), n.anno = (row.anno), n.descrizione =
(row.descrizione), n.regista = (row.regista),
n.studio_cinematografico = (row.studio_cinematografico)
Then I created the attore nodes:
USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM "file:///attore.csv" AS row
CREATE (n:Attore)
SET n = row, n.nome = (row.nome)
And then, after so much try I thought this was the exact way to create relationship, but didn't work:
USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM "file:///recita.csv" AS row
MATCH (attore:Attore {nome: row.attore})
MATCH (film:Film {titolo: row.film})
MERGE (attore)-[:RECITA]-(film);
I hope that someone could tell me the right way to create relationship, thanks.
EDIT: Examples of how are structured my files
attore.csv:
nome
Brendan Fraser
Bett Granstaff
Leslie Nielsen
Martina Gedeck
Martin Sheen
film.csv:
titolo durata genere anno descrizione regista studio_cin
Mortdecai 80 Action 2015 *something* David Koepp Liongate
recita.csv:
attore film
Johnny Depp Mortdecai
Jason Momoa Braven
Instead of the approach you are using. I would recommend to use Merge instead of Create, in this way you can avoid repetitions:
USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM "file:///attore.csv" AS row
MERGE (a:Attore{nome: row.nome})
RETURN a
the same is applied for the film.csv just separate properties with comma.
Second considering your csv docs format, check again the .csv format documentation. From what you have explained and if you want to make your code working, you need to have just two columns in your recita.csv (attore, film) and not 6 as you have (attore, film attore, film attore, film), because they are identical, but the column identifier (name) should be unique you don't need to repeat attore and film 3 times.
Please check the headers of all your files or expand your question with examples of your csv's.
Try to change your recita.csv file according to csv format requirements.
I search how to convert UICollectionView to CSV file and send it with Mail.
I have a collection view like the photo and I want to export the table and send it. I search and found that the best way is to convert to CSV file.
If you have other suggestion, just tell me.
As #Larme has pointed out, converting this to a CSV file has nothing to do with the visual representation in the collection view. You simply need to parse the data source to CSV. CSV stands for Comma Separated Value, which in turn means a type of file where tabular data is encoded using a delimiter between each data point (this is generally a comma, but could be anything), and a new line for each line of the table. Think of the delimiter as the vertical line between each column of the table, and the new line as the row:
So your CSV text file might look like this:
TITLEFORCOLUMN1, TITLEFORCOLUMN2, TITLEFORCOLUMN3
ROWTITLEONE, 200, 300
ROWTITLETWO, 400, 500
and so on. It's not quite this simple, and there are rules that you should follow, especially if you intend the CSV file to be consumed by third parties. There is an official specification which you can look at, but you can also get a lot of tips by searching 'CSV file specification'.
You then need to create a string by iterating through your data source. Start off by creating the line specifying the headers, then add a newline character and then add your data. So for the above example you could do something like (assuming the data is set out as a two dimensional array)
var myCSVString : String = "TITLEFORCOLUMN1, TITLEFORCOLUMN2, TITLEFORCOLUMN3\n"
for lineItem in myDataSource {
myCSVString = myCSVString + lineItem[0] + ", " + lineItem[1] + ", " + lineItem[2] + "\n"
}
Then write the string to file.
You'll need to do more research yourself but hopefully that will set you off in the right direction.
Assume a Node "Properties". I am using "LOAD CSV with headers..."
Following is the sample file format:
fields
a=100,b=110,c=120,d=500
How do I convert fields column to having a node with a,b,c,d and 100,110,120,500 respectively as the properties of the node "Properties"?
LOAD CSV WITH HEADERS FROM 'file:/sample.tsv' AS row FIELDTERMINATOR '\t'
CREATE (:Properties {props: row.fields})
The above does not create individual properties, but sets a string value to props as "a=100,b=110,c=120,d=500"
Also, different rows could have different set of Key values. That is the key needs to be dynamic. (There are other columns as well, I trimmed it for SO)
fields
a=100,b=110,c=120,d=500
X=300,y=210,Z=420,P=600
...
I am looking for a way to not split this key-value as columns and then load. The reason is they are dynamic - today it is a,b,c,d it may change to aa,bb,cc,dd etc.
I don't want to keep on changing my loader script to recognize new column headers.
Any pointers to solve this? I am using the latest 3.0.1 neo4j version.
First things first: Your file format currently defines a single header/property: fields:
fields
a=100,b=110,c=120,d=500
Since you defined a tab as field terminator, that entire string (a=100,b=110,c=120,d=500) would end up in your node's props property:
To have properties loaded dynamically: First set up proper header:
"a","b","x","y"
1,2,,
,,3,4
Then you can query with something like this:
LOAD CSV WITH HEADERS FROM 'file:///Users/David/overflow.csv' AS row
CREATE (:StackOverflow { a:row.a, b:row.b,x:row.x,y:row.y})
Then when you run something like:
match(so:StackOverflow) return so
You'll get the variable properties you wanted:
I am trying to iterate through an unstrucutred csv file (it has no specific headings). The file is generated by an instrument. I would need to select specific rows that have specific column values and create another file. Below is the example of the file layout
,success, (row1)
1,2,protocol (row2)
78,f14,34(row3)
,67,34(row4)
,f14,34(row5)
3,f14,56,56(row6)
I need to select all rows with 'fi4' value. Below is the code
import csv
import sys
reader = csv.reader(open('c:/test_file.csv', newline=''), delimiter=',', quotechar='|')
for row in reader:
print(','.join(row))
I am unable to go beyond this point.
You're almost there:
for row in reader:
if row[1] == 'f14':
print(','.join(row))
You just need to check and see whether the row is one you're interested in or not by checking the value of the column and see if it's what you're looking for. That could be done with a simpleif row[1] == 'f14'conditional statement. However that would fail on any blank lines -- which it looks like your input file may have -- so you'd need to preface that check with another to make sure the row had at least that many columns in it.
To create another csv file with just those rows in it, all you'd need to write each row that passed all the checks to another file opened for output -- instead of, or in addition to, printing the row out. Here's a very concise way of just writing the rows to another file.
(Note: I'm not sure why you had thequotechar='|'in your code on thecsv.reader()call because there aren't any quote characters in the input file shown, so I left it out in the code below -- you might need to add it back if indeed that's what it would be if there were any.)
import csv
with open('test_file.csv', newline='') as infile, \
open('test_file_out.csv', 'w', newline='') as outfile:
csv.writer(outfile).writerows(row for row in csv.reader(infile)
if len(row) >= 2 and row[1] == 'f14')
Contents of'test_file_out.csv'file afterwards:
78,f14,34(row3)
,f14,34(row5)
3,f14,56,56(row6)