9.7. Lists

Cypher has good support for lists.

Lists in general

A literal list is created by using brackets and separating the elements in the list with commas.

Query 

RETURN [0,1,2,3,4,5,6,7,8,9] AS list

Result

list
1 row

[0,1,2,3,4,5,6,7,8,9]

Try this query live create (_0:`Movie` {`name`:"WallStreet", `title`:"Wall Street", `year`:1987}) create (_1:`Movie` {`name`:"ApocalypseNow", `title`:"Apocalypse Now", `year`:1979}) create (_2:`Person` {`name`:"Charlie Sheen", `realName`:"Carlos Irwin Estévez"}) create (_3:`Person` {`name`:"Martin Sheen"}) create (_4:`Movie` {`name`:"RedDawn", `title`:"Red Dawn", `year`:1984}) create (_2)-[:`ACTED_IN`]->(_1) create (_2)-[:`ACTED_IN`]->(_4) create (_2)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_1) ; RETURN [0,1,2,3,4,5,6,7,8,9] AS list

In our examples, we’ll use the range function. It gives you a list containing all numbers between given start and end numbers. Range is inclusive in both ends.

To access individual elements in the list, we use the square brackets again. This will extract from the start index and up to but not including the end index.

Query 

RETURN range(0,10)[3]

Result

range(0,10)[3]
1 row

3

Try this query live create (_0:`Movie` {`name`:"WallStreet", `title`:"Wall Street", `year`:1987}) create (_1:`Movie` {`name`:"ApocalypseNow", `title`:"Apocalypse Now", `year`:1979}) create (_2:`Person` {`name`:"Charlie Sheen", `realName`:"Carlos Irwin Estévez"}) create (_3:`Person` {`name`:"Martin Sheen"}) create (_4:`Movie` {`name`:"RedDawn", `title`:"Red Dawn", `year`:1984}) create (_2)-[:`ACTED_IN`]->(_1) create (_2)-[:`ACTED_IN`]->(_4) create (_2)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_1) ; RETURN range(0,10)[3]

You can also use negative numbers, to start from the end of the list instead.

Query 

RETURN range(0,10)[-3]

Result

range(0,10)[-3]
1 row

8

Try this query live create (_0:`Movie` {`name`:"WallStreet", `title`:"Wall Street", `year`:1987}) create (_1:`Movie` {`name`:"ApocalypseNow", `title`:"Apocalypse Now", `year`:1979}) create (_2:`Person` {`name`:"Charlie Sheen", `realName`:"Carlos Irwin Estévez"}) create (_3:`Person` {`name`:"Martin Sheen"}) create (_4:`Movie` {`name`:"RedDawn", `title`:"Red Dawn", `year`:1984}) create (_2)-[:`ACTED_IN`]->(_1) create (_2)-[:`ACTED_IN`]->(_4) create (_2)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_1) ; RETURN range(0,10)[-3]

Finally, you can use ranges inside the brackets to return ranges of the list.

Query 

RETURN range(0,10)[0..3]

Result

range(0,10)[0..3]
1 row

[0,1,2]

Try this query live create (_0:`Movie` {`name`:"WallStreet", `title`:"Wall Street", `year`:1987}) create (_1:`Movie` {`name`:"ApocalypseNow", `title`:"Apocalypse Now", `year`:1979}) create (_2:`Person` {`name`:"Charlie Sheen", `realName`:"Carlos Irwin Estévez"}) create (_3:`Person` {`name`:"Martin Sheen"}) create (_4:`Movie` {`name`:"RedDawn", `title`:"Red Dawn", `year`:1984}) create (_2)-[:`ACTED_IN`]->(_1) create (_2)-[:`ACTED_IN`]->(_4) create (_2)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_1) ; RETURN range(0,10)[0..3]

Query 

RETURN range(0,10)[0..-5]

Result

range(0,10)[0..-5]
1 row

[0,1,2,3,4,5]

Try this query live create (_0:`Movie` {`name`:"WallStreet", `title`:"Wall Street", `year`:1987}) create (_1:`Movie` {`name`:"ApocalypseNow", `title`:"Apocalypse Now", `year`:1979}) create (_2:`Person` {`name`:"Charlie Sheen", `realName`:"Carlos Irwin Estévez"}) create (_3:`Person` {`name`:"Martin Sheen"}) create (_4:`Movie` {`name`:"RedDawn", `title`:"Red Dawn", `year`:1984}) create (_2)-[:`ACTED_IN`]->(_1) create (_2)-[:`ACTED_IN`]->(_4) create (_2)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_1) ; RETURN range(0,10)[0..-5]

