Skip to content

Latest commit

 

History

History
527 lines (418 loc) · 14.4 KB

File metadata and controls

527 lines (418 loc) · 14.4 KB

GoGraph Query Reference Guide

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.

Table of Contents

Project Overview Queries

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 500

This 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 DESC

This 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.

Architecture Analysis

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 DESC

This 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, imported

This 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 DESC

Identifies packages with many dependencies, which might indicate high coupling.

Code Complexity Analysis

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 20

Functions 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 20

These 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 20

Functions with many dependencies might be doing too much and could benefit from decomposition.

Dependency Analysis

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 10

Circular 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 10

Deep 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 20

Files with many imports might be doing too much or could benefit from better organization.

Function Analysis

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.name

This 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.name

Unused 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.name

These 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 20

Understand 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 path

These queries help you understand which parts of your codebase depend on a specific function, useful for impact analysis when modifying functions.

Interface Analysis

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 DESC

This 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.name

Helps 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.name

Interfaces without implementations might be dead code or work in progress.

Test Coverage Analysis

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 DESC

This 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.name

Identifies 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.name

Quickly identify packages that lack any test files.

Code Quality Queries

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 DESC

Large 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 20

Large 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 20

Structs with too many methods might have too many responsibilities.

Advanced Analysis

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 DESC

High 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 20

Functions 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 DESC

Understand 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 DESC

Helps understand which types have the most methods defined on them.

Query Writing Tips

Performance Tips

  • Always include WHERE n.project_id = 'your-project-id' to filter by project
  • Use LIMIT to restrict results for better performance
  • Use indexes by querying on indexed properties (name, project_id)

Common Patterns

  • Use OPTIONAL MATCH when relationships might not exist
  • Use collect() to aggregate results
  • Use DISTINCT to remove duplicates
  • Use count() instead of size() for counting pattern matches

Debugging Queries

  • Start with simple queries and build complexity
  • Use RETURN * to see all available data
  • Check relationship directions with -->, <--, or --