Skip to main content

Chapter 2: Getting Started and Basic Usage

Overview

This chapter provides a hands-on introduction to Vektagraf, guiding you through installation, setup, and your first application. You'll learn to define schemas, generate code, and perform basic database operations using Vektagraf's fluent API. By the end of this chapter, you'll have a working Vektagraf application and understand the fundamental patterns for building data-driven applications.

Learning Objectives

By the end of this chapter, you will be able to:

  • Install and configure Vektagraf in your Dart project
  • Create and validate JSON schemas for your data models
  • Generate type-safe Dart code from schemas
  • Perform basic CRUD operations with fluent method chaining
  • Handle common errors and troubleshoot setup issues
  • Configure Vektagraf for different deployment scenarios

Prerequisites

  • Dart SDK 3.0.0 or later installed
  • Basic familiarity with Dart programming
  • Understanding of JSON format
  • Text editor or IDE with Dart support (VS Code, IntelliJ, etc.)

Installation and Setup

Step 1: Create a New Dart Project

Start by creating a new Dart project or adding Vektagraf to an existing one:

# Create a new project
dart create my_vektagraf_app
cd my_vektagraf_app

# Or navigate to your existing project
cd my_existing_project

Step 2: Add Vektagraf Dependency

Add Vektagraf to your pubspec.yaml file:

name: my_vektagraf_app
description: A sample Vektagraf application
version: 1.0.0

environment:
  sdk: '>=3.0.0 <4.0.0'

dependencies:
  vektagraf: ^0.1.0

dev_dependencies:
  test: ^1.24.0
  lints: ^6.0.0

Step 3: Install Dependencies

Run the following command to install Vektagraf and its dependencies:

dart pub get

Step 4: Verify Installation

Create a simple test file to verify the installation:

// test/installation_test.dart
import 'package:test/test.dart';
import 'package:vektagraf/vektagraf.dart';

void main() {
  test('Vektagraf installation', () {
    // Test basic imports and ID generation
    final id = VektagrafId(
      timestamp: DateTime.now().millisecondsSinceEpoch,
      machineId: 1,
      sequence: 1,
    );
    
    expect(id.toString(), isNotEmpty);
    expect(id.toInt(), isPositive);
  });
}

Run the test to confirm everything is working:

dart test test/installation_test.dart

Your First Vektagraf Application

Let's build a simple blog application to demonstrate Vektagraf's core features. This example will showcase schema definition, code generation, and basic operations.

Step 1: Define Your Schema

Create a schema file that defines your data models:

// schema/blog.json
{
  "$schema": "vektagraf://schema/v1",
  "models": {
    "user": {
      "$meta": {
        "description": "Blog user with profile and content creation capabilities",
        "timestamps": true
      },
      "id": "id",
      "username": {
        "type": "string",
        "validation": {
          "minLength": 3,
          "maxLength": 50,
          "pattern": "^[a-zA-Z0-9_]+$"
        }
      },
      "email": {
        "type": "string",
        "validation": {
          "format": "email"
        }
      },
      "display_name": "string",
      "bio": {
        "type": "string",
        "optional": true,
        "validation": {
          "maxLength": 500
        }
      },
      "profile_embedding": {
        "type": "vector",
        "dimensions": 384,
        "distance_function": "cosine",
        "optional": true
      },
      "posts": "[@post]",
      "followers": "{@user}",
      "following": "{@user}",
      "created_at": "datetime",
      "updated_at": "datetime"
    },
    "post": {
      "$meta": {
        "description": "Blog post with content and metadata",
        "timestamps": true
      },
      "id": "id",
      "title": {
        "type": "string",
        "validation": {
          "minLength": 1,
          "maxLength": 200
        }
      },
      "content": {
        "type": "string",
        "validation": {
          "minLength": 1,
          "maxLength": 10000
        }
      },
      "content_embedding": {
        "type": "vector",
        "dimensions": 1536,
        "distance_function": "cosine",
        "optional": true
      },
      "author_id": "id",
      "author": "@user",
      "tags": "{@tag}",
      "published": {
        "type": "bool",
        "default": false
      },
      "view_count": {
        "type": "int32",
        "default": 0
      },
      "created_at": "datetime",
      "updated_at": "datetime"
    },
    "tag": {
      "$meta": {
        "description": "Content categorization tags",
        "timestamps": true
      },
      "id": "id",
      "name": {
        "type": "string",
        "validation": {
          "minLength": 1,
          "maxLength": 50,
          "pattern": "^[a-zA-Z0-9_-]+$"
        }
      },
      "description": {
        "type": "string",
        "optional": true,
        "validation": {
          "maxLength": 200
        }
      },
      "posts": "{@post}",
      "created_at": "datetime"
    }
  },
  "metadata": {
    "version": "1.0.0",
    "description": "Simple blog application schema"
  }
}