Query 

RETURN range(0,10)[-5..]

Result

range(0,10)[-5..]
1 row

[6,7,8,9,10]

Try this query live create (_0:`Movie` {`name`:"WallStreet", `title`:"Wall Street", `year`:1987}) create (_1:`Movie` {`name`:"ApocalypseNow", `title`:"Apocalypse Now", `year`:1979}) create (_2:`Person` {`name`:"Charlie Sheen", `realName`:"Carlos Irwin Estévez"}) create (_3:`Person` {`name`:"Martin Sheen"}) create (_4:`Movie` {`name`:"RedDawn", `title`:"Red Dawn", `year`:1984}) create (_2)-[:`ACTED_IN`]->(_1) create (_2)-[:`ACTED_IN`]->(_4) create (_2)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_1) ; RETURN range(0,10)[-5..]

Query 

RETURN range(0,10)[..4]

Result

range(0,10)[..4]
1 row

[0,1,2,3]

Try this query live create (_0:`Movie` {`name`:"WallStreet", `title`:"Wall Street", `year`:1987}) create (_1:`Movie` {`name`:"ApocalypseNow", `title`:"Apocalypse Now", `year`:1979}) create (_2:`Person` {`name`:"Charlie Sheen", `realName`:"Carlos Irwin Estévez"}) create (_3:`Person` {`name`:"Martin Sheen"}) create (_4:`Movie` {`name`:"RedDawn", `title`:"Red Dawn", `year`:1984}) create (_2)-[:`ACTED_IN`]->(_1) create (_2)-[:`ACTED_IN`]->(_4) create (_2)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_1) ; RETURN range(0,10)[..4]

[Note]Note

Out-of-bound slices are simply truncated, but out-of-bound single elements return NULL.

Query 

RETURN range(0,10)[15]

Result

range(0,10)[15]
1 row

<null>

Try this query live create (_0:`Movie` {`name`:"WallStreet", `title`:"Wall Street", `year`:1987}) create (_1:`Movie` {`name`:"ApocalypseNow", `title`:"Apocalypse Now", `year`:1979}) create (_2:`Person` {`name`:"Charlie Sheen", `realName`:"Carlos Irwin Estévez"}) create (_3:`Person` {`name`:"Martin Sheen"}) create (_4:`Movie` {`name`:"RedDawn", `title`:"Red Dawn", `year`:1984}) create (_2)-[:`ACTED_IN`]->(_1) create (_2)-[:`ACTED_IN`]->(_4) create (_2)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_1) ; RETURN range(0,10)[15]

Query 

RETURN range(0,10)[5..15]

Result

range(0,10)[5..15]
1 row

[5,6,7,8,9,10]

Try this query live create (_0:`Movie` {`name`:"WallStreet", `title`:"Wall Street", `year`:1987}) create (_1:`Movie` {`name`:"ApocalypseNow", `title`:"Apocalypse Now", `year`:1979}) create (_2:`Person` {`name`:"Charlie Sheen", `realName`:"Carlos Irwin Estévez"}) create (_3:`Person` {`name`:"Martin Sheen"}) create (_4:`Movie` {`name`:"RedDawn", `title`:"Red Dawn", `year`:1984}) create (_2)-[:`ACTED_IN`]->(_1) create (_2)-[:`ACTED_IN`]->(_4) create (_2)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_1) ; RETURN range(0,10)[5..15]

You can get the size of a list like this:

Query 

RETURN size(range(0,10)[0..3])

Result

size(range(0,10)[0..3])
1 row

3

Try this query live create (_0:`Movie` {`name`:"WallStreet", `title`:"Wall Street", `year`:1987}) create (_1:`Movie` {`name`:"ApocalypseNow", `title`:"Apocalypse Now", `year`:1979}) create (_2:`Person` {`name`:"Charlie Sheen", `realName`:"Carlos Irwin Estévez"}) create (_3:`Person` {`name`:"Martin Sheen"}) create (_4:`Movie` {`name`:"RedDawn", `title`:"Red Dawn", `year`:1984}) create (_2)-[:`ACTED_IN`]->(_1) create (_2)-[:`ACTED_IN`]->(_4) create (_2)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_1) ; RETURN size(range(0,10)[0..3])

List comprehension

List comprehension is a syntactic construct available in Cypher for creating a list based on existing lists. It follows the form of the mathematical set-builder notation (set comprehension) instead of the use of map and filter functions.

