Method to create relationship between two nodes using python driver

I want to create a method that accepts the names of two nodes and a relationship type name, and creates a relationship of that type between the nodes. I'm having trouble figuring out how to reference the relationship name that I'm passing into the method within my query. The version I tried below gives me an error: Invalid input '$': expected whitespace or a rel type name.
Does anyone know how I can create the relationship with the argument that gets passed in to the method?

def create_relationship(tx, node1_name, node2_name, rel_type):
    query = (
        "MATCH (n1:Resource) "
        "WITH n1 "
        "MATCH (n2:Resource) "
        "WHERE n1.name = $node1_name AND n2.name = $node2_name "
        "MERGE (n1)-[r:$rel_type]->(n2) "
        "RETURN n1, n2, r"
    )
    result = tx.run(query, node1_name=node1_name, node2_name=node2_name)
    try:
        return [{"n1": record["n1"]["name"], "n2": record["n2"]["name"], "r":record["r"]}
               for record in result]
    except ServiceUnavailable as exception:
        logging.error("{query} raised an error: \n {exception}".format(
            query=query, exception=exception))
        raise 

        
with driver.session() as session:
    result = session.write_transaction(create_relationship, "Florence", "piazzale Michelangelo", "CONTAINS_POI")
    for record in result:
            print("Created {r} relationship between: {n1} and {n2}".format(
                r=record['r'], n1=record['n1'], n2=record['n2']))

driver.close()

So there's a couple of things going on here the first is you aren't submitting a parameter called rel_type when you do this:

result = tx.run(query, node1_name=node1_name, node2_name=node2_name)

Second -- I think you can't use cypher parameters for labels and reltypes, that kind of parameter interpolation doesn't work in cypher. You might need to convert the relationship to a map and check its type key

1 Like

Thank you! You're right, I neglected to pass in the rel_type param when actually calling the method. I also found an APOC method that I could use to get the functionality I want: apoc.create.relationship - APOC Documentation. Here's what my method looks like now, in case it helps anyone in the future:

def create_relationship(tx, node1_name, node2_name, rel_type):
   query = (
       "MATCH (n1:Resource) "
       "WITH n1 "
       "MATCH (n2:Resource) "
       "WHERE n1.name = $node1_name AND n2.name = $node2_name "
       "CALL apoc.create.relationship(n1, $rel_type, {}, n2) YIELD rel "
       "RETURN n1, n2, rel"
   )
   result = tx.run(query, node1_name=node1_name, node2_name=node2_name, rel_type=rel_type)
   try:
       return [{"n1": record["n1"]["name"], "n2": record["n2"]["name"], "r": record["rel"].type}
              for record in result]
   except ServiceUnavailable as exception:
       logging.error("{query} raised an error: \n {exception}".format(
           query=query, exception=exception))
       raise