user4279562
user4279562

Reputation: 669

Creating unique relationship property in a FOREACH in neo4j

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!

Upvotes: 3

Views: 565

Answers (1)

Stefan Armbruster
Stefan Armbruster

Reputation: 39925

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}]})

Upvotes: 3

Related Questions