Query 

RETURN [x IN range(0,10) WHERE x % 2 = 0 | x^3] AS result

Result

result
1 row

[0.0,8.0,64.0,216.0,512.0,1000.0]

Try this query live create (_0:`Movie` {`name`:"WallStreet", `title`:"Wall Street", `year`:1987}) create (_1:`Movie` {`name`:"ApocalypseNow", `title`:"Apocalypse Now", `year`:1979}) create (_2:`Person` {`name`:"Charlie Sheen", `realName`:"Carlos Irwin Estévez"}) create (_3:`Person` {`name`:"Martin Sheen"}) create (_4:`Movie` {`name`:"RedDawn", `title`:"Red Dawn", `year`:1984}) create (_2)-[:`ACTED_IN`]->(_1) create (_2)-[:`ACTED_IN`]->(_4) create (_2)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_1) ; RETURN [x IN range(0,10) WHERE x % 2 = 0 | x^3] AS result

Either the WHERE part, or the expression, can be omitted, if you only want to filter or map respectively.

Query 

RETURN [x IN range(0,10) WHERE x % 2 = 0] AS result

Result

result
1 row

[0,2,4,6,8,10]

Try this query live create (_0:`Movie` {`name`:"WallStreet", `title`:"Wall Street", `year`:1987}) create (_1:`Movie` {`name`:"ApocalypseNow", `title`:"Apocalypse Now", `year`:1979}) create (_2:`Person` {`name`:"Charlie Sheen", `realName`:"Carlos Irwin Estévez"}) create (_3:`Person` {`name`:"Martin Sheen"}) create (_4:`Movie` {`name`:"RedDawn", `title`:"Red Dawn", `year`:1984}) create (_2)-[:`ACTED_IN`]->(_1) create (_2)-[:`ACTED_IN`]->(_4) create (_2)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_1) ; RETURN [x IN range(0,10) WHERE x % 2 = 0] AS result

Query 

RETURN [x IN range(0,10)| x^3] AS result

Result

result
1 row

[0.0,1.0,8.0,27.0,64.0,125.0,216.0,343.0,512.0,729.0,1000.0]

Try this query live create (_0:`Movie` {`name`:"WallStreet", `title`:"Wall Street", `year`:1987}) create (_1:`Movie` {`name`:"ApocalypseNow", `title`:"Apocalypse Now", `year`:1979}) create (_2:`Person` {`name`:"Charlie Sheen", `realName`:"Carlos Irwin Estévez"}) create (_3:`Person` {`name`:"Martin Sheen"}) create (_4:`Movie` {`name`:"RedDawn", `title`:"Red Dawn", `year`:1984}) create (_2)-[:`ACTED_IN`]->(_1) create (_2)-[:`ACTED_IN`]->(_4) create (_2)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_1) ; RETURN [x IN range(0,10)| x^3] AS result

Literal maps

From Cypher, you can also construct maps. Through REST you will get JSON objects; in Java they will be java.util.Map<String,Object>.

Query 

RETURN { key : "Value", listKey: [{ inner: "Map1" }, { inner: "Map2" }]}

Result

{ key : "Value", listKey: [ { inner: "Map1" }, { inner: "Map2" } ] }
1 row

{key -> "Value", listKey -> [{inner -> "Map1"},{inner -> "Map2"}]}

Try this query live create (_0:`Movie` {`name`:"WallStreet", `title`:"Wall Street", `year`:1987}) create (_1:`Movie` {`name`:"ApocalypseNow", `title`:"Apocalypse Now", `year`:1979}) create (_2:`Person` {`name`:"Charlie Sheen", `realName`:"Carlos Irwin Estévez"}) create (_3:`Person` {`name`:"Martin Sheen"}) create (_4:`Movie` {`name`:"RedDawn", `title`:"Red Dawn", `year`:1984}) create (_2)-[:`ACTED_IN`]->(_1) create (_2)-[:`ACTED_IN`]->(_4) create (_2)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_1) ; RETURN { key : "Value", listKey: [{ inner: "Map1" }, { inner: "Map2" }]}

Map Projection

Cypher supports a concept called "map projections". It allows for easily constructing map projections from nodes, relationships and other map values.

A map projection begins with the variable bound to the graph entity to be projected from, and contains a body of coma separated map elements, enclosed by { and }.

map_variable { map_element, [, ...n] }

