Using Pattern Comprehension

This video was recorded using an earlier version of the sandbox (Neo4j 4.x). You are using a Neo4j 5.4 sandbox for this course. You will see some differences in the PROFILE results for db hits and elapsed time in Neo4j 5.4.

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:

cypher
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:

cypher
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:

cypher
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:

cypher
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:

Partial
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.

cypher
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.