Pattern Comprehensions in Neo4j are a powerful way to “inline” queries inside a single Cypher statement.
They let you collect lists of related nodes or values while applying filters, without needing a separate MATCH
.
🔹 Syntax
-
pattern → a traversal pattern like
(u)-[:WORKS_ON]->(p)
-
expression → usually the starting node
-
WHERE filter → optional condition
-
projection → what to return (node, property, or expression)
1️⃣ Example Dataset
2️⃣ Collect Alice’s projects with filters
✅ Output:
user | projects |
---|---|
Alice | ["ProjectX", "ProjectY"] |
3️⃣ Filter by relationship property
✅ Output:
recent_projects |
---|
["ProjectX"] |
4️⃣ Nested properties from relationships
✅ Output:
details |
---|
[{project:"ProjectX", year:2023}, {project:"ProjectY", year:2022}] |
5️⃣ Aggregation inside comprehension
✅ Output:
p.name | team_size |
---|---|
ProjectX | 2 |
ProjectY | 2 |
👉 When to use Pattern Comprehensions?
-
To inline subqueries without extra MATCH/OPTIONAL MATCH.
-
To filter and project lists of related nodes/relationships.
-
To keep queries compact & expressive.
Let’s now look at Subqueries in Neo4j — introduced in Neo4j 4.x — they’re very useful when you need multi-step logic or want to scope variables.
🔹 Subqueries with CALL { ... }
A subquery is like a "query inside a query".
It’s wrapped inside CALL { ... }
and returns a result that the outer query can continue using.
1️⃣ Syntax
2️⃣ Example Dataset (same as before)
3️⃣ Example – Get Alice’s recent projects (subquery version)
✅ Output:
u.name | recent_projects |
---|---|
Alice | ["ProjectX"] |
4️⃣ Example – Aggregations per group
✅ Output:
p.name | team_size |
---|---|
ProjectX | 2 |
ProjectY | 1 |
5️⃣ Example – Optional subquery
You can also make the whole subquery optional:
✅ Output:
u.name | all_projects |
---|---|
Alice | ["ProjectX", "ProjectY"] |
🔹 When to use Subqueries vs Pattern Comprehensions?
Pattern Comprehension | Subquery (CALL {} ) |
---|---|
Inline filtering & projection | Multi-step logic |
Works inside RETURN only | Can be used anywhere in query |
Good for small filters/lists | Good for aggregations, multiple matches |
Lightweight, compact | More verbose but powerful |
👉 So, if you just need a list with filters → use pattern comprehension.
👉 If you need aggregation, optional logic, or multiple steps → use subqueries.
Let’s dig into List Operations in Cypher — especially two powerful clauses: UNWIND
and WITH
.
🔹 1. UNWIND
– Turn a list into rows
UNWIND
takes a list and expands it into individual rows.
Think of it as the opposite of collect()
.
Example 1: Simple UNWIND
✅ Output:
num |
---|
1 |
2 |
3 |
Example 2: Create multiple nodes from a list
👉 Creates 3 users: Alice, Bob, Charlie.
Example 3: UNWIND with properties
👉 Creates 2 users with properties.
🔹 2. WITH
– Pipeline / pass variables
WITH
is like a pipe: it passes variables to the next part of the query.
Also used for:
-
Aggregations
-
Aliases
-
Ordering, limiting
-
Scoping variables
Example 1: Simple WITH
✅ Renames u.name
→ username
.
Example 2: Filtering with WITH
✅ Finds users who work on more than 1 project.
Example 3: Chaining WITH
✅ Collects all users into a list per project.
Output:
p.name | team |
---|---|
ProjectX | ["Alice", "Bob"] |
ProjectY | ["Alice"] |
🔹 3. Combining UNWIND
+ WITH
Example – Split list per user
👉 For each user, creates 2 skill relationships: Python, Neo4j.
✅ Key Takeaways
-
UNWIND
→ Break a list into rows (for iteration / creation). -
WITH
→ Pipe, filter, rename, aggregate, and control query flow. -
Together → They let you transform data flexibly.
Comments
Post a Comment