Article DetailsDetailsHelp Details As queries execute, they build up result rows. Cypher executes operations per-row. When a query is made up of completely separate parts, unrelated to each other, and you don’t want to split the single query into multiple queries, you sometimes need a way to reset cardinality back to 1 to avoid executing an operation multiple times. For example, using the Movies graph, let’s write a query to label actors, and then create a new :Movie node. MATCH (p:Person) WHERE (p)-[:ACTED_IN]->(:Movie) SET p:Actor CREATE (:Movie{title:'The Animatrix'}) When run all in a single query, you’ll see that multiple 'The Animatrix' nodes were created, not just one. This is because the CREATE clause executes per row, and we have one row for each :Actor just before the CREATE executes. So, when you're not careful about cardinality, it is possible for operations to execute more times than you may expect, which may lead to incorrect behavior, which can include, but is not limited to, duplicated data. While you could get around the extra node creations by using MERGE instead of CREATE, you still pay the cost of executing multiple redundant MERGE operations per row, db hits that are completely unnecessary. Circumventing the issue with subqueries Subqueries are one means of executing work per incoming row, and come in many types. Among these two are very useful for avoiding the need to reset cardinality completely. Unit subqueries Unit subqueries , introduced in Neo4j 4.4, only perform write operations, and do not RETURN anything. A subquery with a lack of a RETURN will be a unit subquery, and as such it will not change cardinality, so the number of rows will not change no matter what happens within the subquery. The example above is a perfect candidate to make use of a unit subquery, because the setting of the actor is completely independent from the creation of a movie node, and with this approach cardinality will remain at 1 row no matter how many persons or movies are in the graph: CALL { MATCH (p:Person) WHERE (p)-[:ACTED_IN]->(:Movie) SET p:Actor} CREATE (:Movie{title:'The Animatrix'}) Inline subqueries Inline subqueries do not use the CALL keyword, and are not clauses, but expressions, and can be used within a WITH clause, and include both Collect subqueries (introduced in Neo4j 5.6) and Count subqueries (introduced in Neo4j 5.0). These line subqueries naturally execute per row, and evaluate to either a collection, or a numeric count (depending on the type) on that row. Cardinality does not change when using these inline subqueries, and so there is no need to reset cardinality. When you do need to manual reset cardinality To reset cardinality back to 1 before the next part of the query, you’ll need to use WITH DISTINCT on some arbitrary value. This should not be a variable but a constant value of some kind, like a number: MATCH (p:Person) WHERE (p)-[:ACTED_IN]->(:Movie) SET p:Actor WITH DISTINCT 1 AS ignored CREATE (:Movie{title:'The Animatrix'}) You could alternate perform a count() aggregation, with no grouping key, which will quickly get you back to single row: MATCH (p:Person) WHERE (p)-[:ACTED_IN]->(:Movie) SET p:Actor WITH count(*) AS ignored CREATE (:Movie{title:'The Animatrix'}) InformationTitleResetting query cardinalityArticle Created Date3/15/2024, 10:56 PMURL Name115005078048-Resetting-query-cardinalityLast Modified Date7/1/2025, 7:46 AM