Article DetailsDetailsHelp DetailsWhile path matching in Cypher prevents traversing across a relationship already traversed within the current path (a characteristic in Cypher's path matching logic called relationship isomorphism), cycles are still possible since nodes previously visited in the path can be visited again, via other relationships. Here are some ways you can efficiently perform acyclic path matching, where no node is revisited in a path, every node unique. ACYCLIC path mode As part of conformance to the GQL (Graph Query Language) standard, Cypher now includes the ACYCLIC path mode, and you can use this keyword when using MATCH with a path variable to ensure we never repeat nodes when matching out the path: MATCH path = ACYCLIC (k:Person {name:'Keanu Reeves'}) (()-[]-(next)){0,5} (end)RETURN count(path) as pathsWithUniqueNodesCount This is the easiest way to perform ACYCLIC path matching. The feature is only available using Cypher 25 in version Neo4j 2026.03 and newer. APOC path expanders using NODE_PATH uniqueness APOC Procedures provides some path expansion capabilities that can change the uniqueness behavior during expansion. One of these is called NODE_PATH uniqueness, which means that within a path, nodes are unique, and cannot be revisited, resulting in acyclic paths. Keep in mind that the path expander procedures have limits, especially with respect to any kind of property filtering, or more advanced filtering during expansion, such as filtering for patterns present (or not present) on expanded nodes. Also note that NODE_GLOBAL uniqueness (used in subgraphNodes(), spanningTree(), and subgraphAll() procedures) can also only output acyclic paths, though the resulting behavior is more strict: each node can only be visited once total, so once a path to any node is found during expansion, any other path found to the node will be discarded and not returned in the results. This fits NODE_GLOBAL usage for questions of reachability, and finding unique connected nodes. allReduce() list predicate to filter during expansion Introduced in Neo4j 2025.08 (and available only when using Cypher 25 or later in your database), allReduce() is a function predicate that allows accumulation of results during expansion, and we can use that to filter and prune paths as we expand. Using the built-in movies graph, we can use allReduce() to accumulate the nodes in the path, and ensure that the one we're processing hasn't already been visited. Since we have head() and tail() functions easily available for lists, it's best to append new nodes to the front of the list of visited nodes, for easy comparison. MATCH path = (k:Person {name:'Keanu Reeves'}) (()-[]-(next)){0,5} (end) WHERE allReduce(acc = [k], nextNode IN next | nextNode + acc, NOT head(acc) IN tail(acc)) RETURN count(path) as pathsWithUniqueNodesCount Inefficient choices If you are not using a Neo4j version that allows any of the above approaches, the only remaining choices will be ones that will produce correct results, but will be inefficient since they cannot filter and prune during expansion, and so will have far more matching paths to filter. MATCH path = (k:Person {name:'Keanu Reeves'}) (()-[]-(next)){0,5} (end) WHERE NOT apoc.coll.containsDuplicates(nodes(path)) RETURN count(path) as pathsWithUniqueNodesCount InformationTitleAcyclic path matchingArticle Created Date11/22/2025, 2:18 AMURL NameAcyclic-path-matchingLast Modified Date5/11/2026, 7:37 PM