Creating Relationships

About this module

You have learned how to create nodes in the graph, add and remove labels from them, and also add, remove, and update properties for a node. Next, you will learn how to create a relationship between two existing nodes in the graph.

At the end of this module, you will write Cypher statements to:

  • Create a relationship.

  • Create a relationship with properties.

  • Create nodes and relationships together.

  • Add properties to a relationship.

  • Remove properties from a relationship.

Because the code examples in this lesson modify the database, it is recommended that you do not execute them against your database as you will be doing so in the hands-on exercises.

Syntax: Creating relationships

As you have learned in the course, Querying with Cypher in Neo4j 4.x, when you query the graph, you often query using connections between nodes (pattern). The connections capture the semantic relationships and context of the nodes in the graph.

Here is the simplified syntax for creating a relationship between two nodes referenced by the variables x and y:

CREATE (x)-[:REL_TYPE]->(y)
CREATE (x)<-[:REL_TYPE]-(y)

When you create the relationship, it must have direction. You can query nodes for a relationship in either direction, but you must create the relationship with a direction.

In most cases, unless you are connecting nodes at creation time, you will retrieve the two nodes, each with their own variables, for example, by specifying a WHERE clause to find them, and then use the variables to connect them.

Example: Creating a relationship

Here is an example. We want to connect the actor, Michael Caine with the movie, Batman Begins. We first retrieve the nodes of interest, then we create the relationship:

MATCH (a:Person), (m:Movie)
WHERE a.name = 'Michael Caine' AND m.title = 'Batman Begins'
CREATE (a)-[:ACTED_IN]->(m)
RETURN a, m

Before you run this Cypher code, you may see a warning in Neo4j Browser that you are creating a query that is a cartesian product that could potentially be a performance issue.

CartesianBeforeCreateRelationship

If you are familiar with the data in the graph and can be sure that the MATCH clauses will not retrieve large amounts of data, you can continue.

In our case, we are simply looking up a particular Person node and a particular Movie node so we can create the relationship.

Here is the result of running this Cypher statement:

CreateActedInRelationship

Creating multiple relationships

You can create multiple relationships at once by simply providing the pattern for the creation that includes the relationship types, their directions, and the nodes that you want to connect.

Here is an example where we have already created Person nodes for an actor, Liam Neeson, and a producer, Benjamin Melniker. We create two relationships in this example, one for :ACTED_IN and one for :PRODUCED.

MATCH (a:Person), (m:Movie), (p:Person)
WHERE a.name = 'Liam Neeson' AND
      m.title = 'Batman Begins' AND
      p.name = 'Benjamin Melniker'
CREATE (a)-[:ACTED_IN]->(m)<-[:PRODUCED]-(p)
RETURN a, m, p

Here is the result of running this Cypher statement:

CreateTwoRelationships
When you create relationships based upon a MATCH clause, you must be certain that only a single node is returned for the MATCH, otherwise multiple relationships will be created.

Creating a relationship with properties

Just as you can create a node with inline properties, you can create a relationship with inline properties.

MATCH (a:Person), (m:Movie)
WHERE a.name = 'Katie Holmes' AND m.title = 'Batman Begins'
CREATE (a)-[rel:ACTED_IN {roles: ['Rachel','Rachel Dawes']}]->(m)
RETURN a.name, rel, m.title

Here is the result of running this code:

KatieHolmsRoles

Creating nodes and relationships together

You have learned how to create nodes using the CREATE clause, and how to find existing nodes to create relationships between them. In Cypher, you can combine the creation of the nodes and relationships in a single execution.

MATCH (m:Movie)
WHERE m.title = 'Batman Begins'
CREATE (a:Person)-[:ACTED_IN]->(m)
SET a.name = 'Gary Oldman', a.born=1958
RETURN a, m

Here is the result of running this Cypher statement:

CreateNodeAndRelationship

We retrieve the movie node for Batman Begins. Then we create a Person node, a, with the :ACTED_IN relationship to the movie. We then set two properties for the Person node.

You might use code like this when you are creating a script to load many actors and relate them to a movie.

What you must be careful of, however is that when you create the node, it is not a duplicate node. In addition, you must ensure that there is always only one :ACTED_IN relationship created between two nodes. In the course, Using Indexes and Query Best Practices in Neo4j 4.x, you will learn how automatically eliminate duplication of nodes and relationships.

Syntax: Adding properties to relationships

You can add properties to a relationship, just as you add properties to a node. You use the SET clause to do so.

Here is the simplified syntax for adding properties to a relationship referenced by the variable r:

SET r.propertyName = value
SET r.propertyName1 = value1 , r.propertyName2 = value2
SET r = {propertyName1: value1, propertyName2: value2}
SET r += {propertyName1: value1, propertyName2: value2}

