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)