A map element projects one or more key value pair to the map projection. There exists four different types of map projection elements:

  • Property selector - Projects the property name as the key, and the value from the map_variable as the value for the projection.
  • Literal entry - This is a key value pair, with the value being arbitrary expression key : <expression>.
  • Variable selector - Projects an variable, with the variable name as the key, and the value the variable is pointing to as the value of the projection. It’s syntax is just the variable.
  • All-properties selector - projects all key value pair from the map_variable value.

Note that if the map_variable points to a null value, the whole map projection will evaluate to null.

Examples of map projections

Find Charlie Sheen and return data about him and the movies he has acted in. This example shows an example of map projection with a literal entry, which in turn also uses map projection inside the aggregating collect().

Query 

MATCH (actor:Person { name:'Charlie Sheen' })-[:ACTED_IN]->(movie:Movie)
RETURN actor { .name, .realName, movies: collect(movie { .title, .year })}

Result

actor
1 row

{name -> "Charlie Sheen", realName -> "Carlos Irwin Estévez", movies -> [{title -> "Apocalypse Now", year -> 1979},{title -> "Red Dawn", year -> 1984},{title -> "Wall Street", year -> 1987}]

Try this query live create (_0:`Movie` {`name`:"WallStreet", `title`:"Wall Street", `year`:1987}) create (_1:`Movie` {`name`:"ApocalypseNow", `title`:"Apocalypse Now", `year`:1979}) create (_2:`Person` {`name`:"Charlie Sheen", `realName`:"Carlos Irwin Estévez"}) create (_3:`Person` {`name`:"Martin Sheen"}) create (_4:`Movie` {`name`:"RedDawn", `title`:"Red Dawn", `year`:1984}) create (_2)-[:`ACTED_IN`]->(_1) create (_2)-[:`ACTED_IN`]->(_4) create (_2)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_1) ; MATCH (actor:Person { name:'Charlie Sheen' })-[:ACTED_IN]->(movie:Movie) RETURN actor { .name, .realName, movies: collect(movie { .title, .year })}

Find all persons that have acted in movies, and show number for each. This example introduces an variable with the count, and uses an variable selector to project the value.

Query 

MATCH (actor:Person)-[:ACTED_IN]->(movie:Movie)
WITH actor, count(movie) AS nrOfMovies
RETURN actor { .name, nrOfMovies }

Result

actor
2 rows

{name -> "Charlie Sheen", nrOfMovies -> 3}

{name -> "Martin Sheen", nrOfMovies -> 2}

Try this query live create (_0:`Movie` {`name`:"WallStreet", `title`:"Wall Street", `year`:1987}) create (_1:`Movie` {`name`:"ApocalypseNow", `title`:"Apocalypse Now", `year`:1979}) create (_2:`Person` {`name`:"Charlie Sheen", `realName`:"Carlos Irwin Estévez"}) create (_3:`Person` {`name`:"Martin Sheen"}) create (_4:`Movie` {`name`:"RedDawn", `title`:"Red Dawn", `year`:1984}) create (_2)-[:`ACTED_IN`]->(_1) create (_2)-[:`ACTED_IN`]->(_4) create (_2)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_1) ; MATCH (actor:Person)-[:ACTED_IN]->(movie:Movie) WITH actor, count(movie) AS nrOfMovies RETURN actor { .name, nrOfMovies }

Again, focusing on Charlie Sheen, this time returning all properties from the node. Here we use an all-properties selector to project all the node properties, and additionally, explicitly project the property age. Since this property does not exist on the node, a null value is projected instead.

Query 

MATCH (actor:Person { name:'Charlie Sheen' })
RETURN actor { .*, .age }

Result

actor
1 row

{realName -> "Carlos Irwin Estévez", name -> "Charlie Sheen", age -> <null>

Try this query live create (_0:`Movie` {`name`:"WallStreet", `title`:"Wall Street", `year`:1987}) create (_1:`Movie` {`name`:"ApocalypseNow", `title`:"Apocalypse Now", `year`:1979}) create (_2:`Person` {`name`:"Charlie Sheen", `realName`:"Carlos Irwin Estévez"}) create (_3:`Person` {`name`:"Martin Sheen"}) create (_4:`Movie` {`name`:"RedDawn", `title`:"Red Dawn", `year`:1984}) create (_2)-[:`ACTED_IN`]->(_1) create (_2)-[:`ACTED_IN`]->(_4) create (_2)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_0) create (_3)-[:`ACTED_IN`]->(_1) ; MATCH (actor:Person { name:'Charlie Sheen' }) RETURN actor { .*, .age }