Hands-On Learning
Hands-on learning provides the fastest path to mastering Geode through practical exercises, interactive challenges, and real-world scenarios. Learn by building, not just reading.
Interactive Learning Philosophy
Active Engagement: Type every query yourself. Copy-paste teaches syntax; typing builds muscle memory and understanding.
Immediate Feedback: Execute queries and see results instantly. When something doesn’t work, you learn why and how to fix it.
Progressive Challenges: Start simple and increase complexity gradually. Each exercise builds on previous knowledge while introducing new concepts.
Real-World Context: Work with realistic datasets and scenarios—social networks, e-commerce systems, knowledge graphs—not toy examples.
Exercise 1: Building Your First Social Network (30 minutes)
Setup
# Start Geode and connect
geode serve --listen localhost:3141 &
geode shell
Task 1.1: Create User Profiles
Create 5 users with varying ages and locations:
CREATE (alice:Person {name: 'Alice', age: 30, city: 'New York'})
CREATE (bob:Person {name: 'Bob', age: 25, city: 'San Francisco'})
CREATE (carol:Person {name: 'Carol', age: 28, city: 'New York'})
CREATE (dave:Person {name: 'Dave', age: 35, city: 'Chicago'})
CREATE (eve:Person {name: 'Eve', age: 27, city: 'San Francisco'})
Verification: Run MATCH (p:Person) RETURN count(p) - should return 5.
Task 1.2: Add Friendships
Create relationships between users:
MATCH (alice:Person {name: 'Alice'})
MATCH (bob:Person {name: 'Bob'})
CREATE (alice)-[:KNOWS {since: 2020}]->(bob)
Challenge: Add 6 more friendships forming a connected network. Make some bidirectional by creating relationships in both directions.
Task 1.3: Query Your Network
Find all of Alice’s friends:
MATCH (alice:Person {name: 'Alice'})-[:KNOWS]->(friend)
RETURN friend.name, friend.city
Challenge Questions:
- Who lives in the same city as Alice?
- Who has the most friends?
- Find all friends-of-friends for Bob who aren’t direct friends
Solutions
-- Same city as Alice
MATCH (alice:Person {name: 'Alice'})
MATCH (other:Person {city: alice.city})
WHERE other <> alice
RETURN other.name
-- Most friends
MATCH (p:Person)-[:KNOWS]->(friend)
RETURN p.name, COUNT(friend) as friend_count
ORDER BY friend_count DESC
LIMIT 1
-- Friends of friends
MATCH (bob:Person {name: 'Bob'})-[:KNOWS]->(friend)-[:KNOWS]->(fof)
WHERE NOT (bob)-[:KNOWS]->(fof) AND bob <> fof
RETURN DISTINCT fof.name
Exercise 2: E-Commerce Recommendation Engine (45 minutes)
Setup Data
-- Create products
CREATE (laptop:Product {id: 'p1', name: 'Laptop', price: 999, category: 'Electronics'})
CREATE (mouse:Product {id: 'p2', name: 'Mouse', price: 29, category: 'Electronics'})
CREATE (keyboard:Product {id: 'p3', name: 'Keyboard', price: 79, category: 'Electronics'})
CREATE (desk:Product {id: 'p4', name: 'Desk', price: 299, category: 'Furniture'})
CREATE (chair:Product {id: 'p5', name: 'Chair', price: 199, category: 'Furniture'})
-- Create users
CREATE (u1:User {id: 'u1', name: 'Alice'})
CREATE (u2:User {id: 'u2', name: 'Bob'})
CREATE (u3:User {id: 'u3', name: 'Carol'})
-- Purchase history
MATCH (u1:User {id: 'u1'}), (laptop:Product {id: 'p1'})
CREATE (u1)-[:PURCHASED {at: '2025-01-01'}]->(laptop)
MATCH (u1:User {id: 'u1'}), (mouse:Product {id: 'p2'})
CREATE (u1)-[:PURCHASED {at: '2025-01-02'}]->(mouse)
MATCH (u2:User {id: 'u2'}), (laptop:Product {id: 'p1'})
CREATE (u2)-[:PURCHASED {at: '2025-01-03'}]->(laptop)
MATCH (u2:User {id: 'u2'}), (keyboard:Product {id: 'p3'})
CREATE (u2)-[:PURCHASED {at: '2025-01-04'}]->(keyboard)
Task 2.1: Basic Recommendations
Write a query that recommends products to Alice based on what users with similar purchases bought:
MATCH (alice:User {id: 'u1'})-[:PURCHASED]->(p:Product)
<-[:PURCHASED]-(other:User)-[:PURCHASED]->(rec:Product)
WHERE NOT (alice)-[:PURCHASED]->(rec)
RETURN rec.name, rec.price, COUNT(*) as relevance
ORDER BY relevance DESC, rec.price ASC
Challenge: Modify to only recommend products under $100 in the Electronics category.
Task 2.2: Product Similarity
Create similarity relationships between products:
MATCH (p1:Product), (p2:Product)
WHERE p1.category = p2.category AND p1 <> p2
CREATE (p1)-[:SIMILAR_TO {reason: 'same_category'}]->(p2)
Challenge: Create a query that recommends “frequently bought together” products based on users who bought both.
Task 2.3: Category Browsing
MATCH (p:Product {category: 'Electronics'})
RETURN p.name, p.price
ORDER BY p.price DESC
Challenge: Add pagination (SKIP/LIMIT) and price range filtering.
Exercise 3: Knowledge Graph Navigation (45 minutes)
Setup Hierarchical Data
-- Create topic hierarchy
CREATE (root:Topic {name: 'Computer Science'})
CREATE (ai:Topic {name: 'Artificial Intelligence'})
CREATE (ml:Topic {name: 'Machine Learning'})
CREATE (dl:Topic {name: 'Deep Learning'})
CREATE (cv:Topic {name: 'Computer Vision'})
CREATE (nlp:Topic {name: 'Natural Language Processing'})
-- Create hierarchy
MATCH (root:Topic {name: 'Computer Science'})
MATCH (ai:Topic {name: 'Artificial Intelligence'})
CREATE (ai)-[:SUBTOPIC_OF]->(root)
MATCH (ai:Topic {name: 'Artificial Intelligence'})
MATCH (ml:Topic {name: 'Machine Learning'})
CREATE (ml)-[:SUBTOPIC_OF]->(ai)
MATCH (ml:Topic {name: 'Machine Learning'})
MATCH (dl:Topic {name: 'Deep Learning'})
CREATE (dl)-[:SUBTOPIC_OF]->(ml)
-- Add more connections...
Task 3.1: Tree Traversal
Find all subtopics of a topic at any depth:
MATCH (parent:Topic {name: 'Artificial Intelligence'})
<-[:SUBTOPIC_OF*]-(child:Topic)
RETURN child.name, length(path) as depth
ORDER BY depth, child.name
Challenge: Find the path from ‘Deep Learning’ to ‘Computer Science’ and list all intermediate topics.
Task 3.2: Related Concepts
Add cross-cutting relationships:
MATCH (cv:Topic {name: 'Computer Vision'})
MATCH (dl:Topic {name: 'Deep Learning'})
CREATE (cv)-[:RELATED_TO {strength: 0.9}]->(dl)
Challenge: Find all topics within 2 hops of ‘Natural Language Processing’ (ignoring hierarchy).
Exercise 4: Access Control with Row-Level Security (30 minutes)
Task 4.1: Multi-Tenant Data
-- Create organizations
CREATE (orgA:Organization {id: 'org1', name: 'Acme Corp'})
CREATE (orgB:Organization {id: 'org2', name: 'TechStart Inc'})
-- Create users belonging to organizations
CREATE (u1:User {id: 'u1', name: 'Alice', org_id: 'org1'})
CREATE (u2:User {id: 'u2', name: 'Bob', org_id: 'org1'})
CREATE (u3:User {id: 'u3', name: 'Carol', org_id: 'org2'})
-- Link users to organizations
MATCH (u:User {id: 'u1'}), (org:Organization {id: 'org1'})
CREATE (u)-[:BELONGS_TO]->(org)
Task 4.2: Filtered Queries
Write a query that only returns users from Alice’s organization:
MATCH (current:User {id: 'u1'})-[:BELONGS_TO]->(org:Organization)
MATCH (coworker:User)-[:BELONGS_TO]->(org)
WHERE coworker <> current
RETURN coworker.name
Challenge: Create a view or parameterized query that automatically filters based on the current user’s organization.
Exercise 5: Performance Optimization (45 minutes)
Task 5.1: Create Sample Data
import asyncio
from geode_client import Client
async def load_data():
client = Client(host="localhost", port=3141)
async with client.connection() as conn:
# Create 1000 users
for i in range(1000):
await conn.execute("""
CREATE (u:User {
id: $id,
name: $name,
email: $email,
created_at: $timestamp
})
""", id=f"user{i}", name=f"User {i}",
email=f"user{i}@example.com",
timestamp="2025-01-01T00:00:00Z")
asyncio.run(load_data())
Task 5.2: Profile Slow Query
-- Run this query and note the execution time
PROFILE MATCH (u:User {email: 'user500@example.com'})
RETURN u.name, u.created_at
Challenge: Create an index on email and compare execution time:
CREATE INDEX ON User(email)
-- Re-run the profile query
PROFILE MATCH (u:User {email: 'user500@example.com'})
RETURN u.name, u.created_at
Task 5.3: Identify Cartesian Products
-- This query is inefficient - why?
MATCH (u:User), (p:Product)
RETURN count(*)
Challenge: Rewrite using proper relationship patterns.
Exercise 6: Transaction Management (30 minutes)
Task 6.1: Banking Transfer
Implement an atomic money transfer:
async def transfer(client, from_id, to_id, amount):
async with client.connection() as tx:
await tx.begin()
# Check sender balance
result, _ = await tx.query("""
MATCH (sender:Account {id: $id})
RETURN sender.balance
""", id=from_id)
row = await result.first()
if row['sender.balance'] < amount:
raise Exception("Insufficient funds")
# Deduct from sender
await tx.execute("""
MATCH (sender:Account {id: $id})
SET sender.balance = sender.balance - $amount
""", id=from_id, amount=amount)
# Add to receiver
await tx.execute("""
MATCH (receiver:Account {id: $id})
SET receiver.balance = receiver.balance + $amount
""", id=to_id, amount=amount)
# Transaction commits automatically if no exceptions
Challenge: Add rollback handling for various failure scenarios.
Task 6.2: Savepoints
async def complex_operation(client):
async with client.connection() as tx:
await tx.begin()
await tx.execute("CREATE (u:User {id: 'temp1', name: 'Test'})")
sp = await tx.savepoint("checkpoint")
try:
# Risky operation
await tx.execute("CREATE (u:User {id: 'temp1'})") # Duplicate!
except Exception:
await tx.rollback_to(sp) # Rollback to savepoint
await tx.execute("CREATE (u:User {id: 'temp2'})")
Challenge: Implement a multi-step import process with savepoints after each batch.
Hands-On Challenges
Challenge 1: Shortest Path
Find the shortest path between any two nodes in your social network. Calculate the degrees of separation.
Challenge 2: Influence Scoring
Implement a query that calculates influence scores based on connection count and friend influence (recursive).
Challenge 3: Real-Time Feeds
Build a query that returns the latest posts from friends, ordered by timestamp with pagination.
Challenge 4: Fraud Detection
Create a graph of financial transactions and write queries to detect suspicious patterns (circular transfers, velocity rules).
Challenge 5: Recommendation Diversity
Modify the recommendation engine to balance relevance with diversity (different categories, price ranges).
Learning Labs
Lab 1: Schema Design Workshop
Given a business domain (e.g., healthcare, logistics, media), design a complete graph schema. Create sample data and write 10 queries covering common use cases.
Lab 2: Migration Project
Take an existing relational database schema and migrate it to Geode. Write queries that demonstrate improved performance for relationship-heavy queries.
Lab 3: Performance Tuning
Start with slow queries, profile them, add indexes strategically, and measure improvements. Document your optimization process.
Lab 4: Security Hardening
Implement a complete security model with authentication, role-based access, and row-level security for a multi-tenant application.
Challenge Solutions and Hints
Shortest Path Challenge Solution
-- Find degrees of separation between any two users
MATCH path = SHORTEST_PATH((a:User {name: 'Alice'})-[:KNOWS*]-(b:User {name: 'Eve'}))
RETURN length(path) AS degrees_of_separation,
[node IN nodes(path) | node.name] AS path_names;
-- Find all paths within certain degree
MATCH path = (a:User {name: 'Alice'})-[:KNOWS*1..3]-(b:User)
WHERE a <> b
RETURN b.name, length(path) AS degree
ORDER BY degree, b.name;
Influence Scoring Challenge Solution
-- Calculate PageRank-style influence
WITH collect(DISTINCT n) AS all_users
UNWIND all_users AS user
MATCH (user:User)
OPTIONAL MATCH (user)-[:KNOWS]->(friend:User)
WITH user,
COUNT(friend) AS direct_influence,
COLLECT(friend) AS friends
UNWIND friends AS friend
OPTIONAL MATCH (friend)-[:KNOWS]->(fof:User)
WITH user, direct_influence,
AVG(COUNT(fof)) AS avg_friend_influence
RETURN user.name,
direct_influence,
avg_friend_influence,
direct_influence + (avg_friend_influence * 0.5) AS total_influence
ORDER BY total_influence DESC;
Real-Time Feed Challenge Solution
-- Latest posts from friends with pagination
MATCH (current:User {id: $user_id})-[:FOLLOWS]->(friend:User)-[:POSTED]->(post:Post)
RETURN friend.name,
post.content,
post.timestamp,
post.likes_count
ORDER BY post.timestamp DESC
SKIP $offset
LIMIT $page_size;
-- With comment count
MATCH (current:User {id: $user_id})-[:FOLLOWS]->(friend:User)-[:POSTED]->(post:Post)
OPTIONAL MATCH (post)<-[:COMMENTED]-(comment:Comment)
WITH friend, post, COUNT(comment) AS comment_count
RETURN friend.name,
post.content,
post.timestamp,
post.likes_count,
comment_count
ORDER BY post.timestamp DESC
SKIP $offset
LIMIT $page_size;
Fraud Detection Challenge Solution
-- Detect circular payment patterns
MATCH path = (a:Account)-[:PAYMENT*3..5]->(a)
WHERE ALL(r IN relationships(path) WHERE r.amount > 1000)
AND ALL(n IN nodes(path) WHERE SIZE([(n)-[:PAYMENT]->() | 1]) > 5)
RETURN path,
[r IN relationships(path) | r.amount] AS amounts,
REDUCE(total = 0, r IN relationships(path) | total + r.amount) AS total_amount;
-- Velocity check: Too many transactions in short time
MATCH (a:Account)-[t:PAYMENT]->()
WHERE t.timestamp > CURRENT_TIMESTAMP - INTERVAL '1' HOUR
WITH a, COUNT(t) AS tx_count, SUM(t.amount) AS total_amount
WHERE tx_count > 10 OR total_amount > 50000
RETURN a.id, tx_count, total_amount
ORDER BY tx_count DESC;
-- Unusual pattern: Receive then immediately send similar amount
MATCH (a:Account)<-[r1:PAYMENT]-(sender)
WHERE r1.timestamp > CURRENT_TIMESTAMP - INTERVAL '24' HOUR
MATCH (a)-[r2:PAYMENT]->(recipient)
WHERE r2.timestamp > r1.timestamp
AND r2.timestamp < r1.timestamp + INTERVAL '1' HOUR
AND ABS(r2.amount - r1.amount) < r1.amount * 0.05 -- Within 5%
RETURN a.id,
sender.id,
recipient.id,
r1.amount,
r2.amount,
DURATION.BETWEEN(r1.timestamp, r2.timestamp).minutes AS minutes_between;
Advanced Hands-On Projects
Project 1: Build a Recommendation System
Objective: Create a complete recommendation engine with multiple algorithms.
Requirements:
- Collaborative filtering based on user similarity
- Content-based recommendations using product attributes
- Hybrid approach combining both
- A/B testing framework to compare algorithms
- Real-time recommendation serving
Starter Code:
class RecommendationEngine:
def __init__(self, client):
self.client = client
async def collaborative_filtering(self, user_id, limit=10):
"""Find products liked by similar users"""
result, _ = await self.client.query("""
// TODO: Implement collaborative filtering
// 1. Find users who bought similar products
// 2. Find products those users also bought
// 3. Rank by similarity score
""", {"user_id": user_id, "limit": limit})
return result
async def content_based(self, user_id, limit=10):
"""Recommend based on product attributes"""
result, _ = await self.client.query("""
// TODO: Implement content-based filtering
// 1. Find products user has liked
// 2. Find similar products by attributes
// 3. Rank by attribute similarity
""", {"user_id": user_id, "limit": limit})
return result
async def hybrid(self, user_id, limit=10):
"""Combine both approaches"""
collab = await self.collaborative_filtering(user_id, limit * 2)
content = await self.content_based(user_id, limit * 2)
# TODO: Implement ranking combination
pass
Project 2: Social Network Analytics Dashboard
Objective: Build analytics dashboard for social network insights.
Features:
- User growth metrics (daily/weekly/monthly active users)
- Engagement metrics (posts, likes, comments per user)
- Network topology analysis (clusters, influencers)
- Content virality tracking
- Retention cohort analysis
Queries to Implement:
-- Daily active users
MATCH (u:User)-[:ACTION]->(a)
WHERE a.timestamp >= DATE_TRUNC('day', CURRENT_TIMESTAMP)
RETURN DATE(a.timestamp) AS date,
COUNT(DISTINCT u) AS daily_active_users;
-- Top influencers by engagement
MATCH (u:User)-[:POSTED]->(p:Post)
OPTIONAL MATCH (p)<-[:LIKED]-(liker)
OPTIONAL MATCH (p)<-[:COMMENTED]-(commenter)
WITH u,
COUNT(DISTINCT p) AS post_count,
COUNT(DISTINCT liker) AS total_likes,
COUNT(DISTINCT commenter) AS total_comments
RETURN u.name,
post_count,
total_likes,
total_comments,
(total_likes + total_comments * 2) AS engagement_score
ORDER BY engagement_score DESC
LIMIT 100;
-- Content virality (posts shared most)
MATCH (p:Post)<-[:SHARED]-(sharer:User)
WITH p, COUNT(sharer) AS share_count
WHERE share_count > 5
MATCH (original_poster:User)-[:POSTED]->(p)
RETURN original_poster.name,
p.content,
p.timestamp,
share_count,
DURATION.BETWEEN(p.timestamp, CURRENT_TIMESTAMP).hours AS hours_since_posted,
share_count * 1.0 / DURATION.BETWEEN(p.timestamp, CURRENT_TIMESTAMP).hours AS virality_rate
ORDER BY virality_rate DESC;
Project 3: Knowledge Graph Query Engine
Objective: Build intelligent query engine over knowledge graph.
Features:
- Natural language to GQL translation
- Entity recognition and linking
- Relationship extraction
- Answer ranking by relevance
- Explanation generation
Implementation Outline:
class KnowledgeGraphQueryEngine:
def __init__(self, client, nlp_model):
self.client = client
self.nlp = nlp_model
async def query(self, natural_language_question):
"""Answer question using knowledge graph"""
# 1. Extract entities
entities = self.extract_entities(natural_language_question)
# 2. Generate GQL queries
gql_queries = self.generate_queries(entities, natural_language_question)
# 3. Execute queries
results = []
for query in gql_queries:
result, _ = await self.client.query(query)
results.append(result)
# 4. Rank and format answers
answers = self.rank_answers(results, natural_language_question)
return answers
def extract_entities(self, question):
# TODO: Use NLP to extract named entities
pass
def generate_queries(self, entities, question):
# TODO: Generate GQL queries based on question type
pass
Project 4: Multi-Tenant SaaS Application
Objective: Build complete multi-tenant application with RLS.
Features:
- Tenant isolation using RLS policies
- Per-tenant resource limits
- Shared schema with tenant-specific data
- Audit logging per tenant
- Tenant analytics dashboard
RLS Policy Examples:
-- Create RLS policy for tenant isolation
CREATE POLICY tenant_isolation ON User
FOR ALL
USING (tenant_id = current_tenant_id());
-- Create policy for hierarchical access
CREATE POLICY manager_access ON Employee
FOR SELECT
USING (
employee_id = current_user_id()
OR EXISTS {
MATCH (current:Employee {id: current_user_id()})-[:MANAGES*]->(emp:Employee)
WHERE emp.employee_id = Employee.employee_id
}
);
-- Row-level encryption policy
CREATE POLICY sensitive_data ON Customer
FOR SELECT
USING (
has_permission(current_user_id(), 'view_pii')
OR customer_id = current_user_id()
);
Debugging Exercises
Exercise: Debug Slow Query
Problem: This query is very slow. Fix it.
-- Slow query
MATCH (u:User)
MATCH (p:Product)
WHERE EXISTS {
MATCH (u)-[:PURCHASED]->(p)
}
RETURN u.name, p.name;
Steps:
- Run EXPLAIN to see execution plan
- Identify the problem (hint: Cartesian product)
- Rewrite to use proper pattern matching
- Verify with PROFILE
Solution
-- Optimized query
MATCH (u:User)-[:PURCHASED]->(p:Product)
RETURN u.name, p.name;
The original creates a Cartesian product of ALL users × ALL products, then filters. The optimized version uses pattern matching directly.
Exercise: Fix Transaction Deadlock
Problem: Two concurrent transactions are deadlocking.
Transaction 1:
BEGIN;
MATCH (a:Account {id: 1}) SET a.balance = a.balance - 100;
-- Pause
MATCH (b:Account {id: 2}) SET b.balance = b.balance + 100;
COMMIT;
Transaction 2:
BEGIN;
MATCH (b:Account {id: 2}) SET b.balance = b.balance - 50;
-- Pause
MATCH (a:Account {id: 1}) SET a.balance = a.balance + 50;
COMMIT;
Task: Identify why deadlock occurs and fix it.
Solution
Deadlock occurs because:
- TX1 locks Account 1, then tries to lock Account 2
- TX2 locks Account 2, then tries to lock Account 1
Fix: Always acquire locks in consistent order:
-- Both transactions should lock in same order (by ID)
BEGIN;
MATCH (a:Account {id: 1}), (b:Account {id: 2})
WHERE a.id < b.id
SET a.balance = a.balance - 100,
b.balance = b.balance + 100;
COMMIT;
Community Challenges
Weekly Challenge: Graph Algorithm Implementation
Implement these algorithms using only GQL:
- Dijkstra’s shortest path with weighted edges
- Triangle counting for clustering coefficient
- Graph coloring for conflict-free scheduling
- Maximum flow in a network
- Minimum spanning tree for optimization
Monthly Project: Build a Full Application
Complete projects that combine multiple concepts:
- Twitter Clone: Social graph with posts, likes, retweets, trending topics
- E-commerce Platform: Products, recommendations, reviews, fraud detection
- Knowledge Base: Hierarchical documentation with search and recommendations
- Project Management: Tasks, dependencies, resources, timelines
- Supply Chain: Logistics network with optimization and tracking
Related Topics
- Tutorials : Structured learning paths with explanations
- Examples : Copy-paste ready code snippets
- Getting Started : Foundation concepts and setup
- Developer Guide : Complete API reference
- Quickstart : Fast-track guides for immediate productivity
- Tutorials : Structured learning paths
- Examples : Ready-to-use code examples
Additional Resources
- Video Walkthroughs: Watch step-by-step solution videos
- Community Forums: Discuss solutions and get help
- Code Templates: Starter code for common patterns
- Solution Repository: Browse complete working solutions
- Office Hours: Weekly live coding sessions
Start with Exercise 1 and work your way through. Don’t skip ahead – each exercise builds essential skills for the next!