Step 2: Generate Dart Code

Vektagraf provides both CLI and programmatic approaches for code generation. Choose the method that fits your workflow:

Option A: CLI Code Generation

# Generate code using the CLI
dart run vektagraf:generate \
  --schema schema/blog.json \
  --output lib/generated/ \
  --package-name my_vektagraf_app

Option B: Programmatic Code Generation

Create a build script for more control over the generation process:

// tool/generate.dart
import 'dart:io';
import 'package:vektagraf/vektagraf.dart';

Future<void> main() async {
  print('Generating Vektagraf code...');
  
  try {
    // Parse the schema
    final parser = VektagrafSchemaParser();
    final schema = await parser.parseFromFile('schema/blog.json');
    
    print('Parsed schema with ${schema.models.length} models:');
    for (final modelName in schema.models.keys) {
      print('  - $modelName');
    }
    
    // Generate code
    final generator = VektagrafCodeGenerator();
    final generatedFiles = await generator.generateFromSchema(
      schema,
      outputDirectory: 'lib/generated',
      packageName: 'my_vektagraf_app',
    );
    
    print('\nGenerated ${generatedFiles.length} files:');
    for (final file in generatedFiles) {
      print('  - $file');
    }
    
    print('\nCode generation completed successfully!');
  } catch (e, stackTrace) {
    print('Error during code generation: $e');
    print('Stack trace: $stackTrace');
    exit(1);
  }
}

Run the generation script:

dart run tool/generate.dart

Step 3: Examine Generated Code

After generation, you'll find several files in the lib/generated/ directory:

lib/generated/
├── models.dart          # Model classes (User, Post, Tag)
├── database.dart        # Database extensions
├── repositories.dart    # Repository classes
└── extensions.dart      # Fluent API extensions

Let's look at what gets generated:

// lib/generated/models.dart (excerpt)
class User {
  final VektagrafId id;
  final String username;
  final String email;
  final String displayName;
  final String? bio;
  final List<double>? profileEmbedding;
  final List<Post> posts;
  final Set<User> followers;
  final Set<User> following;
  final DateTime createdAt;
  final DateTime updatedAt;

  const User({
    required this.id,
    required this.username,
    required this.email,
    required this.displayName,
    this.bio,
    this.profileEmbedding,
    this.posts = const [],
    this.followers = const {},
    this.following = const {},
    required this.createdAt,
    required this.updatedAt,
  });

  // Validation methods
  bool get isValid => _validate().isEmpty;
  List<String> _validate() {
    final errors = <String>[];
    
    if (username.length < 3 || username.length > 50) {
      errors.add('Username must be between 3 and 50 characters');
    }
    
    if (!RegExp(r'^[a-zA-Z0-9_]+$').hasMatch(username)) {
      errors.add('Username can only contain letters, numbers, and underscores');
    }
    
    // Additional validation...
    return errors;
  }

  // Serialization methods
  Map<String, dynamic> toJson() => {
    'id': id.toString(),
    'username': username,
    'email': email,
    'display_name': displayName,
    if (bio != null) 'bio': bio,
    if (profileEmbedding != null) 'profile_embedding': profileEmbedding,
    'created_at': createdAt.toIso8601String(),
    'updated_at': updatedAt.toIso8601String(),
  };

  factory User.fromJson(Map<String, dynamic> json) => User(
    id: VektagrafId.parse(json['id']),
    username: json['username'],
    email: json['email'],
    displayName: json['display_name'],
    bio: json['bio'],
    profileEmbedding: json['profile_embedding']?.cast<double>(),
    createdAt: DateTime.parse(json['created_at']),
    updatedAt: DateTime.parse(json['updated_at']),
  );

  // Copy methods for immutable updates
  User copyWith({
    String? username,
    String? email,
    String? displayName,
    String? bio,
    List<double>? profileEmbedding,
  }) => User(
    id: id,
    username: username ?? this.username,
    email: email ?? this.email,
    displayName: displayName ?? this.displayName,
    bio: bio ?? this.bio,
    profileEmbedding: profileEmbedding ?? this.profileEmbedding,
    posts: posts,
    followers: followers,
    following: following,
    createdAt: createdAt,
    updatedAt: DateTime.now(),
  );
}

