UNWIND
Introduction
The UNWIND clause in Cypher is used to expand a list into a sequence of individual elements. It transforms a list value into rows. For each element in the list, UNWIND creates a new row with the variable bound to that list element. If the expression evaluates to null, or an empty list, UNWIND will produce a single row with a null value for the variable, or no rows at all, respectively, depending on the specific database implementation. In AGE, UNWIND will produce a single row with a null value for the variable when the expression is null, and no rows when the list is empty.
UNWIND is particularly useful when dealing with list properties of nodes or relationships, or when you need to iterate over a collection of values within your query.
Examples
Data Setup
For some of these examples, we will be using this reference data:
SELECT * FROM cypher('cypher_unwind', $$
CREATE (n {name: 'node1', a: [1, 2, 3]}),
(m {name: 'node2', a: [4, 5, 6]}),
(o {name: 'node3', a: [7, 8, 9]}),
(n)-[:KNOWS]->(m),
(m)-[:KNOWS]->(o)
$$) as (i agtype);
Basic UNWIND with a List of Integers
This example demonstrates the most basic use of UNWIND, where a literal list of integers is expanded into individual rows.
SQL Query
SELECT * FROM cypher('cypher_unwind', $$
UNWIND [1, 2, 3] AS i
RETURN i
$$) as (i agtype);
Output
i
---
1
2
3
(3 rows)
UNWIND with Node Properties
This example shows how to use UNWIND to process list properties of nodes and uses the reference data.
SQL Query
SELECT * FROM cypher('cypher_unwind', $$
MATCH (n)
WITH n.a AS a
UNWIND a AS i
RETURN *
$$) as (i agtype, j agtype);
Output
i | j
-----------+---
[1, 2, 3] | 1
[1, 2, 3] | 2
[1, 2, 3] | 3
[4, 5, 6] | 4
[4, 5, 6] | 5
[4, 5, 6] | 6
[7, 8, 9] | 7
[7, 8, 9] | 8
[7, 8, 9] | 9
(9 rows)
Nested UNWIND
UNWIND can be nested to flatten nested lists.
SQL Query
SELECT * FROM cypher('cypher_unwind', $$
WITH [[1, 2], [3, 4], 5] AS nested
UNWIND nested AS x
UNWIND x AS y
RETURN y
$$) as (i agtype);
Output
i
---
1
2
3
4
5
(5 rows)
UNWIND with Path Functions: nodes()
UNWIND can be used with path functions like nodes() to process vertices in a path.
SQL Query
SELECT * FROM cypher('cypher_unwind', $$
MATCH p=(n)-[:KNOWS]->(m)
UNWIND nodes(p) as node
RETURN node
$$) as (i agtype);
Output
i
-----------------------------------------------------------------------------------------------
{"id": 281474976710657, "label": "", "properties": {"a": [1, 2, 3], "name": "node1"}}::vertex
{"id": 281474976710658, "label": "", "properties": {"a": [4, 5, 6], "name": "node2"}}::vertex
{"id": 281474976710658, "label": "", "properties": {"a": [4, 5, 6], "name": "node2"}}::vertex
{"id": 281474976710659, "label": "", "properties": {"a": [7, 8, 9], "name": "node3"}}::vertex
(4 rows)
UNWIND with Path Functions: relationships()
Similarly, UNWIND can be used with relationships() to process relationships in a path.
SQL Query
SELECT * FROM cypher('cypher_unwind', $$
MATCH p=(n)-[:KNOWS]->(m)
UNWIND relationships(p) as relation
RETURN relation
$$) as (i agtype);
Output
i
---------------------------------------------------------------------------------------------------------------------------
{"id": 844424930131969, "label": "KNOWS", "end_id": 281474976710658, "start_id": 281474976710657, "properties": {}}::edge
{"id": 844424930131970, "label": "KNOWS", "end_id": 281474976710659, "start_id": 281474976710658, "properties": {}}::edge
(2 rows)
UNWIND with Path Functions: relationships() and paths
This example demonstrates unwinding relationships from paths, where the path itself is also unwound.
SQL Query
SELECT * FROM cypher('cypher_unwind', $$
MATCH p=({name:'node1'})-[e:KNOWS*]->({name:'node3'})
UNWIND [p] as path
UNWIND relationships(path) as edge
RETURN edge
$$) as (i agtype);
Output
i
---------------------------------------------------------------------------------------------------------------------------
{"id": 844424930131969, "label": "KNOWS", "end_id": 281474976710658, "start_id": 281474976710657, "properties": {}}::edge
{"id": 844424930131970, "label": "KNOWS", "end_id": 281474976710659, "start_id": 281474976710658, "properties": {}}::edge
(2 rows)
UNWIND in SET Clause
UNWIND can be combined with the SET clause to update properties based on unwound values.
SQL Query
SELECT * FROM cypher('cypher_unwind', $$
MATCH p=(n)-[:KNOWS]->(m)
UNWIND nodes(p) as node
SET node.type = 'vertex'
$$) as (i agtype);
Output
i
---
(0 rows)
UNWIND with NULL
This example shows how UNWIND handles a NULL value. This behavior is important to understand when dealing with optional list properties or situations where the expression might evaluate to NULL.
SQL Query
SELECT * FROM cypher('cypher_unwind', $$
UNWIND NULL as i
RETURN i
$$) as (i agtype);
Output
i
---
(1 row)