This document contains all the Cypher queries you can use to analyze your Go codebase with GoGraph. Each query is organized by category with examples and explanations.
- Project Overview Queries
- Architecture Analysis
- Code Complexity Analysis
- Dependency Analysis
- Function Analysis
- Interface Analysis
- Test Coverage Analysis
- Code Quality Queries
- Advanced Analysis
View Entire Project Structure
// View the entire project structure (limit to 500 nodes for performance)
MATCH (n)
WHERE n.project_id = 'my-awesome-project'
RETURN n
LIMIT 500This query returns all nodes in your project, giving you a complete overview of your codebase structure in the Neo4j browser.
Count Nodes by Type
// Get a summary of all node types in your project
MATCH (n)
WHERE n.project_id = 'my-awesome-project'
RETURN labels(n)[0] as NodeType, count(n) as Count
ORDER BY Count DESCThis helps you understand the composition of your codebase - how many packages, files, functions, structs, etc.
Show Database Labels and Relationships
// Show all available node labels
CALL db.labels()
// Show all available relationship types
CALL db.relationshipTypes()These queries help you understand what types of nodes and relationships are available in the database.
Package Overview
// View all packages and their file counts
MATCH (p:Package)-[:CONTAINS]->(f:File)
WHERE p.project_id = 'my-awesome-project'
RETURN p.name as package, count(f) as files
ORDER BY files DESCThis query shows you the size of each package in terms of number of files, helping identify large packages that might need refactoring.
Package Dependencies
// Visualize what each package imports
MATCH (p1:Package)-[:CONTAINS]->(f:File)-[:IMPORTS]->(i:Import)
WHERE p1.project_id = 'my-awesome-project'
RETURN DISTINCT p1.name as importer, i.name as imported
ORDER BY importer, importedThis shows the import relationships between packages, helping you understand your project's dependency structure.
Package Import Statistics
// Count imports per package
MATCH (p:Package)-[:CONTAINS]->(f:File)-[:IMPORTS]->(i:Import)
WHERE p.project_id = 'my-awesome-project'
RETURN p.name as package, count(DISTINCT i.name) as import_count
ORDER BY import_count DESCIdentifies packages with many dependencies, which might indicate high coupling.
Function Complexity Hotspots
// Find the most connected functions (potential complexity hotspots)
MATCH (f:Function)
WHERE f.project_id = 'my-awesome-project'
OPTIONAL MATCH (f)-[:CALLS]->(called)
WITH f, count(called) as outgoing_calls
OPTIONAL MATCH (f)<-[:CALLS]-(caller)
RETURN f.name, f.package, outgoing_calls, count(caller) as incoming_calls,
(outgoing_calls + count(caller)) as total_connections
ORDER BY total_connections DESC
LIMIT 20Functions with many connections (both calling and being called) are often complexity hotspots that might benefit from refactoring.
Most Called Functions
// Find the most frequently called functions
MATCH (f:Function)<-[:CALLS]-(caller)
WHERE f.project_id = 'my-awesome-project'
RETURN f.name, f.package, count(caller) as call_count
ORDER BY call_count DESC
LIMIT 20These are your most reused functions - changes to them can have wide-reaching effects.
Functions with Most Dependencies
// Find functions that call many other functions
MATCH (f:Function)-[:CALLS]->(called)
WHERE f.project_id = 'my-awesome-project'
RETURN f.name, f.package, count(called) as dependencies
ORDER BY dependencies DESC
LIMIT 20Functions with many dependencies might be doing too much and could benefit from decomposition.
Circular Dependencies Detection
// Find circular dependencies at function level
MATCH path = (f:Function)-[:CALLS*2..]->(f)
WHERE f.project_id = 'my-awesome-project'
RETURN path
LIMIT 10Circular dependencies can make code hard to understand and maintain. This query helps identify them.
Deep Call Chains
// Find deep call chains (more than 5 levels)
MATCH path = (f1:Function)-[:CALLS*5..]->(f2:Function)
WHERE f1.project_id = 'my-awesome-project'
AND f2.project_id = 'my-awesome-project'
RETURN path
LIMIT 10Deep call chains can indicate complex control flow that might be simplified.
Import Analysis by File
// Show which files import the most packages
MATCH (f:File)-[:IMPORTS]->(i:Import)
WHERE f.project_id = 'my-awesome-project'
RETURN f.path, count(i) as import_count
ORDER BY import_count DESC
LIMIT 20Files with many imports might be doing too much or could benefit from better organization.
Find All Functions in a Package
// List all functions in a specific package
MATCH (p:Package {name: "main"})-[:CONTAINS]->(f:File)-[:DEFINES]->(fn:Function)
WHERE p.project_id = 'my-awesome-project'
RETURN fn.name, fn.signature, f.name as file
ORDER BY fn.nameThis helps you explore what functions are available in a specific package.
Unused Functions
// Find functions that are never called (except main)
MATCH (f:Function)
WHERE f.project_id = 'my-awesome-project'
AND NOT (f)<-[:CALLS]-()
AND NOT f.name = 'main'
RETURN f.name, f.package, f.file_path
ORDER BY f.package, f.nameUnused functions might be dead code that can be removed to simplify the codebase.
Entry Points
// Find all entry points (functions not called by any other function)
MATCH (f:Function)
WHERE f.project_id = 'my-awesome-project'
AND NOT (f)<-[:CALLS]-()
AND f.is_exported = true
RETURN f.name, f.package, f.signature
ORDER BY f.package, f.nameThese are typically main functions, API handlers, or exported library functions.
Function Call Chains
// Trace call chain from a specific function
MATCH path = (f:Function {name: "HandleRequest"})-[:CALLS*1..5]->(target)
WHERE f.project_id = 'my-awesome-project'
RETURN path
LIMIT 20Understand how a specific function interacts with the rest of your codebase.
Reverse Call Chains (Find Callers)
// Find all functions that call a specific function
MATCH path = (caller:Function)-[:CALLS*1..3]->(f:Function {name: "SaveUser"})
WHERE f.project_id = 'my-awesome-project'
RETURN path
LIMIT 20
// Direct callers only
MATCH (caller:Function)-[:CALLS]->(f:Function {name: "SaveUser"})
WHERE f.project_id = 'my-awesome-project'
RETURN caller.name, caller.package, caller.file_path
ORDER BY caller.package, caller.name
// Find call paths between two specific functions (reverse)
MATCH path = (end:Function {name: "main"})<-[:CALLS*1..5]-(start:Function {name: "ProcessRequest"})
WHERE start.project_id = 'my-awesome-project'
RETURN pathThese queries help you understand which parts of your codebase depend on a specific function, useful for impact analysis when modifying functions.
Interface Implementations
// Find all interface implementations
MATCH (s:Struct)-[:IMPLEMENTS]->(i:Interface)
WHERE s.project_id = 'my-awesome-project'
RETURN i.name as Interface,
collect(s.name) as Implementations,
count(s) as ImplementationCount
ORDER BY ImplementationCount DESCThis shows which interfaces are most widely implemented, indicating key abstractions in your design.
Interfaces by Package
// List interfaces grouped by package
MATCH (p:Package)-[:CONTAINS]->(f:File)-[:DEFINES]->(i:Interface)
WHERE p.project_id = 'my-awesome-project'
RETURN p.name as package, collect(i.name) as interfaces
ORDER BY p.nameHelps understand how interfaces are distributed across your packages.
Unimplemented Interfaces
// Find interfaces with no implementations
MATCH (i:Interface)
WHERE i.project_id = 'my-awesome-project'
AND NOT (i)<-[:IMPLEMENTS]-()
RETURN i.name, i.package
ORDER BY i.package, i.nameInterfaces without implementations might be dead code or work in progress.
Test Coverage by Package
// Analyze test file ratio by package
MATCH (p:Package)
WHERE p.project_id = 'my-awesome-project'
OPTIONAL MATCH (p)-[:CONTAINS]->(f:File)
WHERE f.name ENDS WITH '_test.go'
WITH p, count(f) as test_files
OPTIONAL MATCH (p)-[:CONTAINS]->(f2:File)
WHERE NOT f2.name ENDS WITH '_test.go'
RETURN p.name, count(f2) as source_files, test_files,
CASE WHEN count(f2) > 0
THEN round(100.0 * test_files / count(f2), 2)
ELSE 0 END as test_ratio
ORDER BY test_ratio DESCThis query helps identify packages with low test coverage.
Functions with Tests
// Find functions that have corresponding test functions
MATCH (f:Function)<-[:CALLS]-(test:Function)
WHERE f.project_id = 'my-awesome-project'
AND test.name STARTS WITH 'Test'
RETURN f.name, f.package, collect(test.name) as test_functions
ORDER BY f.package, f.nameIdentifies which functions have direct test coverage.
Packages Without Tests
// Find packages with no test files
MATCH (p:Package)
WHERE p.project_id = 'my-awesome-project'
AND NOT EXISTS {
MATCH (p)-[:CONTAINS]->(f:File)
WHERE f.name ENDS WITH '_test.go'
}
RETURN p.name
ORDER BY p.nameQuickly identify packages that lack any test files.
Large Files
// Find files with many lines of code
MATCH (f:File)
WHERE f.project_id = 'my-awesome-project'
AND f.lines > 500
RETURN f.path, f.lines
ORDER BY f.lines DESCLarge files might benefit from being split into smaller, more focused files.
Large Functions
// Find functions with many lines
MATCH (f:Function)
WHERE f.project_id = 'my-awesome-project'
AND (f.line_end - f.line_start) > 50
RETURN f.name, f.package, (f.line_end - f.line_start) as lines
ORDER BY lines DESC
LIMIT 20Large functions are often hard to understand and test.
God Objects
// Find structs with many methods (potential god objects)
MATCH (s:Struct)-[:HAS_METHOD]->(m:Method)
WHERE s.project_id = 'my-awesome-project'
RETURN s.name, s.package, count(m) as method_count
ORDER BY method_count DESC
LIMIT 20Structs with too many methods might have too many responsibilities.
Package Coupling Analysis
// Analyze coupling between packages
MATCH (p1:Package)-[:CONTAINS]->(f1:File)-[:IMPORTS]->(i:Import),
(p2:Package)-[:CONTAINS]->(f2:File)
WHERE p1.project_id = 'my-awesome-project'
AND p2.project_id = 'my-awesome-project'
AND f2.path = i.name
AND p1.name <> p2.name
RETURN p1.name as from_package, p2.name as to_package, count(*) as import_count
ORDER BY import_count DESCHigh coupling between packages might indicate they should be merged or better separated.
Find Similar Functions
// Find functions with similar names (potential duplicates)
MATCH (f1:Function), (f2:Function)
WHERE f1.project_id = 'my-awesome-project'
AND f2.project_id = 'my-awesome-project'
AND f1.name CONTAINS f2.name
AND f1 <> f2
AND length(f1.name) > 5
RETURN f1.name, f1.package, f2.name, f2.package
ORDER BY f1.name
LIMIT 20Functions with similar names might be duplicates or could be consolidated.
External Dependency Analysis
// Find all external (non-stdlib) imports
MATCH (f:File)-[:IMPORTS]->(i:Import)
WHERE f.project_id = 'my-awesome-project'
AND NOT i.name STARTS WITH 'github.com/compozy/gograph'
AND i.name CONTAINS '.'
AND NOT i.name IN ['fmt', 'os', 'io', 'strings', 'errors', 'context', 'time', 'encoding/json']
RETURN DISTINCT i.name as external_import, count(f) as usage_count
ORDER BY usage_count DESCUnderstand your project's external dependencies and how widely they're used.
Method Receiver Analysis
// Analyze method receivers by type
MATCH (m:Method)
WHERE m.project_id = 'my-awesome-project'
RETURN m.receiver_type as receiver, count(m) as method_count
ORDER BY method_count DESCHelps understand which types have the most methods defined on them.
- Always include
WHERE n.project_id = 'your-project-id'to filter by project - Use
LIMITto restrict results for better performance - Use indexes by querying on indexed properties (name, project_id)
- Use
OPTIONAL MATCHwhen relationships might not exist - Use
collect()to aggregate results - Use
DISTINCTto remove duplicates - Use
count()instead ofsize()for counting pattern matches
- Start with simple queries and build complexity
- Use
RETURN *to see all available data - Check relationship directions with
-->,<--, or--