Step 4: Create Your Application

Now create your main application file:

// lib/main.dart
import 'package:vektagraf/vektagraf.dart';
import 'generated/models.dart';
import 'generated/database.dart';

Future<void> main() async {
  print('=== Vektagraf Blog Application ===\n');
  
  // Initialize database
  final db = VektagrafDatabase();
  await db.open('blog.vektagraf', config: VektagrafConfig.embedded());
  
  try {
    await runBlogExample(db);
  } finally {
    await db.close();
  }
}

Future<void> runBlogExample(VektagrafDatabase db) async {
  // 1. Create users
  print('1. Creating users...');
  
  final alice = User(
    id: VektagrafId.generate(),
    username: 'alice_dev',
    email: 'alice@example.com',
    displayName: 'Alice Johnson',
    bio: 'Software engineer passionate about databases and AI',
    createdAt: DateTime.now(),
    updatedAt: DateTime.now(),
  );
  
  final bob = User(
    id: VektagrafId.generate(),
    username: 'bob_writer',
    email: 'bob@example.com',
    displayName: 'Bob Smith',
    bio: 'Technical writer and developer advocate',
    createdAt: DateTime.now(),
    updatedAt: DateTime.now(),
  );
  
  // Save users to database
  await db.users().save(alice);
  await db.users().save(bob);
  
  print('Created users: ${alice.displayName}, ${bob.displayName}');
  
  // 2. Create tags
  print('\n2. Creating tags...');
  
  final dartTag = Tag(
    id: VektagrafId.generate(),
    name: 'dart',
    description: 'Dart programming language',
    createdAt: DateTime.now(),
  );
  
  final databaseTag = Tag(
    id: VektagrafId.generate(),
    name: 'database',
    description: 'Database technologies and concepts',
    createdAt: DateTime.now(),
  );
  
  await db.tags().save(dartTag);
  await db.tags().save(databaseTag);
  
  print('Created tags: ${dartTag.name}, ${databaseTag.name}');
  
  // 3. Create posts
  print('\n3. Creating posts...');
  
  final post1 = Post(
    id: VektagrafId.generate(),
    title: 'Getting Started with Vektagraf',
    content: '''
Vektagraf is a revolutionary database that combines object storage, 
vector search, and graph operations in a single platform. In this post, 
we'll explore how to build your first application.

Key features:
- Schema-driven development
- Type-safe Dart integration
- Built-in vector search
- Natural graph operations
- Enterprise security
    ''',
    authorId: alice.id,
    author: alice,
    tags: {dartTag, databaseTag},
    published: true,
    viewCount: 0,
    createdAt: DateTime.now(),
    updatedAt: DateTime.now(),
  );
  
  final post2 = Post(
    id: VektagrafId.generate(),
    title: 'Advanced Vector Search Patterns',
    content: '''
Vector search is becoming increasingly important for modern applications.
This post covers advanced patterns for implementing semantic search,
recommendation systems, and similarity matching using Vektagraf.

Topics covered:
- Embedding generation strategies
- Distance function selection
- Performance optimization
- Hybrid search patterns
    ''',
    authorId: alice.id,
    author: alice,
    tags: {databaseTag},
    published: true,
    viewCount: 0,
    createdAt: DateTime.now(),
    updatedAt: DateTime.now(),
  );
  
  await db.posts().save(post1);
  await db.posts().save(post2);
  
  print('Created posts: "${post1.title}", "${post2.title}"');
  
  // 4. Demonstrate basic queries
  print('\n4. Querying data...');
  
  // Find all users
  final allUsers = await db.users().toList();
  print('Total users: ${allUsers.length}');
  
  // Find posts by author
  final alicePosts = await db.posts()
    .where((post) => post.authorId == alice.id)
    .toList();
  print('Posts by Alice: ${alicePosts.length}');
  
  // Find published posts
  final publishedPosts = await db.posts()
    .where((post) => post.published)
    .toList();
  print('Published posts: ${publishedPosts.length}');
  
  // Find posts with specific tag
  final dartPosts = await db.posts()
    .where((post) => post.tags.any((tag) => tag.name == 'dart'))
    .toList();
  print('Posts tagged with "dart": ${dartPosts.length}');
  
  // 5. Demonstrate updates
  print('\n5. Updating data...');
  
  // Update post view count
  final updatedPost1 = post1.copyWith();
  // Note: In a real implementation, you'd increment the view count
  await db.posts().save(updatedPost1);
  
  // Add follower relationship
  final updatedBob = bob.copyWith();
  // Note: In a real implementation, you'd add Alice to Bob's following set
  await db.users().save(updatedBob);
  
  print('Updated post view count and user relationships');
  
  // 6. Demonstrate complex queries
  print('\n6. Complex queries...');
  
  // Find recent posts by followed users (simulated)
  final recentPosts = await db.posts()
    .where((post) => post.createdAt.isAfter(
      DateTime.now().subtract(Duration(days: 7))
    ))
    .orderBy((post) => post.createdAt, descending: true)
    .take(5);
  
  print('Recent posts (last 7 days): ${recentPosts.length}');
  
  // Find popular tags (posts count > 0)
  final popularTags = await db.tags()
    .where((tag) => tag.posts.isNotEmpty)
    .toList();
  
  print('Popular tags: ${popularTags.map((t) => t.name).join(', ')}');
  
  print('\n=== Blog Example Completed Successfully ===');
}

