Using pattern comprehension
Pattern comprehension in Cypher enables you to create a list based upon values obtained during a query. It is implemented in Cypher as a subquery.
Here is how we aggregate using the collect()
function:
PROFILE
MATCH(m:Movie)
WHERE m.year = 2015
OPTIONAL MATCH (a:Person)-[:ACTED_IN]-(m)
WITH m, collect(DISTINCT a.name) AS Actors
OPTIONAL MATCH (m)-[:DIRECTED]-(d:Person)
RETURN m.title AS Movie, Actors, collect (DISTINCT d.name) AS Directors
Using Cypher’s pattern comprehension syntax: [<pattern> | value]
, we dynamically return a list using values obtained from the pattern.
In some cases, pattern comprehension performs better than using collect()
because it uses a subquery.
Here is the same query using pattern comprehension:
PROFILE
MATCH (m:Movie)
WHERE m.year = 2015
RETURN m.title AS Movie,
[(dir:Person)-[:DIRECTED]->(m) | dir.name] AS Directors,
[(actor:Person)-[:ACTED_IN]->(m) | actor.name] AS Actors
The behavior of pattern comprehension is similar to using OPTIONAL MATCH and for this particular query, the elapsed time is slightly reduced, but the number of db hits remains the same.
A benefit of pattern comprehension is that you don’t need to have a collect() stage and you avoid potential cartesian products.
Filtering during pattern comprehension
You can specify a filtering criteria for the pattern:
MATCH (a:Person {name: 'Tom Hanks'})
RETURN [(a)--(b:Movie)
WHERE b.title CONTAINS "Toy" | b.title ]
AS Movies
Adding more context to the list returned
You can even provide more context to the elements of the list returned where we add the year to the movie title for each element of the list:
MATCH (a:Person {name: 'Tom Hanks'})
RETURN [(a)--(b:Movie)
WHERE b.title CONTAINS "Toy" | b.title + ": " + b.year]
AS Movies
Check your understanding
1. Pattern comprehension syntax
Suppose you have a query that retrieves Movie nodes:
MATCH (m:Movie)
What must you use to return a list of actor names for the movie using pattern comprehension: (select all that apply)
-
❏ MATCH (m)-[ACTED_IN]-(a:Person) RETURN collect(a.name)
-
✓ RETURN [ (m)-[ACTED_IN]-(a:Person)| a.name]
-
❏ RETURN [ (m)-[ACTED_IN]-(a:Person)| collect(a.name)]
-
❏ RETURN [ (m)-[ACTED_IN]-(a:Person)| list(a.name)]
Hint
Using pattern comprehension, you need not explicitly collect the data
Solution
You use RETURN [ (m)-[ACTED_IN]-(a:Person)| a.name]
to return the list per movie.
2. Returning the Genres for Movies
We want to return the Genres for each movie that Tom Hanks acted in. Use the dropdown below complete the query to use pattern comprehension.
Once you have selected your option, click the Check Results query button to continue.
MATCH (a:Person {name: 'Tom Hanks'})-[:ACTED_IN]-(m:Movie)
RETURN
m.title AS Movie,
/*select:[(m)--(g:Genre) | g.name] AS Genres*/
-
❏
[(m)--(g:Genre) | collect(g.name)] AS Genres
-
❏
[m--(g:Genre) | g.name] AS Genres
-
✓
[(m)--(g:Genre) | g.name] AS Genres
-
❏
collect(g.name) AS Genres
Hint
You must use "[]" to return the list. You must specify a valid pattern in the pattern comprehension part returned. You must separate the pattern and the value added to the list with the "|" character. You must specify a value to be added to the list based upon the variables in the pattern.
Solution
The correct answer is`[(m)--(g:Genre) | g.name] AS Genres`.
Summary
In this lesson, you reviewed and learned more about aggregating data pattern comprehension your Cypher queries. In the next Challenge, you will create a query to aggregate using pattern comprehension.