0
votes

Overarching background
I am currently attempting to write neo4j queries into functions to be used in flask.
I am aiming to have the function load the data from a csv file that updates itself periodically and create new nodes and relationships as needed.

I have been attempting to follow the function structure shown here:
https://github.com/nicolewhite/neo4j-flask/blob/master/blog/models.py

I have tested neo4j cypher queries separately, and I have currently run into two problems (I'll post the second py2neo problem in a separate post).

title_id,title  
T1,Article Title 1  
T2,Article Title 2 

I have been changing the csv file by manually adding in rows like:

title_id,title  
T1,Article Title 1  
T2,Article Title 2 
T3,TEST

My keyword csv file looks like this:

title_id,keyword_id,keyword  
T1,K1,aaa  
T1,K2,bbb  
T1,K3,ccc  
T1,K4,ddd  
T2,K1,aaa  
T2,K5,eee  
T2,K6,fff  
T2,K4,ddd  

Likewise, I have been adding in new keywords to test like so:

title_id,keyword_id,keyword  
T1,K1,aaa  
T1,K2,bbb  
T1,K3,ccc  
T1,K4,ddd  
T2,K1,aaa  
T2,K5,eee  
T2,K6,fff  
T2,K4,ddd  
T2,K7,TEST  

My constraints are as follows:

CREATE CONSTRAINT ON (a_title:Title) ASSERT a_title.t_id IS UNIQUE  
CREATE CONSTRAINT ON (keyword:Keyword) ASSERT keyword.k_id IS UNIQUE  

The first problem I have run into is a LOAD CSV problem.

My py2neo code is as follows:

def create_titles(self):
    #
    query = '''
    'LOAD CSV WITH HEADERS FROM "file:///1209test_titles.csv" AS csvLine1 WITH csvLine1 ' \
    'WHERE csvLine1.title_id IS NOT NULL MERGE (a_title:Title{t_id:csvLine1.title_id,Title:csvLine1.title})'
    '''


    return graph.run(query)

However, as I attempt to create a new title node by appending new data to my csv file, I run into a constraint error telling me the node I just already exists.

I have tried to follow the answer found here:
Neo4j Load CSV only when unique
My current LOAD CSV code I am testing in the browser environment is as follows:

LOAD CSV WITH HEADERS FROM "file:///1209test_titles.csv" AS csvLine1
WITH csvLine1
WHERE csvLine1.title_id IS NOT NULL
MERGE (a_title:Title)
ON MATCH SET a_title.t_id = csvLine1.title_id
ON MATCH SET a_title.Title = csvLine1.title

... but it still gives me a constraint error.

(As a comparison, I tried running my keyword cypher query but it seemed to work fine without any errors)

  query2 = 'LOAD CSV WITH HEADERS FROM 

"file:///1209test_titleid_kwid_kw.csv" AS csvLine3 
WITH csvLine3 WHERE csvLine3.title_id IS NOT NULL   MERGE(keyword:Keyword{k_id:csvLine3.keyword_id,Keyword:csvLine3.keyword})   WITH csvLine3, keyword MATCH(title:Title{t_id:csvLine3.title_id}) MERGE(title)-[r1:HAS_KEYWORDS]->(keyword)'

graph.run(query2)

I'm not quite sure what I'm doing wrong, and what the difference is between my keyword node creation and title node creation... (Upon checking my files, appending information to the title csv file used to work...)

Thank you very much,

Eric

1

1 Answers

0
votes

You need to MERGE using the unique property (or properties), and only after the MERGE can you use one of the variations of SET.

This approach you cited will not work:

LOAD CSV WITH HEADERS FROM "file:///1209test_titles.csv" AS csvLine1
WITH csvLine1
WHERE csvLine1.title_id IS NOT NULL
MERGE (a_title:Title)
ON MATCH SET a_title.t_id = csvLine1.title_id
ON MATCH SET a_title.Title = csvLine1.title

The MERGE here will make it match to everything that matches the pattern, so it will match to all :Title nodes in your database and then set those properties on all of them (and then repeat the same process per row in the CSV).

You need this instead:

LOAD CSV WITH HEADERS FROM "file:///1209test_titles.csv" AS csvLine1
WITH csvLine1
WHERE csvLine1.title_id IS NOT NULL
MERGE (a_title:Title {t_id:csvLine1.title_id})
ON MATCH SET a_title.Title = csvLine1.title // or just SET if you want to set it in all cases