Step 5: Run Your Application

Execute your application to see Vektagraf in action:

dart run lib/main.dart

Expected output:

=== Vektagraf Blog Application ===

1. Creating users...
Created users: Alice Johnson, Bob Smith

2. Creating tags...
Created tags: dart, database

3. Creating posts...
Created posts: "Getting Started with Vektagraf", "Advanced Vector Search Patterns"

4. Querying data...
Total users: 2
Posts by Alice: 2
Published posts: 2
Posts tagged with "dart": 1

5. Updating data...
Updated post view count and user relationships

6. Complex queries...
Recent posts (last 7 days): 2
Popular tags: dart, database

=== Blog Example Completed Successfully ===

Basic CRUD Operations

Now let's explore the fundamental Create, Read, Update, and Delete operations in detail.

Create Operations

Vektagraf provides several ways to create objects:

// Single object creation
final user = User(
  id: VektagrafId.generate(),
  username: 'new_user',
  email: 'user@example.com',
  displayName: 'New User',
  createdAt: DateTime.now(),
  updatedAt: DateTime.now(),
);

await db.users().save(user);

// Batch creation
final users = [
  User(/* ... */),
  User(/* ... */),
  User(/* ... */),
];

await db.users().saveAll(users);

// Create with validation
try {
  final invalidUser = User(
    id: VektagrafId.generate(),
    username: 'x', // Too short - will fail validation
    email: 'invalid-email', // Invalid format
    displayName: '',
    createdAt: DateTime.now(),
    updatedAt: DateTime.now(),
  );
  
  if (invalidUser.isValid) {
    await db.users().save(invalidUser);
  } else {
    print('Validation errors: ${invalidUser._validate()}');
  }
} catch (e) {
  print('Save failed: $e');
}

Read Operations

Vektagraf's fluent API makes querying intuitive and powerful:

// Find by ID
final user = await db.users().findById(userId);

// Find single object with condition
final alice = await db.users()
  .where((u) => u.username == 'alice_dev')
  .firstOrNull;

// Find multiple objects
final activeUsers = await db.users()
  .where((u) => u.createdAt.isAfter(DateTime.now().subtract(Duration(days: 30))))
  .toList();

// Pagination
final page1 = await db.posts()
  .where((p) => p.published)
  .orderBy((p) => p.createdAt, descending: true)
  .skip(0)
  .take(10);

final page2 = await db.posts()
  .where((p) => p.published)
  .orderBy((p) => p.createdAt, descending: true)
  .skip(10)
  .take(10);

// Count operations
final totalUsers = await db.users().count();
final publishedPostCount = await db.posts()
  .where((p) => p.published)
  .count();

// Existence checks
final hasUsers = await db.users().any();
final hasUnpublishedPosts = await db.posts()
  .where((p) => !p.published)
  .any();

Update Operations

Updates in Vektagraf use immutable patterns with copy methods:

// Single field update
final user = await db.users().findById(userId);
final updatedUser = user.copyWith(
  displayName: 'Updated Display Name',
  bio: 'New bio content',
);
await db.users().save(updatedUser);