If the property does not exist, it is added to the relationship. If the property exists, its value is updated for the relationship. When specify the JSON-style object for assignment to the relationship using =, the object must include all of the properties for the relationship, just as you need to do for nodes. If you use +=, you can add or update properties, just as you do for nodes.

Example: Adding properties to a relationship

Here is an example where we will add the roles property to the :ACTED_IN relationship from Christian Bale to Batman Begins right after we have created the relationship:

MATCH (a:Person), (m:Movie)
WHERE a.name = 'Christian Bale' AND m.title = 'Batman Begins'
CREATE (a)-[rel:ACTED_IN]->(m)
SET rel.roles = ['Bruce Wayne','Batman']
RETURN a, rel, m

Here is the result of running this Cypher statement:

AddRelationshipWithRoles

The roles property is a list so we add it as such. If the relationship had multiple properties, we could have added them as a comma separated list or as an object, like you can do for node properties.

Example: Adding properties inline

Alternatively, you can also add properties to a relationship when the relationship is created. Here is another way to create and add the properties for the relationship:

MATCH (a:Person), (m:Movie)
WHERE a.name = 'Christian Bale' AND m.title = 'Batman Begins'
CREATE (a)-[:ACTED_IN {roles: ['Bruce Wayne', 'Batman']}]->(m)
RETURN a, m

By default, the graph engine will create a relationship between two nodes, even if one already exists. This could be dangerous so in your code make sure that if you use CREATE to create a relationship, it does not already exist.

Example: Testing before creating relationship

You can test to see if the relationship exists before you create it as follows:

MATCH (a:Person),(m:Movie)
WHERE a.name = 'Christian Bale' AND
      m.title = 'Batman Begins' AND
      NOT exists((a)-[:ACTED_IN]->(m))
CREATE (a)-[rel:ACTED_IN]->(m)
SET rel.roles = ['Bruce Wayne','Batman']
RETURN a, rel, m
The best way to prevent duplication of relationships is to use the MERGE clause, rather than the CREATE clause. You will learn about merging data later in this course.

Removing properties from a relationship

There are two ways that you can remove a property from a relationship. One way is to use the REMOVE keyword. The other way is to set the property’s value to null, just as you do for properties of nodes.

Suppose we have added the :ACTED_IN relationship between Christian Bale and the movie, Batman Returns where the roles property is added to the relationship. Here is an example where we remove the roles property, yet keep the :ACTED_IN relationship:

MATCH (a:Person)-[rel:ACTED_IN]->(m:Movie)
WHERE a.name = 'Christian Bale' AND m.title = 'Batman Begins'
REMOVE rel.roles
RETURN a, rel, m

Here is the result returned. An alternative to REMOVE rel.roles would be SET rel.roles = null.

RemoveRoles

Exercise 10: Creating relationships

In the query edit pane of Neo4j Browser, execute the browser command:

:play 4.0-intro-neo4j-exercises

and follow the instructions for Exercise 10.

This exercise has 13 steps. Estimated time to complete: 45 minutes.

Check your understanding

Question 1

Suppose our graph has a Person node for Tom Jones and a Movie node for the movie Life is Wonderful. We want to connect these two nodes with the ACTED_IN relationship. What is wrong with this code?

MATCH (a:Person), (m:Movie)
WHERE a.name = 'Tom Jones' AND m.title = 'Life is Wonderful'
CREATE (a)-[rel:ACTED_IN]-(m)

Select the correct answer.

  • CREATE must be replaced with CREATE RELATIONSHIP.

  • You cannot specify a variable for a relationship.

  • Direction must be specified when you create the relationship.

  • You cannot return the variable, rel.

Question 2

Given this code, what Cypher clause do you use to add the roles property to the relationship?

CREATE (p:Person {name: 'Jack Brown'})
CREATE (m:Movie {title: 'The Goods'})
CREATE (p)-[r:ACTED_IN]->(m)
?? r = {roles: ['The Villain']}

Select the correct answer.

  • CREATE

  • CREATE PROPERTY

  • SET

  • SET PROPERTY

Question 3

Assuming the nodes are successfully retrieved, how many relationships are created?

MATCH (a:Person), (m:Movie)
WHERE a.name = 'Tom Jones' AND m.title = 'Life is Wonderful'
CREATE (a)-[:ACTED_IN]->(m)
CREATE (a)-[:ACTED_IN {roles: ['The Villain']}]->(m)
CREATE (a)-[:ACTED_IN {roles: ['The Villain','Joe']}]->(m)

Select the correct answer.

  • None

  • One

  • Two

  • Three

Summary

You can now write Cypher statements to:

  • Create a relationship.

  • Create a relationship with properties.

  • Create nodes and relationships together.

  • Add properties to a relationship.

  • Remove properties from a relationship.