0
votes

Iam searching for the right cypher query to get the first and last nodes of paths when selecting a node which is in between. The idea is to compress a large impact graph so that only the sources (only outgoing edges = green nodes) and the final consequences (only incoming edges = red nodes) as well as the selected node is displayed.

Here is an illustrative example graph:

Example Graph

Now, when selecting e.g node d, i would like to receive node d and the first node and last node of every path in which node d is part of as well as the respective (new) relationships so that the output is the follwing graph:

enter image description here

Hence, Iam searching for a kind of collapsing where the start and end nodes are excluded.

Due to this answer I already know that is possible to create virtual graphs with apoc.create.vRelationship.

But Iam struggling with the identification of the green start nodes and red end nodes as described above as well as the creation of the desired output.

Iam searching for a query where only the node in between (e.g node d) is a parameter and the output is always like in the second image.

I appreciate every help or inspiration a lot, thank you in advance!

2

2 Answers

0
votes

This query would return node d (filtering here by a name property just as an example) and all related edge nodes:

MATCH (d {name: "d"})-[:RELATED_TO*]-(n)
WHERE NOT ((n)-[:RELATED_TO]->() AND (n)<-[:RELATED_TO]-())
RETURN d, n

The condition for the edge nodes would be that they don't have :RELATED_TO relationships in both directions.

0
votes

For your illustrated data model (assuming the desired middle node is neither the start nor end node):

MATCH (start)-[:RELATED_TO*]->(middle)-[:RELATED_TO*]->(end)
WHERE
  middle.id = 123 AND
  NOT EXISTS(()-[:RELATED_TO]->(start)) AND
  NOT EXISTS((end)-[:RELATED_TO]->())
RETURN start, middle, end,
  apoc.create.vRelationship(start, 'RELATED_TO', {}, middle) as pre_rel,
  apoc.create.vRelationship(middle, 'RELATED_TO', {}, end) as post_rel

[UPDATE]

The above query can, unfortunately, create duplicate virtual relationships. This one does not:

MATCH (middle)
WHERE middle.id = 123
MATCH (start)-[:RELATED_TO*]->(middle)
WHERE NOT EXISTS(()-[:RELATED_TO]->(start))
WITH middle, COLLECT(start) AS starts, COLLECT(apoc.create.vRelationship(start, 'RELATED_TO', {}, middle)) AS vr1s
MATCH (middle)-[:RELATED_TO*]->(end)
WHERE NOT EXISTS((end)-[:RELATED_TO]->())
RETURN middle, starts, COLLECT(end) AS ends, vr1s, COLLECT(apoc.create.vRelationship(middle, 'RELATED_TO', {}, end)) AS vr2s

NOTE: You also need to uncheck the "Connect result nodes" option in the Browser Settings (click on the Gear icon in the Browser's left panel), or else some "real" relationships will also be displayed.