You can generate things like this as queries (this is 2 starting points, same end-point):
// Define your 3 nodes here
MATCH (start1), (start2), (end)
WHERE start1.id = 'A' // โ replace with your start node 1 identifier
AND start2.id = 'B' // โ replace with your start node 2 identifier
AND end.id = 'C' // โ replace with your end node identifier
// Find all paths from each start to the end node
MATCH p1 = (start1)-[*]->(end)
MATCH p2 = (start2)-[*]->(end)
// Extract the relationships from each path
WITH
collect(DISTINCT p1) AS paths1,
collect(DISTINCT p2) AS paths2
// Flatten all edges across all paths for each start node
WITH
[p IN paths1 | relationships(p)] AS relSets1,
[p IN paths2 | relationships(p)] AS relSets2
WITH
apoc.coll.toSet(apoc.coll.flatten(relSets1)) AS edges1,
apoc.coll.toSet(apoc.coll.flatten(relSets2)) AS edges2
// Compute intersection and union
WITH
edges1, edges2,
[e IN edges1 WHERE e IN edges2] AS intersection,
apoc.coll.toSet(edges1 + edges2) AS union
// Calculate overlap % (Jaccard similarity)
WITH
size(intersection) AS sharedEdges,
size(union) AS totalEdges,
size(edges1) AS edgesPath1,
size(edges2) AS edgesPath2,
toFloat(size(intersection)) / toFloat(size(union)) * 100 AS overlapPct
// Apply 4-grade scale
WITH *,
CASE
WHEN overlapPct >= 75 THEN '4 - High overlap (โฅ75%)'
WHEN overlapPct >= 50 THEN '3 - Moderate overlap (50โ74%)'
WHEN overlapPct >= 25 THEN '2 - Low overlap (25โ49%)'
ELSE '1 - Minimal overlap (<25%)'
END AS overlapGrade
RETURN
edgesPath1 AS totalEdgesFromStart1,
edgesPath2 AS totalEdgesFromStart2,
sharedEdges AS sharedEdges,
totalEdges AS unionEdges,
round(overlapPct, 2) AS overlapPct,
overlapGrade
this one has 2 pairs of [starting, end] and consider overlap
// Define your 2 pairs of start/end nodes
MATCH (start1), (end1), (start2), (end2)
WHERE start1.id = 'A' // โ replace with your pair 1 start node identifier
AND end1.id = 'B' // โ replace with your pair 1 end node identifier
AND start2.id = 'C' // โ replace with your pair 2 start node identifier
AND end2.id = 'D' // โ replace with your pair 2 end node identifier
// Find all paths for each pair
MATCH p1 = (start1)-[*]->(end1)
MATCH p2 = (start2)-[*]->(end2)
// Collect all paths per pair
WITH
collect(DISTINCT p1) AS paths1,
collect(DISTINCT p2) AS paths2
// Flatten all edges across all paths for each pair
WITH
apoc.coll.toSet(apoc.coll.flatten([p IN paths1 | relationships(p)])) AS edges1,
apoc.coll.toSet(apoc.coll.flatten([p IN paths2 | relationships(p)])) AS edges2
// Compute intersection and union
WITH
edges1, edges2,
[e IN edges1 WHERE e IN edges2] AS intersection,
apoc.coll.toSet(edges1 + edges2) AS union
// Calculate Jaccard overlap %
WITH
size(intersection) AS sharedEdges,
size(union) AS totalEdges,
size(edges1) AS edgesPair1,
size(edges2) AS edgesPair2,
toFloat(size(intersection)) / toFloat(size(union)) * 100 AS overlapPct
// Apply 4-grade scale
WITH *,
CASE
WHEN overlapPct >= 75 THEN '4 - High overlap (โฅ75%)'
WHEN overlapPct >= 50 THEN '3 - Moderate overlap (50โ74%)'
WHEN overlapPct >= 25 THEN '2 - Low overlap (25โ49%)'
ELSE '1 - Minimal overlap (<25%)'
END AS overlapGrade
RETURN
edgesPair1 AS totalEdgesPair1,
edgesPair2 AS totalEdgesPair2,
sharedEdges AS sharedEdges,
totalEdges AS unionEdges,
round(overlapPct, 2) AS overlapPct,
overlapGrade