What’s new and what’s been deprecated in Cypher in the latest release of Neo4j
A couple of weeks ago, Neo4j 5 was released. If you are like me and have ignored all the deprecation warnings during the later Neo4j 4 version, you might have to update your Cypher queries to work with the latest Neo4j version. Luckily, there are no significant differences in the new Cypher syntax, so the update process should not be difficult. However, I have decided to write this blog post to help you transition. Additionally, I will introduce some of the new Cypher syntax that could simplify your queries.
The Cypher examples of this blog post are available as a application. On the other hand, you can use a free cloud instance available as
The Dune dataset is available on Kaggle under the CC0 license. To make it easier for you, I have copied the dataset to a GitHub repository, so you don’t have to download the dataset and can easily import it in either your local or cloud instance of Neo4j. Additionally, I have renamed the relationship types Parent-Child and Other Family to Family, and removed the Unknown relation.
Graph Model

The graph model revolves around characters. The character nodes have multiple properties like the name, Culture, and when they were Born or Died. Additionally, their house allegiance is represented as a secondary node label. The main idea for using the secondary node label instead of a separate node is to demonstrate the new node label filtering options in Cypher. There are four types of relationships between characters:
- ALLIES
- ENEMIES,
- FAMILY
- MARRIAGE
Dataset import
As with most imports, you first want to define unique constraints in Neo4j. Unique constraints ensure that a given property is unique for every node with a particular label.
The syntax for defining unique constraints has slightly changed in Neo4j v5.

The new syntax for unique constraints has two keywords replaced. The ON keyword is replaced with FOR, while the ASSERT is changed to REQUIRE.
The following Cypher statements define the unique constraint for name property of Character nodes.
CREATE CONSTRAINT IF NOT EXISTS FOR (c:Character) REQUIRE c.name IS UNIQUE;
Next, you need to import the CSV file. Even though the Dune CSV file has only 1000 rows, you will pretend you are dealing with a large CSV file with many thousands of rows. Therefore, you want to use batch import into multiple transactions. As USING PERIODIC COMMIT clause has been deprecated in Neo4j v5, you need to use the new batched transaction syntax.

The subqueries were already introduced in Neo4j v4 but have taken on a more prominent role in v5. The subqueries are instantiated with a CALL clause and wrapped with curly brackets {}. They are great for various functionalities like , and was my go-to option for the better part of my blog post. However, as the theme of this blog post are Cypher subqueries, I have decided to show you how to use Cypher subqueries for conditional execution. First, with the nested Cypher subquery, you need to import both the row and the c variables. Next, you need to filter out only rows where the to column is not null. However, you cannot filter variables in the same WITH clause used to import them. Therefore, you need to add a second WITH clause to filter rows. Lastly, you use the APOC’s procedure for merging relationships, as the plain Cypher syntax does not support creating properties with dynamic relationship types.
You can check out the .
Count subqueries
The last category of subqueries in this post is the so-called count subqueries. They are used to count the number of defined graph patterns. For example, I frequently used them in my previous blog posts to count the number of relationships a node has.

Previously, you could wrap a graph pattern with the size() in order to count the number of particular patterns. It is a handy syntax to count graph patterns without affecting the cardinality of the main query. Additionally, it might outperform other approaches to counting the number of relationships. In Neo4j v5, you need to replace the size() operator with the count{}.
The following Cypher statement returns the top five Character node ordered by their degree (relationship count).
MATCH (c:Character)
RETURN c.name AS character,
count{ (c)--() } AS degree
ORDER BY degree DESC
LIMIT 5
As before, you can filter nodes by using the counting subqueries in a WHERE clause. In this example, the Cypher statement filters nodes with more than relationships.
MATCH (c:Character)
WHERE count{ (c)--() } > 2
RETURN count(*) AS count
Summary
The new version of Neo4j offers faster performance and more Cypher flexibility. However, you might have to refactor a few of your existing Cypher statements to work with Neo4j v5. Hopefully, this blog post will help you with the upgrade process.
As always, the code is available on was originally published in Towards Data Science on Medium, where people are continuing the conversation by highlighting and responding to this story.
SOCIAL SHARE CARD GENERATOR