// Conditional updates
final posts = await db.posts()
  .where((p) => p.authorId == userId)
  .toList();

for (final post in posts) {
  if (!post.published) {
    final publishedPost = post.copyWith(
      published: true,
      updatedAt: DateTime.now(),
    );
    await db.posts().save(publishedPost);
  }
}

// Batch updates
final unpublishedPosts = await db.posts()
  .where((p) => !p.published)
  .toList();

final publishedPosts = unpublishedPosts.map((p) => p.copyWith(
  published: true,
  updatedAt: DateTime.now(),
)).toList();

await db.posts().saveAll(publishedPosts);

Delete Operations

Vektagraf supports both soft and hard deletion patterns:

// Delete by ID
await db.users().deleteById(userId);

// Delete by condition
await db.posts()
  .where((p) => !p.published && p.createdAt.isBefore(
    DateTime.now().subtract(Duration(days: 30))
  ))
  .delete();

// Delete all objects of a type (use with caution)
await db.tags().deleteAll();

// Soft delete pattern (using a deleted field)
final user = await db.users().findById(userId);
final softDeletedUser = user.copyWith(
  // Assuming you have a 'deleted' field in your schema
  // deleted: true,
  updatedAt: DateTime.now(),
);
await db.users().save(softDeletedUser);

Configuration Options

Vektagraf supports various configuration options for different deployment scenarios.

Embedded Configuration

For single-application deployments:

final config = VektagrafConfig.embedded(
  maxMemoryBytes: 512 * 1024 * 1024, // 512MB
  enableCompression: true,
  enableEncryption: false, // Disable for development
  backupInterval: Duration(hours: 6),
);

final db = VektagrafDatabase();
await db.open('myapp.vektagraf', config: config);

Hosted Configuration

For client-server deployments:

final config = VektagrafConfig.hosted(
  connectionTimeout: Duration(seconds: 10),
  maxConnections: 20,
  enableTLS: true,
  authToken: await getAuthToken(),
  retryAttempts: 3,
);

final db = VektagrafDatabase();
await db.open('vektagraf://server:8080/mydb', config: config);

Development Configuration

Optimized for development and testing:

final config = VektagrafConfig(
  // Fast startup
  maxMemoryBytes: 128 * 1024 * 1024, // 128MB
  enableCompression: false,
  enableEncryption: false,
  
  // Detailed logging
  enableLogging: true,
  logLevel: LogLevel.debug,
  
  // Relaxed timeouts
  requestTimeout: Duration(seconds: 30),
  transactionTimeout: Duration(minutes: 5),
  
  // Development features
  enableMetrics: true,
  enableProfiler: true,
);

Production Configuration

Optimized for production environments:

final config = VektagrafConfig(
  // Performance settings
  maxMemoryBytes: 2 * 1024 * 1024 * 1024, // 2GB
  enableCompression: true,
  enableEncryption: true,
  
  // Security settings
  enableTLS: true,
  tlsCertificatePath: '/etc/ssl/certs/vektagraf.crt',
  tlsKeyPath: '/etc/ssl/private/vektagraf.key',
  
  // Reliability settings
  backupInterval: Duration(hours: 1),
  maxRetryAttempts: 5,
  connectionTimeout: Duration(seconds: 5),
  
  // Monitoring
  enableMetrics: true,
  enableAuditLog: true,
  logLevel: LogLevel.warning,
);

Common Error Scenarios and Troubleshooting

Understanding common errors and their solutions will help you develop more robust applications.

Schema Validation Errors

// Error: Invalid schema format
try {
  final parser = VektagrafSchemaParser();
  final schema = await parser.parseFromFile('invalid_schema.json');
} catch (e) {
  if (e is SchemaParseException) {
    print('Schema error in ${e.model}.${e.field}: ${e.message}');
    // Handle specific schema issues
  }
}

Connection Errors

// Error: Database connection failed
try {
  final db = VektagrafDatabase();
  await db.open('vektagraf://unreachable:8080/db');
} catch (e) {
  print('Connection failed: $e');
  
  // Implement retry logic
  for (int attempt = 1; attempt <= 3; attempt++) {
    try {
      await Future.delayed(Duration(seconds: attempt * 2));
      await db.open('vektagraf://backup:8080/db');
      break;
    } catch (retryError) {
      if (attempt == 3) {
        print('All connection attempts failed');
        rethrow;
      }
    }
  }
}

Validation Errors

