Creating relations between countries in neo4j using python

Question:

I need help with creating relations between countries in neo4j using python. I have a code, but in neo4j browser it doesn’t create relations.

from neo4j import GraphDatabase
driver = GraphDatabase.driver("neo4j://localhost:7687",
                              auth=("neo4j", "test"))

def create_country(tx, name,continent,population_mln,govrm_system,bcountry):
    tx.run("CREATE (a:Country {name: $name,continent: $continent,population_mln: $population_mln,govrm_system:$govrm_system,bcountry: $bcountry})",
           name=name,continent=continent,population_mln=population_mln,govrm_system=govrm_system,bcountry=bcountry)

with driver.session() as session:
    session.execute_write(create_country, "russia","Asia",143,"terrorist state",["Kazakhstan","Lithuania","Finland","China","Japan"])
    session.execute_write(create_country, "India","Asia",1393,"Parliamentary Republic","China")
    session.execute_write(create_country, "China","Asia",1412,"One-party state",["India","russia","Philipines","Japan"])
    session.execute_write(create_country, "Poland","Europe",37,"Parliamentary Republic",["Lithuania","Germany","Czechia"])
    session.execute_write(create_country, "Kazakhstan","Asia",19,"Presidential system Republic","russia")
    session.execute_write(create_country, "Lithuania","Europe",2.7,"Parliamentary Republic",["russia","Poland"])
    session.execute_write(create_country, "Finland","Europe",5.5,"Parliamentary Republic","russia")
    session.execute_write(create_country, "Philipines","Asia",111,"Parliamentary Republic",["Japan","China"])
    session.execute_write(create_country, "Japan","Asia",125,"Constitutional Monarchy",["Philipines","China","russia"])
    session.execute_write(create_country, "Germany","Europoe",83,"Parliamentary Republic",["Czechia","Austria","Poland"])
    session.execute_write(create_country, "Czechia","Europoe",10,"Parliamentary Republic",["Austria","Poland","Germany"])
    session.execute_write(create_country, "Austria","Europoe",9,"Parliamentary Republic",["Czechia","Germany"])

def create_bordering_country(tx, name, bcountry):
    tx.run("FOREACH (n IN a.bcountry | MERGE (bcountry:Country {name: n}) MERGE (a)-[:HAS_BORDER_WITH]-(bcountry))") 

It should look like this:

enter image description here

What I get in neo4j:

enter image description here

I also tried to do like this, but then I get duplicates of countries:

def create_bordering_country(tx, name, bcountry):
    tx.run("MATCH (a:Country) WHERE a.name = $name "
           "MERGE (a)-[:HAS_BORDER_WITH]-(:Country {name: $bcountry}) RETURN DISTINCT a.name",
           name=name, bcountry=bcountry)

session.execute_write(create_bordering_country, "russia", "China")
    session.execute_write(create_bordering_country, "India", "China")
    session.execute_write(create_bordering_country, "russia", "Kazakhstan")
    session.execute_write(create_bordering_country, "russia", "Lithuania")
    session.execute_write(create_bordering_country, "russia", "Finland")
    session.execute_write(create_bordering_country, "Poland", "Lithuania")
    session.execute_write(create_bordering_country, "China", "Japan")
    session.execute_write(create_bordering_country, "Russia", "Japan")
    session.execute_write(create_bordering_country, "Philipines", "Japan")
    session.execute_write(create_bordering_country, "Philipines", "China")
    session.execute_write(create_bordering_country, "Germany", "Poland")
    session.execute_write(create_bordering_country, "Austria", "Poland")
    session.execute_write(create_bordering_country, "Czechia", "Poland")
    session.execute_write(create_bordering_country, "Czechia", "Austria")
    session.execute_write(create_bordering_country, "Czechia", "Germany")
    session.execute_write(create_bordering_country, "Germany", "Austria") 
Asked By: Laura_777

||

Answers:

You are getting duplicates because merge will create more bcountry even if it exists already. Please use below new query.

Function: create_bordering_country

Old code:

 MATCH (a:Country) WHERE a.name = $name 
 MERGE (a)-[:HAS_BORDER_WITH]-(:Country {name: $bcountry}) 
 RETURN DISTINCT a.name

New code:

 MERGE (a:Country) WHERE a.name = $name 
 MERGE (b:Country) WHERE b.name = $bcountry 
 MERGE (a)-[:HAS_BORDER_WITH]-(b) 
 RETURN a.name
Answered By: jose_bacoy

In your first attempt, it doesn’t look like you ever called the create_bordering_country function. I would recommend this approach:

import pandas as pd
from neo4j import GraphDatabase
driver = GraphDatabase.driver("neo4j://localhost:7687",
                              auth=("neo4j", "test"))

country_df = pd.DataFrame([
   ["russia","Asia",143,"terrorist state",["Kazakhstan","Lithuania","Finland","China","Japan"]],
   ["India","Asia",1393,"Parliamentary Republic",["China"]],
   ["China","Asia",1412,"One-party state", ["India","russia","Philipines","Japan"]],
   ["Poland","Europe",37,"Parliamentary Republic",["Lithuania","Germany","Czechia"]],
   ["Kazakhstan","Asia",19,"Presidential system Republic", ["russia"]],
   ["Lithuania","Europe",2.7,"Parliamentary Republic",["russia","Poland"]],
   ["Finland","Europe",5.5,"Parliamentary Republic",["russia"]],
   ["Philipines","Asia",111,"Parliamentary Republic",["Japan","China"]],
   ["Japan","Asia",125,"Constitutional Monarchy",["Philipines","China","russia"]],
   ["Germany","Europoe",83,"Parliamentary Republic",["Czechia","Austria","Poland"]],
   ["Czechia","Europoe",10,"Parliamentary Republic",["Austria","Poland","Germany"]],
   ["Austria","Europoe",9,"Parliamentary Republic",["Czechia","Germany"]]], 
    columns=['name', 'continent', 'populationMillion', 'governmentSystem', 'neighboringCountries'])

node_dicts = country_df[['name', 'continent', 'populationMillion', 'governmentSystem']].to_dict("records")
rel_dicts = country_df[['name', 'neighboringCountries']].to_dict("records")

def create_countries(tx, node_dicts):
    result = tx.run("""UNWIND $nodeDicts as nodeDict
              MERGE (c:Country {name: nodeDict['name']})
              SET c.continent = nodeDict['continent'] ,
                 c.populationMillion = nodeDict['populationMillion'],
                 c.governmentSystem = nodeDict['governmentSystem']""",
          {"nodeDicts": node_dicts})
    summary = result.consume()
    return summary.counters

def create_neighbor_relationships(tx, rel_dicts):
    result = tx.run("""UNWIND $relDicts as relDict
              MATCH (c:Country {name: relDict['name']})
              UNWIND relDict['neighboringCountries'] as neighbor
              MATCH (n:Country {name: neighbor})
              MERGE (c)-[:HAS_BORDER_WITH]->(n)""",
          {"relDicts": rel_dicts})
    summary = result.consume()
    return summary.counters

with driver.session() as session:
    node_results = session.write_transaction(create_countries, node_dicts)
    print(node_results)
    rel_results = session.write_transaction(create_neighbor_relationships, rel_dicts)
    print(rel_results)

I would also recommend creating an index on the name property for the Country nodes.

Answered By: Nathan Smith
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.