### Gopher Cypher CLI Tools Installation and Usage Source: https://github.com/seuros/gopher-cypher/blob/master/README.md Provides instructions for installing and using the Gopher Cypher command-line interface (CLI) tools. It covers installation via `go install`, and demonstrates common commands for linting, formatting, inspecting query Abstract Syntax Trees (AST), and starting the Language Server Protocol (LSP) for IDE integration. ```bash # Install CLI tools go install github.com/seuros/gopher-cypher/cmd/cyq@latest # Validate and format queries cyq lint queries/*.cypher cyq fmt src/queries/user-management.cypher # Explore AST structure cyq inspect complex-query.cypher # Start Language Server for IDE integration cyq lsp ``` -------------------------------- ### Install Cypher Binary Source: https://github.com/seuros/gopher-cypher/blob/master/BUILD.md This snippet shows the command to install the built cypher binary. 'make install' places the executable in the $GOPATH/bin directory, making it accessible from the command line. ```bash make install # Installs cyq with proper version to $GOPATH/bin ``` -------------------------------- ### Compile a Simple RETURN Literal Expression in Go Source: https://github.com/seuros/gopher-cypher/blob/master/docs/parser_ast_examples.md Demonstrates how to construct a simple Cypher AST for `RETURN "Hello, AST!"` and compile it into a query string and parameters using the `gopher-cypher` compiler. This example shows the creation of `LiteralNode` and `ReturnNode` and their subsequent compilation. ```go package main import ( "fmt" "log" "github.com/seuros/gopher-cypher/src/cypher" // Assuming this is the correct import path ) func main() { // 1. Create a LiteralNode for the string literal := &cypher.LiteralNode{Value: "Hello, AST!"} // 2. Create a ReturnNode // The Items field expects a slice of interfaces. // If ReturnNode expects specific types or Expression, this might need adjustment. // Based on compiler.go, renderExpression handles various types, including LiteralNode. returnClause := &cypher.ReturnNode{ Items: []interface{}{literal}, } // 3. Compile the AST compiler := cypher.NewCompiler() // The Compile method takes a variadic Node argument queryString, params := compiler.Compile(returnClause) fmt.Println("Generated Cypher Query:") fmt.Println(queryString) fmt.Println("Parameters:") for k, v := range params { fmt.Printf("%s: %v\n", k, v) } // Expected Output: // Generated Cypher Query: // RETURN $p1 // Parameters: // p1: Hello, AST! } ``` -------------------------------- ### Installing Gopher Cypher CLI Tool (cyq) in Go Source: https://github.com/seuros/gopher-cypher/blob/master/README.md Details the command to install the `cyq` command-line interface tool for Gopher Cypher. This tool likely aids in interacting with or managing Cypher databases. ```bash go install github.com/seuros/gopher-cypher/cmd/cyq@latest ``` -------------------------------- ### Docker Compose for Gopher Cypher Development Source: https://github.com/seuros/gopher-cypher/blob/master/README.md Outlines the steps to set up a development environment using Docker Compose for Gopher Cypher. This includes cloning the repository, starting the database, and running the test suite. ```bash git clone https://github.com/seuros/gopher-cypher cd gopher-cypher docker-compose up -d # Start graph database make test # Run full test suite ``` -------------------------------- ### Bash: Format and Normalize Cypher Queries with cyq fmt Source: https://context7.com/seuros/gopher-cypher/llms.txt Demonstrates the usage of the 'cyq fmt' command-line tool for formatting Cypher queries. Examples include printing formatted output to stdout, saving formatted queries back to files, and integrating 'cyq fmt' as a pre-commit hook. ```bash # Format query and print to stdout cyq fmt queries/complex-query.cypher # Output: # MATCH (u:User) # WHERE u.age > $minAge # RETURN u.name, u.email # LIMIT $maxResults # Format and save back to file (shell script) cyq fmt queries/unformatted.cypher > /tmp/formatted.cypher mv /tmp/formatted.cypher queries/unformatted.cypher # Pre-commit hook integration # .git/hooks/pre-commit #!/bin/bash # for file in $(git diff --cached --name-only | grep ".cypher$"); do # cyq fmt "$file" > "$file.formatted" # mv "$file.formatted" "$file" # git add "$file" # done ``` -------------------------------- ### Construct Cypher AST with MATCH, WHERE, RETURN in Go Source: https://github.com/seuros/gopher-cypher/blob/master/docs/parser_ast_examples.md This Go snippet illustrates the programmatic construction of a Cypher Abstract Syntax Tree (AST) for a query involving MATCH, WHERE, and RETURN clauses. It outlines the conceptual structures like PatternNode, MatchNode, WhereNode, and ReturnNode, and shows how they are compiled into a Cypher query string and parameters. Note that the specific struct names and methods used are speculative and depend on the actual implementation within the `github.com/seuros/gopher-cypher/src/cypher` package. ```go package main import ( "fmt" "log" "github.com/seuros/gopher-cypher/src/cypher" // Assuming this is the correct import path ) func main() { // It's highly likely that specific structs exist for patterns, expressions, etc. // This is a conceptual example. The actual node construction will depend // on the precise definitions in the src/cypher/ package. // Representing the pattern (n:Person) // This is speculative. The actual API for creating patterns might be different. // For instance, there might be functions like cypher.NodePattern("n", "Person", nil) pattern := cypher.PatternNode{ // Assuming PatternNode exists Path: []cypher.PathElement{ // PathElement is also an assumption { Node: &cypher.NodePattern{ // NodePattern is an assumption Variable: "n", Labels: []string{"Person"}, }, }, }, } // 1. MatchNode matchClause := &cypher.MatchNode{ Pattern: pattern, // Or however patterns are supplied } // 2. WhereNode // Representing n.name = "CHAD" // This likely involves an Expression type. // Example: cypher.Equals(cypher.Property("n", "name"), cypher.Literal("CHAD")) // For simplicity, we'll use a placeholder string, though in reality, // this would be a structured Expression. whereCondition := cypher.Expression{ // Placeholder, this would be a structured expression // This is a simplified representation. // Actual implementation would use specific expression types. Representation: "n.name = $param1", // Example, actual structure needed } // The compiler handles parameter registration. Let's assume "CHAD" would be registered. // To make this runnable, we'd need to ensure "CHAD" is passed in a way the // compiler can create a parameter for it, or use a LiteralNode if appropriate. // For the purpose of this example, let's assume the Expression handles it. whereClause := &cypher.WhereNode{ Conditions: []cypher.Expression{whereCondition}, } // 3. ReturnNode // Representing n.age // Example: cypher.Property("n", "age") returnItem := cypher.Expression{ // Placeholder Representation: "n.age", } returnClause := &cypher.ReturnNode{ Items: []interface{}{returnItem}, } // 4. Compile the AST compiler := cypher.NewCompiler() queryString, params := compiler.Compile(matchClause, whereClause, returnClause) // Pass nodes in order fmt.Println("Generated Cypher Query:") fmt.Println(queryString) fmt.Println("Parameters:") // In a real scenario, "CHAD" would be in params if `whereCondition` was a proper LiteralNode // or if the Expression system registered it. // For this conceptual example, params might be empty or contain what the // simplified Expression placeholder implied. Let's assume "CHAD" became p1. // To make this fully work, `literalCHAD := &cypher.LiteralNode{Value: "CHAD"}` // would be used in the expression for `n.name = $p1` // and params would then contain `p1: "CHAD"`. // A more realistic parameter setup if LiteralNode was used for "CHAD": // params["param1"] = "CHAD" // Or whatever key the compiler generates fmt.Println("--- Conceptual Output ---") fmt.Println("MATCH (n:Person)") fmt.Println("WHERE n.name = $p1") // Assuming "CHAD" is parameterized fmt.Println("RETURN n.age") fmt.Println("Parameters: {p1: \"CHAD\"}") // Ideal parameters // Actual output will depend heavily on how PatternNode and Expression are truly implemented // and how they interact with the compiler for parameterization. } ``` -------------------------------- ### Installing Gopher Cypher Driver in Go Source: https://github.com/seuros/gopher-cypher/blob/master/README.md Provides the command to install the Gopher Cypher driver library using Go modules. This is the primary step for integrating the library into a Go project. ```bash go get github.com/seuros/gopher-cypher ``` -------------------------------- ### Initialize and Use ConsoleLogger in Go Source: https://context7.com/seuros/gopher-cypher/llms.txt Demonstrates initializing the ConsoleLogger with a specific log level and timestamp format. It then integrates this logger with the Gopher Cypher driver's configuration to enable detailed logging for driver operations and query execution. The example shows how to set up the driver and execute a query, with the ConsoleLogger outputting detailed information about each step. ```go package main import ( "context" "log" "time" "github.com/seuros/gopher-cypher/src/driver" ) func main() { // Create console logger with DEBUG level consoleLogger := driver.NewConsoleLogger(driver.LogLevelDebug) consoleLogger.SetTimeFormat("2006-01-02 15:04:05.000") config := &driver.Config{ Logging: &driver.LoggingConfig{ Logger: consoleLogger, LogQueryTiming: true, LogConnectionPool: true, LogBoltMessages: true, LogAuthEvents: true, LogTLSEvents: true, LogStreamingEvents: true, }, } dr, err := driver.NewDriverWithConfig( "bolt://neo4j:password@localhost:7687", config, ) if err != nil { log.Fatal(err) } defer dr.Close() ctx := context.Background() // Execute query with full logging _, _, summary, err := dr.RunWithContext( ctx, "MATCH (u:User) WHERE u.created > $since RETURN u.name, u.email LIMIT $limit", map[string]interface{}{ "since": time.Now().Add(-24 * time.Hour).Unix(), "limit": 50, }, nil, ) if err != nil { log.Fatal(err) } // Console output: // [2024-12-12 14:30:15.123] INFO [gopher-cypher] Initializing gopher-cypher driver | url=bolt://localhost:7687 // [2024-12-12 14:30:15.124] DEBUG [gopher-cypher] Connection URL resolved | host=localhost port=7687 ssl=false database= // [2024-12-12 14:30:15.125] DEBUG [gopher-cypher] Connection pool created successfully // [2024-12-12 14:30:15.126] DEBUG [gopher-cypher] Checking Bolt protocol version // [2024-12-12 14:30:15.127] DEBUG [gopher-cypher] Bolt version check successful // [2024-12-12 14:30:15.128] DEBUG [gopher-cypher] Authenticating with server // [2024-12-12 14:30:15.130] DEBUG [gopher-cypher] Authentication successful // [2024-12-12 14:30:15.131] INFO [gopher-cypher] Executing query | query=MATCH (u:User) WHERE... param_count=2 // [2024-12-12 14:30:15.145] INFO [gopher-cypher] Query completed | duration=14ms records=42 query_type=read log.Printf("Retrieved %d users in %v", summary.RecordsConsumed, summary.ExecutionTime) } ``` -------------------------------- ### Bash: Explore Cypher AST Structure with cyq inspect Source: https://context7.com/seuros/gopher-cypher/llms.txt Illustrates how to use the 'cyq inspect' command-line tool to explore the Abstract Syntax Tree (AST) of Cypher queries. Examples show inspecting a file, piping query strings to the tool, and understanding the parsed structure of complex expressions. ```bash # Inspect query structure cyq inspect queries/pagination.cypher # Output: # Query structure for queries/pagination.cypher: # Generated Cypher: MATCH (p:Product) # WHERE p.category = $category # RETURN p.name, p.price # SKIP $offset # LIMIT $pageSize # Parameters: map[category:p1 offset:p2 pageSize:p3] # Debug complex expressions echo 'MATCH (p) RETURN p.price * 1.2 AS total LIMIT 10' | cyq inspect /dev/stdin # Shows how math expressions are parsed into AST nodes ``` -------------------------------- ### Go: Setup OpenTelemetry Tracing for Gopher Cypher Driver Source: https://context7.com/seuros/gopher-cypher/llms.txt Initializes OpenTelemetry tracing using stdout exporter and configures the Gopher Cypher driver to enable tracing and metrics. This setup allows for detailed observability of database operations, including custom attributes and result metrics. ```go package main import ( "context" "log" "github.com/seuros/gopher-cypher/src/driver" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" "go.opentelemetry.io/otel/sdk/trace" ) func main() { // Initialize OpenTelemetry tracing exporter, err := stdouttrace.New(stdouttrace.WithPrettyPrint()) if err != nil { log.Fatal(err) } tp := trace.NewTracerProvider( trace.WithBatcher(exporter), ) otel.SetTracerProvider(tp) defer tp.Shutdown(context.Background()) // Configure driver with observability config := &driver.Config{ Observability: &driver.ObservabilityConfig{ EnableTracing: true, EnableMetrics: true, TracingAttributes: []attribute.KeyValue{ attribute.String("service.name", "user-service"), attribute.String("service.version", "1.0.0"), attribute.String("environment", "production"), }, }, Logging: &driver.LoggingConfig{ Logger: driver.NewConsoleLogger(driver.LogLevelInfo), LogQueryTiming: true, }, } dr, err := driver.NewDriverWithConfig( "bolt://neo4j:password@localhost:7687", config, ) if err != nil { log.Fatal(err) } defer dr.Close() // Create application-level span ctx := context.Background() tracer := otel.Tracer("user-service") ctx, span := tracer.Start(ctx, "getUserFriends") defer span.End() // Add custom attributes span.SetAttributes( attribute.String("user.id", "user-123"), attribute.String("query.type", "friends"), ) // Query automatically creates child span _, _, summary, err := dr.RunWithContext( ctx, "MATCH (u:User {id: $userId})-[:FRIEND]->(f:User) RETURN f.name, f.age", map[string]interface{}{"userId": "user-123"}, nil, ) if err != nil { span.RecordError(err) log.Fatal(err) } // Add result metrics to span span.SetAttributes( attribute.Int64("result.records", summary.RecordsConsumed), attribute.String("result.duration", summary.ExecutionTime.String()), ) log.Printf("Query traced: %d records in %v", summary.RecordsConsumed, summary.ExecutionTime) // Trace output includes: // - Parent span: getUserFriends // - Child span: cypher.query (auto-created by driver) // - Attributes: query text, parameters, database, server // - Events: connection acquire, authentication, query execute // - Metrics: duration, record count, network calls } ``` -------------------------------- ### Go: TLS Modes for Neo4j Driver Configuration Source: https://context7.com/seuros/gopher-cypher/llms.txt Demonstrates various TLS configurations for the Neo4j driver in Go, including verified SSL, self-signed certificates, and custom mutual TLS setups. It shows how to load certificates and configure the TLS settings for secure connections. ```go package main import ( "crypto/tls" "crypto/x509" "log" "os" "github.com/seuros/gopher-cypher/src/driver" ) func main() { // Example 1: Production with verified SSL (bolt+ssl://) dr1, err := driver.NewDriver("bolt+ssl://neo4j:password@graphdb.example.com:7687") if err != nil { log.Fatal(err) } defer dr1.Close() // Example 2: Development with self-signed certificates (bolt+ssc://) dr2, err := driver.NewDriver("bolt+ssc://neo4j:password@localhost:7687") if err != nil { log.Fatal(err) } defer dr2.Close() // Example 3: Custom TLS with client certificates (mutual TLS) clientCert, err := tls.LoadX509KeyPair("client-cert.pem", "client-key.pem") if err != nil { log.Fatalf("Failed to load client certificate: %v", err) } // Load custom CA certificate caCert, err := os.ReadFile("ca-cert.pem") if err != nil { log.Fatalf("Failed to read CA certificate: %v", err) } caCertPool := x509.NewCertPool() if !caCertPool.AppendCertsFromPEM(caCert) { log.Fatal("Failed to parse CA certificate") } config3 := &driver.Config{ TLS: &driver.TLSConfig{ Config: &tls.Config{ Certificates: []tls.Certificate{clientCert}, RootCAs: caCertPool, ServerName: "graph.internal.example.com", MinVersion: tls.VersionTLS13, InsecureSkipVerify: false, }, }, } dr3, err := driver.NewDriverWithConfig( "bolt://neo4j:password@graph.internal.example.com:7687", config3, ) if err != nil { log.Fatal(err) } defer dr3.Close() // Example 4: Custom TLS from files helper tlsConfig, err := driver.NewTLSConfigFromCertFiles( "client-cert.pem", "client-key.pem", "ca-cert.pem", ) if err != nil { log.Fatal(err) } config4 := &driver.Config{ TLS: tlsConfig, } dr4, err := driver.NewDriverWithConfig( "bolt+ssl://neo4j:password@secure.example.com:7687", config4, ) if err != nil { log.Fatal(err) } defer dr4.Close() log.Println("All TLS configurations successful") } ``` -------------------------------- ### Execute Reactive Queries with Gopher Cypher (Go) Source: https://context7.com/seuros/gopher-cypher/llms.txt Demonstrates how to execute reactive queries using Gopher Cypher's ReactiveDriver. It includes setting up the driver, running a query, and building a reactive processing pipeline with operators like Filter, Transform, DoOnNext, Batch, and OnError. The example also shows how to subscribe to the stream with a custom subscriber to process batches of enriched data and handle stream completion or errors. ```go package main import ( "context" "fmt" "log" "time" "github.com/seuros/gopher-cypher/src/driver" ) func main() { dr, _ := driver.NewDriver("bolt://neo4j:password@localhost:7687") defer dr.Close() reactiveDriver := dr.(driver.ReactiveDriver) ctx := context.Background() // Execute reactive query reactive, err := reactiveDriver.RunReactive( ctx, "MATCH (t:Transaction) WHERE t.timestamp > $since RETURN t.id, t.amount, t.userId, t.timestamp, t.location", map[string]interface{}{"since": time.Now().Add(-24 * time.Hour).Unix()}, nil, ) if err != nil { log.Fatal(err) } // Build reactive pipeline with composable operators pipeline := reactive. // Filter high-value transactions Filter(func(record *driver.Record) bool { amount := (*record)("amount").(float64) return amount > 10000.0 }). // Transform and enrich data Transform(func(record *driver.Record) *driver.Record { userId := (*record)("userId").(string) // Simulate external API call for user data userData := fetchUserProfile(userId) enriched := driver.Record{ "transaction_id": (*record)("id"), "amount": (*record)("amount"), "userId": userId, "timestamp": (*record)("timestamp"), "location": (*record)("location"), "user_name": userData.Name, "user_tier": userData.Tier, "risk_score": userData.RiskScore, } return &enriched }). // Filter suspicious patterns Filter(func(record *driver.Record) bool { riskScore := (*record)("risk_score").(int) return riskScore > 70 }). // Side effect: Real-time alerting DoOnNext(func(record *driver.Record) { fmt.Printf("ALERT: High-risk transaction %v for user %s (risk: %d)\n", (*record)("transaction_id"), (*record)("user_name"), (*record)("risk_score")) sendAlertToSecurityTeam(record) }). // Batch for efficient processing Batch(50). // Error recovery OnError(func(err error) error { log.Printf("Stream error (continuing): %v", err) return nil // Return nil to continue processing }) // Subscribe with custom subscriber err = pipeline.Subscribe(ctx, &driver.FuncSubscriber{ OnNextFunc: func(record *driver.Record) { batch := (*record)("batch").([]*driver.Record) fmt.Printf("Processing batch of %d suspicious transactions\n", len(batch)) // Bulk database update, message queue publish, etc. for _, txn := range batch { updateFraudDatabase(txn) } }, OnCompleteFunc: func(summary *driver.ResultSummary) { fmt.Printf("Reactive processing completed: %d records in %v\n", summary.RecordsConsumed, summary.ExecutionTime) }, OnErrorFunc: func(err error) { log.Printf("Fatal stream error: %v", err) }, }) if err != nil { log.Fatal(err) } // Continue with other work while stream processes in background... fmt.Println("Reactive stream running in background") } type UserProfile struct { Name string Tier string RiskScore int } func fetchUserProfile(userId string) UserProfile { // Simulate external API call return UserProfile{Name: "John Doe", Tier: "Premium", RiskScore: 85} } func sendAlertToSecurityTeam(record *driver.Record) { // Send alert via email, Slack, PagerDuty, etc. } func updateFraudDatabase(record *driver.Record) { // Bulk update fraud detection database } ``` -------------------------------- ### Data Pipeline Processing with Reactive Streams in Go Source: https://github.com/seuros/gopher-cypher/blob/master/README.md Details a reactive stream pipeline for data processing. This example includes validation, normalization, batching, error handling with retries, and completion notifications, suitable for ETL tasks. ```go pipeline := reactive. Filter(validateData). Transform(cleanAndNormalize). Batch(1000). DoOnNext(bulkProcessBatch). OnError(retryWithBackoff). DoOnComplete(notifyCompletion) ``` -------------------------------- ### High-Performance Analytics Stream Processing in Go Source: https://github.com/seuros/gopher-cypher/blob/master/README.md Presents a reactive stream setup for high-performance analytics. It utilizes time-based batching, data transformation for aggregate computation, and direct output to dashboards and message queues. ```go analytics := reactive. BatchByTime(5 * time.Second). Transform(computeAggregates). DoOnNext(updateDashboard). DoOnNext(publishToKafka) ``` -------------------------------- ### TLS Modes and Custom Configuration in Go Source: https://github.com/seuros/gopher-cypher/blob/master/README.md Details the support for various TLS modes in the Gopher Cypher driver, including production-ready certificate verification, development-friendly self-signed certificate usage, and custom TLS configurations. It shows how to instantiate the driver with different security protocols and provides an example of a custom TLS configuration. ```go // Production with certificate verification driver.NewDriver("bolt+ssl://user:pass@graphdb.example.com:7687") // Development with self-signed certificates driver.NewDriver("bolt+ssc://user:pass@localhost:7687") // Custom TLS configuration config := &driver.Config{ TLS: &driver.TLSConfig{ Mode: driver.TLSModeCustom, Config: &tls.Config{ ServerName: "my-graph-server", RootCAs: customCertPool, }, }, } ``` -------------------------------- ### Perform Standard Build Source: https://github.com/seuros/gopher-cypher/blob/master/BUILD.md This snippet demonstrates the standard build process for the gopher-cypher project, which includes injecting the version number into the binary. The 'make build' command creates the 'cyq' executable, and './cyq version' verifies the injected version. ```bash make build # Builds cyq binary with proper version ./cyq version # Shows: cyq version 0.2.0 ``` -------------------------------- ### Define Cypher AST Node Interface in Go Source: https://github.com/seuros/gopher-cypher/blob/master/docs/parser_ast_examples.md Defines the base `Node` interface for Cypher AST elements and the `Visitor` interface used in the visitor pattern for AST traversal. This is fundamental for building and processing Cypher queries programmatically. ```go package cypher // Node represents a single AST element. It participates in the visitor // pattern used by the compilers. type Node interface { // Accept allows a visitor to process the node. Accept(v Visitor) error } // Visitor is implemented by types that can handle specific AST nodes. type Visitor interface{} "" ``` -------------------------------- ### Reactive Backpressure Configuration in Go Source: https://github.com/seuros/gopher-cypher/blob/master/README.md Demonstrates how to configure reactive streams with backpressure handling to prevent memory issues. This snippet shows setting buffer size, backpressure strategy, and maximum concurrency, along with applying rate limiting. ```go // Automatic backpressure handling prevents memory issues config := &driver.ReactiveConfig{ BufferSize: 1000, BackpressureStrategy: driver.BackpressureBuffer, MaxConcurrency: 10, } reactive := driver.NewReactiveResult(source, query, params, config) throttled := reactive.Throttle(100 * time.Millisecond) // Rate limiting // Never overwhelms slow consumers throttled.Subscribe(ctx, slowSubscriber) ``` -------------------------------- ### Reactive Graph Database Queries with Go Source: https://github.com/seuros/gopher-cypher/blob/master/README.md Demonstrates how to perform reactive graph database queries using the Go driver. It includes building a processing pipeline with filtering, transformation, batching, error handling, and side effects, culminating in a non-blocking subscription to process results. External API calls and external functions are assumed to exist. ```go // Reactive graph database queries reactiveDriver := dr.(driver.ReactiveDriver) reactive, err := reactiveDriver.RunReactive(ctx, "MATCH (t:Transaction) RETURN t.amount, t.userId, t.timestamp", nil, nil) if err != nil { log.Fatal(err) } // Build reactive processing pipeline pipeline := reactive. // Filter high-value transactions Filter(func(record *driver.Record) bool { amount := (*record)["amount"].(float64) return amount > 10000.0 }). // Transform and enrich data Transform(func(record *driver.Record) *driver.Record { userId := (*record)["userId"].(string) userData := fetchUserData(userId) // External API call enriched := driver.Record{ "amount": (*record)["amount"], "userId": userId, "timestamp": (*record)["timestamp"], "userTier": userData.Tier, "riskScore": userData.RiskScore, } return &enriched }). // Batch for efficient processing Batch(100). // Handle errors gracefully OnError(func(err error) error { log.Printf("Stream error: %v", err) return nil // Continue processing }). // Side effects without modifying stream DoOnNext(func(record *driver.Record) { // Real-time alerting if shouldAlert(*record) { sendFraudAlert(*record) } }) // Non-blocking subscription pipeline.Subscribe(ctx, &driver.FuncSubscriber{ OnNextFunc: func(record *driver.Record) { batch := (*record)["batch"].([]*driver.Record) processBatch(batch) // Bulk operations }, OnCompleteFunc: func(summary *driver.ResultSummary) { log.Printf("Reactive processing completed: %d records", summary.RecordsConsumed) }, }) // Continue with other work while stream processes in background... ``` -------------------------------- ### Get Single Record with Validation - Go Source: https://context7.com/seuros/gopher-cypher/llms.txt Illustrates the use of the 'Single' method to retrieve exactly one record from a query result, with built-in validation. This method returns an error if zero or more than one record is found, ensuring data integrity. It requires a context and handles potential errors during retrieval. ```go package main import ( "context" "fmt" "log" "github.com/seuros/gopher-cypher/src/driver" ) func main() { dr, _ := driver.NewDriver("bolt://neo4j:password@localhost:7687") defer dr.Close() streamingDriver := dr.(driver.StreamingDriver) ctx := context.Background() // Example 2: Get single record with validation result2, _ := streamingDriver.RunStream( ctx, "MATCH (u:User) WHERE u.email = $email RETURN u.id, u.name, u.role", map[string]interface{}{"email": "admin@example.com"}, nil, ) user, err := result2.Single(ctx) if err != nil { log.Fatalf("Expected exactly one user: %v", err) // Error if 0 or >1 records: "Result contains no records" or "Result contains more than one record" } fmt.Printf("User: %s (ID: %v, Role: %s)\n", (*user)["name"], (*user)["id"], (*user)["role"]) // Output: User: Admin User (ID: 1, Role: administrator) } ``` -------------------------------- ### Manage Project Version Source: https://github.com/seuros/gopher-cypher/blob/master/BUILD.md This snippet shows how to view and update the project's version using the VERSION file. It's a simple text-based approach for managing release versions. ```bash cat VERSION # Show current version echo "0.3.0" > VERSION # Update version ``` -------------------------------- ### Perform Development Build Source: https://github.com/seuros/gopher-cypher/blob/master/BUILD.md This snippet illustrates how to perform a development build using 'go run'. This method typically results in the version being reported as 'dev', differentiating it from production builds. ```bash go run cmd/cyq/main.go version # Shows: cyq version dev ``` -------------------------------- ### Basic Driver Usage in Go Source: https://github.com/seuros/gopher-cypher/blob/master/README.md Demonstrates how to connect to a graph database using Gopher Cypher with custom configuration for logging and TLS. It executes a Cypher query and logs execution time and records consumed. Requires the `github.com/seuros/gopher-cypher/src/driver` package. ```go package main import ( "context" "log" "github.com/seuros/gopher-cypher/src/driver" ) func main() { // Connect with comprehensive configuration config := &driver.Config{ Logging: &driver.LoggingConfig{ Logger: &driver.ConsoleLogger{Level: driver.InfoLevel}, LogQueryTiming: true, LogConnectionPool: true, LogBoltMessages: false, }, TLS: &driver.TLSConfig{ Mode: driver.TLSModeSSL, }, } dr, err := driver.NewDriverWithConfig("bolt://user:pass@localhost:7687", config) if err != nil { log.Fatal(err) } defer dr.Close() ctx := context.Background() cols, rows, summary, err := dr.RunWithContext(ctx, "MATCH (u:User) WHERE u.age > $minAge RETURN u.name, u.age", map[string]interface{}{"minAge": 18}, nil, ) if err != nil { log.Fatal(err) } log.Printf("Query executed in %v, returned %d records", summary.ExecutionTime, summary.RecordsConsumed) } ``` -------------------------------- ### Build Cypher Queries Programmatically with Go Source: https://context7.com/seuros/gopher-cypher/llms.txt Demonstrates building Cypher queries using the Gopher Cypher library. It shows how to add MATCH, WHERE, RETURN, and LIMIT clauses programmatically, registering parameters for safe value substitution. This method avoids string concatenation and ensures query safety. ```go package main import ( "fmt" "github.com/seuros/gopher-cypher/src/cypher" ) func main() { // Build query programmatically q := cypher.NewQuery() // Add MATCH clause matchNode := &cypher.MatchNode{ Pattern: "(u:User)", } q.AddClause(cypher.NewClauseAdapter(matchNode)) // Add WHERE clause with registered parameter ageParam := q.RegisterParameter(25) whereNode := &cypher.WhereNode{ Conditions: []cypher.Expression{ &cypher.ComparisonExpr{ LHS: &cypher.PropertyAccessExpr{ Variable: &cypher.LiteralExpr{Value: "u"}, PropertyName: "age", }, Op: ">", RHS: &cypher.LiteralExpr{Value: ageParam}, }, }, } q.AddClause(cypher.NewClauseAdapter(whereNode)) // Add RETURN clause with property access returnNode := &cypher.ReturnNode{ Items: []interface{}{ &cypher.PropertyAccessExpr{ Variable: &cypher.LiteralExpr{Value: "u"}, PropertyName: "name", }, &cypher.PropertyAccessExpr{ Variable: &cypher.LiteralExpr{Value: "u"}, PropertyName: "email", }, }, } q.AddClause(cypher.NewClauseAdapter(returnNode)) // Add LIMIT clause limitParam := q.RegisterParameter(10) limitNode := &cypher.LimitNode{ Expression: limitParam, } q.AddClause(cypher.NewClauseAdapter(limitNode)) // Build final query cypherQuery, params := q.BuildCypher() fmt.Printf("Generated Cypher:\n%s\n\n", cypherQuery) fmt.Printf("Parameters: %v\n", params) // Output: // Generated Cypher: // MATCH (u:User) // WHERE u.age > $p1 // RETURN u.name, u.email // LIMIT $p2 // // Parameters: map[p1:25 p2:10] } ``` -------------------------------- ### Streaming Query Execution with RunStream in Go Source: https://context7.com/seuros/gopher-cypher/llms.txt Demonstrates how to execute Cypher queries using RunStream for memory-efficient streaming of large result sets. It fetches records on-demand, allowing for constant memory usage regardless of dataset size. Dependencies include the gopher-cypher driver. Inputs are a context, Cypher query, and parameters. Outputs include column names, streamed records, and execution summary. ```go package main import ( "context" "fmt" "log" "github.com/seuros/gopher-cypher/src/driver" ) func main() { dr, _ := driver.NewDriver("bolt://neo4j:password@localhost:7687") defer dr.Close() // Cast to StreamingDriver interface streamingDriver := dr.(driver.StreamingDriver) ctx := context.Background() // Execute streaming query for large dataset result, err := streamingDriver.RunStream( ctx, "MATCH (p:Product) WHERE p.category = $category RETURN p.id, p.name, p.price ORDER BY p.price DESC", map[string]interface{}{"category": "Electronics"}, nil, ) if err != nil { log.Fatalf("Stream query failed: %v", err) } // Get column names columns, _ := result.Keys() fmt.Printf("Columns: %v\n", columns) // Stream records one at a time - constant memory usage count := 0 totalPrice := 0.0 for result.Next(ctx) { record := result.Record() // Process record without loading entire result set productID := (*record)["id"].(int64) productName := (*record)["name"].(string) price := (*record)["price"].(float64) totalPrice += price count++ fmt.Printf("Product %d: %s - $%.2f\n", productID, productName, price) // Progress indicator for large datasets if count%1000 == 0 { fmt.Printf("Processed %d records so far...\n", count) } } // Check for streaming errors if err := result.Err(); err != nil { log.Fatalf("Streaming error: %v", err) } // Get summary statistics summary, _ := result.Consume(ctx) avgPrice := totalPrice / float64(count) fmt.Printf("Streamed %d products, average price: $%.2f\n", count, avgPrice) fmt.Printf("Total execution time: %v\n", summary.ExecutionTime) // Output: Streamed 50000 products, average price: $1249.99 // Output: Total execution time: 2.3s } ``` -------------------------------- ### OpenTelemetry Observability Configuration in Go Source: https://github.com/seuros/gopher-cypher/blob/master/README.md Illustrates how to enable OpenTelemetry for tracing and metrics collection within the Gopher Cypher driver. It shows the configuration of the driver with OpenTelemetry settings and demonstrates how queries are automatically traced, with metrics for duration, record count, and error rates being collected. ```go import ( "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/trace" ) // Configure with OpenTelemetry config := &driver.Config{ Observability: &driver.ObservabilityConfig{ EnableTracing: true, EnableMetrics: true, TracingAttributes: []attribute.KeyValue{ attribute.String("service.name", "user-service"), attribute.String("service.version", "1.0.0"), }, }, } dr, _ := driver.NewDriverWithConfig(url, config) // Queries automatically traced and metrics collected ctx, span := otel.Tracer("app").Start(ctx, "user-query") defer span.End() _, _, summary, _ := dr.RunWithContext(ctx, "MATCH (u:User) RETURN u", nil, nil) // Automatic metrics: query duration, record count, error rates ``` -------------------------------- ### Enterprise Logging Integration with Zap in Go Source: https://github.com/seuros/gopher-cypher/blob/master/README.md Shows how to integrate enterprise logging frameworks, specifically using `go.uber.org/zap`, with the Gopher Cypher driver. It defines a custom logger adapter that implements the driver's logging interface and configures the driver to use this adapter, enabling detailed logging of driver operations. ```go // Integrate with your existing logging framework import "go.uber.org/zap" // Custom logger adapter type ZapLoggerAdapter struct { logger *zap.SugaredLogger } func (z *ZapLoggerAdapter) Debug(msg string, keysAndValues ...interface{}) { z.logger.Debugw(msg, keysAndValues...) } func (z *ZapLoggerAdapter) Info(msg string, keysAndValues ...interface{}) { z.logger.Infow(msg, keysAndValues...) } // Configure driver with your logger zapLogger, _ := zap.NewProduction() config := &driver.Config{ Logging: &driver.LoggingConfig{ Logger: &ZapLoggerAdapter{logger: zapLogger.Sugar()}, LogQueryTiming: true, LogConnectionPool: true, LogBoltMessages: true, // Full protocol debugging }, } dr, _ := driver.NewDriverWithConfig(url, config) ``` -------------------------------- ### Configure Version Injection in Makefile Source: https://github.com/seuros/gopher-cypher/blob/master/BUILD.md This snippet shows how the Makefile is configured to read the version from the VERSION file and inject it into the binary using Go's linker flags (-ldflags). This ensures the 'LibraryVersion' variable is set at compile time. ```makefile VERSION := $(shell cat VERSION) LDFLAGS := -ldflags "-X github.com/seuros/gopher-cypher/src/internal/boltutil.LibraryVersion=$(VERSION)" ``` -------------------------------- ### Advanced Cursor Navigation: Peek and NextRecord in Go Source: https://context7.com/seuros/gopher-cypher/llms.txt Illustrates advanced cursor navigation for streaming results, including peek-ahead functionality without consuming records and batch processing using NextRecord. This allows for inspection of upcoming data and flexible consumption patterns. Dependencies include the gopher-cypher driver. It handles event data with status 'pending'. ```go package main import ( "context" "fmt" "log" "github.com/seuros/gopher-cypher/src/driver" ) func main() { dr, _ := driver.NewDriver("bolt://neo4j:password@localhost:7687") defer dr.Close() streamingDriver := dr.(driver.StreamingDriver) ctx := context.Background() result, err := streamingDriver.RunStream( ctx, "MATCH (e:Event) WHERE e.status = 'pending' RETURN e.id, e.type, e.timestamp ORDER BY e.timestamp", nil, nil, ) if err != nil { log.Fatal(err) } // Peek at first record without consuming it if result.Peek(ctx) { var peekedRec *driver.Record result.PeekRecord(ctx, &peekedRec) fmt.Printf("Next event type: %s\n", (*peekedRec)["type"]) } // Use NextRecord pattern for batch processing var rec *driver.Record batch := make([]*driver.Record, 0, 10) for result.NextRecord(ctx, &rec) { // Copy record to avoid pointer reuse issues recordCopy := make(driver.Record) for k, v := range *rec { recordCopy[k] = v } batch = append(batch, &recordCopy) // Process batches of 10 if len(batch) == 10 { fmt.Printf("Processing batch of %d events\n", len(batch)) // Send to worker pool, queue, etc. processBatch(batch) batch = batch[:0] // Reset batch } } // Process remaining records if len(batch) > 0 { fmt.Printf("Processing final batch of %d events\n", len(batch)) processBatch(batch) } if err := result.Err(); err != nil { log.Fatal(err) } } func processBatch(batch []*driver.Record) { for _, rec := range batch { fmt.Printf("Event %v: %s\n", (*rec)["id"], (*rec)["type"]) } } ``` -------------------------------- ### Initialize Gopher Cypher Driver with Configuration Source: https://context7.com/seuros/gopher-cypher/llms.txt Initializes a new Gopher Cypher driver instance using custom configurations for logging, TLS, connection pooling, and observability. It returns a Driver interface capable of executing synchronous, streaming, and reactive queries against Bolt-compatible databases. ```go package main import ( "context" "fmt" "log" "time" "github.com/seuros/gopher-cypher/src/driver" ) func main() { // Configure driver with enterprise features config := &driver.Config{ Logging: &driver.LoggingConfig{ Logger: driver.NewConsoleLogger(driver.LogLevelInfo), LogQueryTiming: true, LogConnectionPool: true, LogBoltMessages: false, }, TLS: &driver.TLSConfig{ MinVersion: 0x0303, // TLS 1.2 ServerName: "graph.example.com", }, ConnectionPool: &driver.PoolConfig{ MaxConnections: 50, MaxIdleTime: 30 * time.Minute, ConnectionLifetime: 1 * time.Hour, AcquisitionTimeout: 10 * time.Second, EnableLivenessCheck: true, }, Observability: &driver.ObservabilityConfig{ EnableTracing: true, EnableMetrics: true, }, } // Initialize driver with bolt+ssl:// URL dr, err := driver.NewDriverWithConfig( "bolt+ssl://neo4j:password@localhost:7687/mydb", config, ) if err != nil { log.Fatalf("Failed to create driver: %v", err) } defer dr.Close() // Execute query with context ctx := context.Background() cols, rows, summary, err := dr.RunWithContext( ctx, "MATCH (u:User)-[:FOLLOWS]->(f:User) WHERE u.name = $name RETURN f.name AS follower, f.joined AS since", map[string]interface{}{"name": "Alice"}, nil, ) if err != nil { log.Fatalf("Query failed: %v", err) } // Process results fmt.Printf("Columns: %v\n", cols) // Output: [follower since] for _, row := range rows { fmt.Printf("Follower: %s, Since: %v\n", row["follower"], row["since"]) } // Query metadata fmt.Printf("Query executed in %v, returned %d records\n", summary.ExecutionTime, summary.RecordsConsumed) // Output: Query executed in 45ms, returned 12 records } ```