// Error: Object validation failed
final user = User(
  id: VektagrafId.generate(),
  username: 'x', // Too short
  email: 'invalid', // Invalid format
  displayName: '',
  createdAt: DateTime.now(),
  updatedAt: DateTime.now(),
);

if (!user.isValid) {
  final errors = user._validate();
  print('Validation failed:');
  for (final error in errors) {
    print('  - $error');
  }
  
  // Handle validation errors appropriately
  return;
}

Transaction Errors

// Error: Transaction conflict or timeout
try {
  await db.transaction((tx) async {
    final user = await tx.users().findById(userId);
    final updatedUser = user.copyWith(displayName: 'New Name');
    await tx.users().save(updatedUser);
    
    // Simulate long operation that might timeout
    await Future.delayed(Duration(minutes: 10));
  });
} catch (e) {
  if (e is TransactionTimeoutException) {
    print('Transaction timed out - consider breaking into smaller operations');
  } else if (e is TransactionConflictException) {
    print('Transaction conflict - retry with exponential backoff');
  }
}

Performance Issues

// Issue: Slow queries
// Solution: Add proper indexing and optimize queries

// Instead of loading all objects
final allPosts = await db.posts().toList(); // Slow for large datasets

// Use pagination and filtering
final recentPosts = await db.posts()
  .where((p) => p.createdAt.isAfter(DateTime.now().subtract(Duration(days: 7))))
  .orderBy((p) => p.createdAt, descending: true)
  .take(20); // Much faster

// Use count instead of loading objects
final totalCount = await db.posts().count(); // Fast
// Instead of: final count = (await db.posts().toList()).length; // Slow

Memory Issues

// Issue: Out of memory errors
// Solution: Process data in batches

// Instead of loading everything at once
final allUsers = await db.users().toList(); // May cause OOM

// Process in batches
const batchSize = 100;
int offset = 0;

while (true) {
  final batch = await db.users()
    .skip(offset)
    .take(batchSize);
  
  if (batch.isEmpty) break;
  
  // Process batch
  for (final user in batch) {
    // Process individual user
  }
  
  offset += batchSize;
}

Best Practices

Schema Design

  1. Use descriptive names: Choose clear, consistent naming for models and fields
  2. Add validation: Define validation rules in your schema to catch errors early
  3. Plan relationships: Think about how your objects relate before defining relationships
  4. Version your schemas: Use schema versioning for production applications

Code Organization

// Organize your code into logical modules
lib/
├── models/           # Generated model classes
├── repositories/     # Data access layer
├── services/         # Business logic
├── utils/           # Helper functions
└── main.dart        # Application entry point

Error Handling

// Always handle potential errors gracefully
Future<User?> findUserSafely(VektagrafId userId) async {
  try {
    return await db.users().findById(userId);
  } catch (e) {
    logger.error('Failed to find user $userId: $e');
    return null;
  }
}

Performance Optimization

// Use appropriate query patterns
// Good: Specific queries with conditions
final activeUsers = await db.users()
  .where((u) => u.lastLoginAt.isAfter(cutoffDate))
  .take(100);

// Bad: Loading everything then filtering
final allUsers = await db.users().toList();
final activeUsers = allUsers.where((u) => 
  u.lastLoginAt.isAfter(cutoffDate)).take(100).toList();

Summary

This chapter introduced you to Vektagraf's fundamental concepts and operations. You learned how to:

  1. Install and configure Vektagraf in your Dart project
  2. Define schemas using JSON with proper validation and relationships
  3. Generate type-safe code from schemas using CLI or programmatic approaches
  4. Perform CRUD operations using Vektagraf's fluent API
  5. Handle common errors and troubleshoot issues effectively
  6. Configure Vektagraf for different deployment scenarios

Key takeaways:

  • Schema-first development ensures consistency and type safety
  • Fluent APIs make complex queries readable and maintainable
  • Generated code provides compile-time validation and IDE support
  • Proper error handling is essential for robust applications
  • Configuration matters for performance and reliability

In the next chapter, we'll dive deeper into schema design and explore advanced code generation features that enable more sophisticated applications.

Next Steps

  • Chapter 3: Schema Design and Code Generation - Master advanced schema patterns
  • Chapter 4: Database Operations and Transactions - Learn advanced query patterns
  • Chapter 5: Vector Search and Similarity Operations - Implement semantic search
  • Chapter 6: Graph Operations and Relationship Modeling - Build connected applications