3

I am trying to accomplish something quite simple in python but not so in Neo4j. I'd appreciate any comment and suggestions to improve the procedure!

Within Python script, I am trying to create a relationship as well as its property for every pair of two nodes. From a data analysis (not a csv file), I ended up having a dataframe with three columns as following:

name1    name2    points
===========================
Jack     Sara     0.3
Jack     Sam      0.4
Jack     Jill     0.2
Mike     Jack     0.4
Mike     Sara     0.5    
...

From this point, I would like to create all nodes for the people: Jack, Sara, Sam, Mike, etc and as well as their relationship with a property name points.

First I tried to match all nodes and then use "FOREACH" to update the relationship property one at a time.

tx = graph.cypher.begin()
qs2 = "MATCH (p1:person {name:"Jack"}), (p2:person) 
       WHERE p2.name IN ["Sara","Jill","Mike"] 
       FOREACH (r IN range(10) | 
         CREATE (p1)-[:OWES TO {score:{score_list}[r]}]->(p2))"

Above statement does not return what I expected. Instead of matching one node to another, it calls all nodes in p2 and create the relationship between the paris, resulting multiple copies of the same information.

Is there a notation to indicate one node at a time? If you think there is a better approach than above, please do share with me. Thank you!

Michael Hunger
  • 41,339
  • 3
  • 57
  • 80
user4279562
  • 669
  • 12
  • 25
  • `range(10)` is an invalid function call, and where do you get {score_list} from and what's in there? – Michael Hunger Nov 26 '14 at 22:22
  • range (0,10) is actually how it was used in the code. The above is just for demonstration, sorry for the confusion. {score_list} is a parameter which is expressed using the curly brackets. – user4279562 Nov 27 '14 at 09:27

1 Answers1

3

The easiest approach would be to export the data to be imported into csv file and use then the LOAD CSV command in cypher.

LOAD CSV WITH HEADERS FROM <url> AS csvLine
MATCH (p1:Person {name:csvLine.name1}), (p2:Person {name:csvLine.name2})
CREATE (p1)-[:OWES_TO {score:csvLine.points}]->(p2)

In case you cannot use that approach you can use a parameterized Cypher statement using the transactional http endpoint. The parameter is a single element map containing an array of your data structure. On http level the request body would look like:

{
   "statements": [
       {
           "parameters": {
               "data": [
                   {
                       "name1": "Jack", "name2": "Sara", "points": 0.3 
                   }, 
                   {
                       "name1": "Jack", "name2": "Sam", "points": 0.4
                   }, 
                   {
                       "name1": "Jack", "name2": "Jill", "points": 0.2
                   }  // ...
               ]
           }, 
           "statement": "UNWIND {data} AS row     
                         MATCH (p1:Person {name:row.name1}), (p2:Person {name:row.name2})
                         CREATE (p1)-[:OWES_TO {row.points}]->(p2)"
       }
   ]
}

update regarding comment below

Q: How can I create the parameters from pyhton? A: use the python json module

import json
json.dumps({'data':[{'name1':'Jack', 'name2':'Sara', 'points':0.3},{'name1':'Jack', 'name2':'Sam', 'points':0.4}]})
Stefan Armbruster
  • 39,465
  • 6
  • 87
  • 97
  • That's very good suggestion. One thing, however, is how do you suggest to create the "statement" data structure? My data is returned as a list in my python program. In order to implement your UNWIND trick, does the data have to be in the dictionary format as it is above? Thanks. – user4279562 Nov 27 '14 at 09:29
  • don't know python very well, but there should be a way to create json out of a nested data structure. If you have a dict with a single key `data` whose value is an array of dicts you should be fine. – Stefan Armbruster Nov 27 '14 at 09:31
  • in fact it's pretty simple, see my updated answer above – Stefan Armbruster Nov 27 '14 at 09:36
  • Great! Thank you! This will make the code look nicer. – user4279562 Nov 27 '14 at 17:25