1+ // Anomaly Detection Graphs: Find top nodes marked as "Bridge" including their incoming and outgoing dependencies and output them in Graphviz format.
2+
3+ // Step 1: Query overall statistics, e.g. min/max weight for later normalization
4+ MATCH (sourceForStatistics )- [ dependencyForStatistics : DEPENDS_ON ] -> (targetForStatistics )
5+ WHERE $projection_node_label IN labels (sourceForStatistics )
6+ AND $projection_node_label IN labels (targetForStatistics )
7+ WITH max (coalesce (dependencyForStatistics .weight25PercentInterfaces , dependencyForStatistics .weight )) AS maxWeight
8+ // Step 2: Query selected central node
9+ MATCH (central )
10+ WHERE $projection_node_label IN labels (central )
11+ AND central .anomalyBridgeRank = toInteger ($projection_node_rank )
12+ WITH maxWeight
13+ ,central
14+ ,"Top Rank #" + $projection_node_rank + " " + $projection_language + " " + $projection_node_label + " Bridge\\ n" AS graphLabel
15+ ,coalesce (central .fqn , central .globalFqn , central .fileName , central .signature , central .name ) AS targetName
16+ ,[] AS graphVizOutput
17+ WITH * , graphVizOutput + ["graph [label=\" " + graphLabel + targetName + "\\ n\\ n\" ];" ] AS graphVizOutput
18+ WITH * , "🌉 bridge #" + central .anomalyBridgeRank + "\\ n" + central .name AS centralNodeLabel
19+ WITH * , graphVizOutput + ["central [label=\" " + centralNodeLabel + "\" ];" ] AS graphVizOutput
20+ // Step 3: Query direct incoming dependencies to the central node
21+ MATCH (source )- [ dependency : DEPENDS_ON ] -> (central )
22+ WHERE $projection_node_label IN labels (source )
23+ AND source .outgoingDependencies > 0
24+ ORDER BY dependency .weight DESC , source .name ASC
25+ LIMIT 60
26+ WITH * , coalesce (dependency .weight25PercentInterfaces , dependency .weight , 1 ) AS weight
27+ WITH * , round ((toFloat (weight ) / toFloat (maxWeight ) * 2.5 ) + 0.4 , 1.0 ) AS penWidth
28+ WITH * , "label=" + weight + "; weight=" + weight + "; penwidth=" + penWidth AS edgeAttributes
29+ WITH maxWeight
30+ ,central
31+ ,graphVizOutput
32+ ,collect (source ) AS incomingDependencyNodes
33+ ,collect ("\" " + source .name + "\" -> central [" + edgeAttributes + "];" ) AS directInEdges
34+ WITH * , graphVizOutput + directInEdges AS graphVizOutput
35+ // Step 4: Query direct outgoing dependencies from the central node
36+ MATCH (source )<- [ dependency : DEPENDS_ON ] - (central )
37+ WHERE $projection_node_label IN labels (source )
38+ AND source .incomingDependencies > 0
39+ ORDER BY dependency .weight DESC , source .name ASC
40+ LIMIT 60
41+ WITH * , coalesce (dependency .weight25PercentInterfaces , dependency .weight , 1 ) AS weight
42+ WITH * , round ((toFloat (weight ) / toFloat (maxWeight ) * 2.5 ) + 0.4 , 1.0 ) AS penWidth
43+ WITH * , "label=" + weight + "; weight=" + weight + "; penwidth=" + penWidth AS edgeAttributes
44+ // Use a lighter color for the target nodes of outgoing dependencies from the central node and their edges
45+ WITH * , edgeAttributes + "; color = 5" AS edgeAttributes
46+ WITH * , "\" " + source .name + "\" [color = 5; fillcolor = 1;]; " AS directOutNode
47+ WITH maxWeight
48+ ,central
49+ ,graphVizOutput
50+ ,incomingDependencyNodes
51+ ,collect (source ) AS outgoingDependencyNodes
52+ ,collect (directOutNode + "central -> \" " + source .name + "\" [" + edgeAttributes + "];" ) AS directOutEdges
53+ WITH * , graphVizOutput + directOutEdges AS graphVizOutput
54+ WITH * , incomingDependencyNodes + outgoingDependencyNodes AS directDependentNodes
55+ // Step 5: Query dependencies between direct dependencies outside the central node
56+ UNWIND directDependentNodes AS directDependentNode
57+ MATCH (directDependentNode )- [ dependency : DEPENDS_ON ] -> (anotherDirectDependentNode )
58+ WHERE anotherDirectDependentNode IN directDependentNodes
59+ AND anotherDirectDependentNode <> directDependentNode
60+ ORDER BY dependency .weight DESC , directDependentNode .name ASC
61+ WITH maxWeight
62+ ,central
63+ ,graphVizOutput
64+ ,directDependentNode
65+ ,dependency
66+ ,collect (anotherDirectDependentNode )[0 ] AS firstLinkedDependentNode
67+ LIMIT 140
68+ WITH * , coalesce (dependency .weight25PercentInterfaces , dependency .weight , 1 ) AS weight
69+ // Use a fixed small pen width for secondary dependencies for better visibility of the more important direct dependency
70+ WITH * , "label=" + weight + "; weight=" + weight + "; penwidth=0.3" AS edgeAttributes
71+ // Use a light color for secondary dependency edges
72+ WITH * , edgeAttributes + "; color = 3" AS edgeAttributes
73+ WITH * , "\" " + directDependentNode .name + "\" -> \" " + firstLinkedDependentNode .name + "\" " AS directDependenciesEdge
74+ WITH * , collect (directDependenciesEdge + " [" + edgeAttributes + "]" ) AS directDependenciesEdges
75+ WITH * , graphVizOutput + directDependenciesEdges AS graphVizOutput
76+ UNWIND graphVizOutput AS graphVizOutputLine
77+ RETURN DISTINCT graphVizOutputLine
0 commit comments