with one click
practice-author
Write optional practice lessons with query exercises
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Menu
Write optional practice lessons with query exercises
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Based on SOC occupation classification
Identify deprecated Cypher syntax in code files.
Create linear issues for the GRAC (GraphAcademy) team.
Periodically review course content for accuracy, relevance, and consistency. This includes checking for deprecated Cypher syntax.
Fact-check a single lesson against Neo4j documentation using the neo4j-docs MCP. Fixes inaccurate claims inline and appends a WHY report.
Review a single lesson for US English grammar, style, voice, and Neo4j terminology. Fixes issues inline and appends a WHY report.
Review a single lesson for pedagogical structure, lesson length, opening pattern, concept delivery, and scaffolding. Fixes issues inline and appends a WHY report.
| name | practice-author |
| description | Write optional practice lessons with query exercises |
| allowed-tools | Read, Write, Edit, Glob, Grep |
Purpose: Write optional practice lessons with query exercises.
When to use: Workshop lesson provides additional query practice for skill reinforcement.
Prerequisites:
This skill writes optional practice lessons that:
:optional: trueDo NOT write concept lessons, challenges, or validation lessons. This skill focuses ONLY on optional practice lessons.
Focus on graph databases and graph technologies.
Practice lessons should:
Before writing anything, answer:
MUST READ:
- WORKSHOP-PLAN.md (for practice objectives)
- Previous lessons (what structure exists, what was taught)
- Source course lesson (for query examples)
- CONTENT_GUIDELINES.md (for style rules)
REFERENCE:
- modules/3-modeling-relationships/lessons/3-optional-queries/lesson.adoc
- modules/4-many-to-many/lessons/3-optional-queries/lesson.adoc
Introduction
├── Explicitly addresses two paths
│ ├── Advanced learners: Skip ahead
│ └── Beginners: These exercises prepare you for [upcoming concept]
└── States what will be practiced
Exercise 1: [Simple Business Question]
├── Question in plain language
└── Collapsible solution with explanation
Exercise 2: [More Complex Question]
├── Question in plain language
└── Collapsible solution with explanation
Exercise 3-5: [Progressive Questions]
├── Each builds complexity
└── Each has solution with variations
Summary
├── Patterns practiced
└── Connection to upcoming concept
Start simple, increase complexity:
:optional: true metadata= [Practice Topic]
:type: lesson
:order: X
:duration: 15
:optional: true
// Source: [course-name]/modules/X/lessons/Y-lesson
[.slide.discrete]
== Optional Practice
You [what was just built]. In this lesson, you will practice [what patterns].
**Advanced learners:** Skip to Module [N+1].
**Beginners:** These exercises prepare you for [upcoming concept].
Example:
= Optional Query Practice
:type: lesson
:order: 4
:duration: 15
:optional: true
// Source: neo4j-fundamentals/modules/2-querying/lessons/3-practice
[.slide.discrete]
== Optional Practice
You imported Customer and Order nodes with PLACED relationships. In this lesson, you will practice traversing these relationships to answer business questions.
**Advanced learners:** Skip to Module 4 for many-to-many relationships.
**Beginners:** These exercises prepare you for multi-hop traversals and collaborative filtering.
CRITICAL: Mark as optional:
:optional: true
This tells the platform this lesson can be skipped.
[.slide]
== Exercise [N]: [Business Question]
[Plain language business question or scenario]
[%collapsible]
====
[source,cypher]
.[Descriptive query title]
----
[Query here with numbered annotations if complex]
----
[Explanation of what query does]
**Try experimenting:**
* [Variation 1]
* [Variation 2]
====
Example Exercise 1 (Simple):
[.slide]
== Exercise 1: Count Customer Orders
How many orders did customer ALFKI place?
[%collapsible]
====
[source,cypher]
.Count orders for a customer
----
MATCH (c:Customer {id: 'ALFKI'})-[:PLACED]->(o:Order)
RETURN c.name, count(o) AS orderCount;
----
This query finds the customer, follows PLACED relationships to orders, and counts them.
**Try experimenting:**
* Change 'ALFKI' to 'ANTON' to count orders for a different customer
* Add `ORDER BY orderCount DESC` after RETURN to see who ordered most
====
Example Exercise 2 (Filtering):
[.slide]
== Exercise 2: Recent Orders
Find orders placed by customer ALFKI in 1997.
[%collapsible]
====
[source,cypher]
.Filter orders by year
----
MATCH (c:Customer {id: 'ALFKI'})-[:PLACED]->(o:Order)
WHERE o.date STARTS WITH '1997'
RETURN o.id, o.date
ORDER BY o.date;
----
The WHERE clause filters orders to only those from 1997. The STARTS WITH operator checks if the date string begins with '1997'.
**Try experimenting:**
* Change '1997' to '1998' to see orders from a different year
* Remove the WHERE clause to see all orders
* Add `LIMIT 5` to see only the first 5 results
====
Example Exercise 3 (Aggregation):
[.slide]
== Exercise 3: Customer Order Summary
List all customers with their order counts, sorted by who ordered most.
[%collapsible]
====
[source,cypher]
.Customer order summary
----
MATCH (c:Customer)-[:PLACED]->(o:Order)
RETURN c.name,
count(o) AS orderCount
ORDER BY orderCount DESC
LIMIT 10;
----
This query finds all customers and their orders, aggregates the count per customer, and sorts to show top customers first.
**Try experimenting:**
* Remove `LIMIT 10` to see all customers
* Add `WHERE orderCount > 5` after RETURN to filter to active customers
* Add `c.country` to RETURN to see where customers are located
====
Example Exercise 4 (Complex):
[.slide]
== Exercise 4: Orders with Multiple Products
Find orders that contain more than 5 different products.
[%collapsible]
====
[source,cypher]
.Orders with many products
----
MATCH (o:Order)-[:ORDERS]->(p:Product) // (1)
WITH o, count(DISTINCT p) AS productCount // (2)
WHERE productCount > 5 // (3)
RETURN o.id, productCount // (4)
ORDER BY productCount DESC;
----
1. **Pattern match** - Find orders and their products
2. **Aggregation** - Count distinct products per order
3. **Filter** - Only orders with more than 5 products
4. **Return** - Show order ID and product count
This query uses WITH to aggregate before filtering, a common pattern when you need to filter on aggregated values.
**Try experimenting:**
* Change `> 5` to `> 10` to find even larger orders
* Add `LIMIT 5` to see just the top 5
* Try counting `o` before the WITH to see total products including duplicates
====
[.summary]
== Summary
In this optional practice, you reinforced [patterns/skills]:
* **[Pattern 1]** - [What it practices]
* **[Pattern 2]** - [What it practices]
* **[Pattern 3]** - [What it practices]
These patterns prepare you for [upcoming concept].
In the next module, you will [what comes next].
Example:
[.summary]
== Summary
In this optional practice, you reinforced query patterns:
* **Relationship traversal** - Following PLACED relationships from customers to orders
* **Filtering** - Using WHERE to find specific data
* **Aggregation** - Counting and collecting results per customer
* **Complex patterns** - Using WITH to aggregate before filtering
These patterns prepare you for multi-hop traversals and collaborative filtering in the next module.
In Module 4, you will learn how to traverse many-to-many relationships between orders and products.
:optional: true in metadata// <1> not // (1)CRITICAL: Use [%collapsible] not [.collapsible]
[%collapsible]
====
[Solution content here]
====
NOT:
[.collapsible]
====
[This won't work!]
====
:optional: trueBefore completing:
Test each query:
Verify progression:
Check explanations:
See these real files:
modules/3-modeling-relationships/lessons/3-optional-queries/lesson.adoc
modules/4-many-to-many/lessons/3-optional-queries/lesson.adoc
modules/2-foundation/lessons/6-optional-queries-cycle1/lesson.adoc
3-optional-queries/lesson.adoc (Module 3):
:optional: true metadataKey patterns:
:optional: true in front matterPattern to practice: COUNT, collect, sum
== Exercise: Total Order Value
Calculate the total value of all orders for customer ALFKI.
[%collapsible]
====
[source,cypher]
----
MATCH (c:Customer {id: 'ALFKI'})-[:PLACED]->(o:Order)
RETURN c.name, sum(o.total) AS totalSpent;
----
====
Pattern to practice: WHERE, comparison operators
== Exercise: High-Value Orders
Find orders with a total value greater than $1000.
[%collapsible]
====
[source,cypher]
----
MATCH (o:Order)
WHERE o.total > 1000
RETURN o.id, o.total
ORDER BY o.total DESC;
----
====
Pattern to practice: Multi-hop traversals
== Exercise: Customer Product Preferences
What products did customer ALFKI order most frequently?
[%collapsible]
====
[source,cypher]
----
MATCH (c:Customer {id: 'ALFKI'})
-[:PLACED]->(:Order)
-[:ORDERS]->(p:Product)
RETURN p.name, count(*) AS timesOrdered
ORDER BY timesOrdered DESC;
----
====
Pattern to practice: collect, list operations
== Exercise: Customer Product List
List all unique products each customer has ordered.
[%collapsible]
====
[source,cypher]
----
MATCH (c:Customer)-[:PLACED]->(:Order)-[:ORDERS]->(p:Product)
RETURN c.name,
collect(DISTINCT p.name) AS products
LIMIT 5;
----
====
Pattern to practice: WITH for chaining queries
== Exercise: Active Customers
Find customers who placed more than 10 orders, show their top 3 most-ordered products.
[%collapsible]
====
[source,cypher]
----
MATCH (c:Customer)-[:PLACED]->(o:Order)
WITH c, count(o) AS orderCount
WHERE orderCount > 10
MATCH (c)-[:PLACED]->(:Order)-[:ORDERS]->(p:Product)
WITH c, p, count(*) AS timesOrdered
ORDER BY timesOrdered DESC
RETURN c.name,
collect(p.name)[0..3] AS topProducts
LIMIT 5;
----
====
Before marking practice lesson complete, verify:
lesson.adoc exists:type: lesson, :order: X, :duration: 5-15, :optional: true