Incorrect Traversal Stopping Condition in Neo4j

I have a Cypher query that is supposed to create IMPACT relationships between an Issue node and Version nodes in a version chain.

MATCH (problem:Issue {id: $issueId})
MATCH path = (problem)-[:FIRST_AFFECTED]->(firstVersion:Version)
        (()<-[:PREDECESSOR_VERSION]-(nextVersion:Version) WHERE NOT EXISTS { (nextVersion)<-[:FIXED]-(problem) })*
        (affectedVersion:Version)
MERGE (problem)-[:IMPACT]->(affectedVersion)

UNION

MATCH (problem:Issue {id: $issueId})
MATCH path = (problem)-[:FIXED]->(fixedVersion:Version)
        (()-[:PREDECESSOR_VERSION]->(upVersion:Version) WHERE NOT EXISTS { (upVersion)<-[:FIRST_AFFECTED | IMPACT | FIXED]-(problem) })*
        (affectedVersion:Version)
WHERE affectedVersion <> fixedVersion
MERGE (problem)-[:IMPACT]->(affectedVersion)

WITH problem, affectedVersion

MATCH path = (affectedVersion)<-[:PREDECESSOR_VERSION*]-(childVersion:Version)
WHERE NOT EXISTS { (childVersion)<-[:FIXED | FIRST_AFFECTED | IMPACT]-(problem) }
MERGE (problem)-[:IMPACT]->(childVersion)

The query consists of two parts joined by a UNION. The first part handles versions affected by the issue, and the second part handles versions fixed by the issue. The issue arises in the second part of the query, specifically in the following section:

MATCH path = (affectedVersion)<-[:PREDECESSOR_VERSION*]-(childVersion:Version)
WHERE NOT EXISTS { (childVersion)<-[:FIXED | FIRST_AFFECTED | IMPACT]-(problem) }
MERGE (problem)-[:IMPACT]->(childVersion)

The problem is that this part of the query does not stop traversing the version chain when it encounters a Version node that has a FIXED, FIRST_AFFECTED, or IMPACT relationship with problem. Instead, it continues to create IMPACT relationships for all parent versions, except the one with the FIXED relationship.

Example Graph:

Consider the following version chain:

If an Issue has a FIXED relationship with v2, the query should only create an IMPACT relationship with v1. However, it creates IMPACT relationships with all versions from v1 to v10, except v2.

How can I modify the query to ensure that the traversal stops when it encounters a Version node with a FIXED, FIRST_AFFECTED, or IMPACT relationship, and only creates IMPACT relationships up to that point?

This is due to the fact that the variable length query returns a result for each path from the affected node to each version. It then filters out the paths whose last version node in the chain does not have the relationship to the problem node.

Do you want to only create the relationship from the last version node to the problem node, if it doesn’t exist? If so, add an additional predicate to return only the path that has the last version node.

MATCH path = (affectedVersion)<-[:PREDECESSOR_VERSION*]-(childVersion:Version)
WHERE NOT EXISTS ( (childVersion)<-[:PREDECESSOR_VERSION]-(:Version) )
AND NOT EXISTS { (childVersion)<-[:FIXED | FIRST_AFFECTED | IMPACT]-(problem) }
MERGE (problem)-[:IMPACT]->(childVersion)

hi, the new query creates an extra IMPACT relationship with the version at the very end of the chain

What should the solution look like? Can you sen a script to generate test data?

Impact relations in this example should be created only for the 1st and 2nd version before the FIXED relation, the solution you provided passes almost all my test cases, but fails at this point, when there is only one FIXED relation in the graph, because it creates one additional relation at the end of the chain.

UNWIND range(1, 10) AS id
CREATE (v:Version {id: id});

WITH [
{from: 1, to: 2},
{from: 2, to: 3},
{from: 3, to: 4},
{from: 4, to: 5},
{from: 5, to: 6},
{from: 6, to: 7},
{from: 7, to: 8},
{from: 8, to: 9},
{from: 9, to: 10}
] AS relationships
UNWIND relationships AS rel
MATCH (from:Version {id: rel.from}), (to:Version {id: rel.to})
CREATE (from)<-[:PREDECESSOR_VERSION]-(to);

CREATE (i:Issue {id: 1})
WITH i
MATCH (v:Version {id: 3})
CREATE (i)-[:FIXED]->(v);