diff --git a/modules/ROOT/content-nav.adoc b/modules/ROOT/content-nav.adoc index b1bf4a547..223b28d68 100644 --- a/modules/ROOT/content-nav.adoc +++ b/modules/ROOT/content-nav.adoc @@ -77,6 +77,7 @@ ** xref:expressions/string-operators.adoc[] ** xref:expressions/temporal-operators.adoc[] ** xref:expressions/list-expressions.adoc[] +** xref:expressions/map-expressions.adoc[] ** xref:expressions/conditional-expressions.adoc[] * xref:functions/index.adoc[] diff --git a/modules/ROOT/pages/expressions/index.adoc b/modules/ROOT/pages/expressions/index.adoc index f2b0fc0ec..5a05fe28f 100644 --- a/modules/ROOT/pages/expressions/index.adoc +++ b/modules/ROOT/pages/expressions/index.adoc @@ -15,5 +15,6 @@ For details and examples of specific expressions, see the following sections: * xref:expressions/string-operators.adoc[]: `+`, `||` * xref:expressions/temporal-operators.adoc[]: `+`, `-`, `*`, `/` * xref:expressions/list-expressions.adoc[]: information about list concatenation operators (`||`, `+`), list element access, list slicing, and list as well as pattern comprehensions. +* xref:expressions/map-expressions.adoc[]: information about map operators (`.`, `[]`) and map projection. * xref:expressions/conditional-expressions.adoc[] diff --git a/modules/ROOT/pages/expressions/map-expressions.adoc b/modules/ROOT/pages/expressions/map-expressions.adoc new file mode 100644 index 000000000..c0953eee1 --- /dev/null +++ b/modules/ROOT/pages/expressions/map-expressions.adoc @@ -0,0 +1,446 @@ += Map expressions +:description: Information about Cypher's map expressions. +:table-caption!: + +Map expressions allow you to manipulate and query xref:values-and-types/maps.adoc[`MAP`] values in Cypher. + +[NOTE] +The xref:functions/list.adoc#functions-keys[`keys()`] function can be used to return a `LIST` of all the keys in a `MAP`. + +[[example-graph]] +== Example graph + +The following graph is used for the examples below: + +image::values_and_types_maps_graph.svg[width="700",role="middle"] + +To recreate the graph, run the following query against an empty Neo4j database: + +[source, cypher, role=test-setup] +---- +CREATE (keanu:Person {name: 'Keanu Reeves', nationality: 'Canadian'}), + (carrieAnne:Person {name: 'Carrie-Anne Moss'}), + (theMatrixRevolutions:Movie {title: 'The Matrix Revolutions', released: 2003}), + (theMatrixReloaded:Movie {title: 'The Matrix Reloaded', released: 2003}), + (theMatrix:Movie {title: 'The Matrix', released: 1999}), + (theDevilsAdvocate:Movie {title: 'The Devils Advocate', released: 1997}), + (theMatrixResurrections:Movie {title: 'The Matrix Resurrections', released: 2021}), + + (keanu)-[:ACTED_IN]->(theMatrix), + (keanu)-[:ACTED_IN]->(theMatrixRevolutions), + (keanu)-[:ACTED_IN]->(theMatrixReloaded), + (keanu)-[:ACTED_IN]->(theMatrixResurrections), + (keanu)-[:ACTED_IN]->(theDevilsAdvocate), + + (carrieAnne)-[:ACTED_IN]->(theMatrix), + (carrieAnne)-[:ACTED_IN]->(theMatrixRevolutions), + (carrieAnne)-[:ACTED_IN]->(theMatrixReloaded), + (carrieAnne)-[:ACTED_IN]->(theMatrixResurrections) +---- + +[[map-operators]] +== Map operators + +Cypher contains two map operators: + +* Statically access a value by key: dot operator (`.`). +* Dynamically access a value by key: subscript operator (`[]`). + +[[static-map-access]] +=== Statically access a `MAP` value + +`MAP` values can be accessed statically by specifying a key after the `.` operator. + +.Static `MAP` value access +[source, cypher] +---- +WITH {a: 10, b: 20, c: 30} AS map +RETURN map.a AS firstValue, + map.c AS lastValue +---- + +.Result +[role="queryresult",options="header,footer",cols="2*(m:Movie) +RETURN p.name AS actor, collect(m{.title, .released}) AS movies +---- + +.Result +[role="queryresult",options="header,footer",cols="2*(movie:Movie) +WITH keanu, collect(movie) AS movies +RETURN keanu {.name, totalMovies: size(movies)} AS keanuDetails +---- + +.Result +[role="queryresult",options="header,footer",cols="1*(movie:Movie) +WITH actor, count(movie) AS totalMovies +RETURN actor{totalMovies, .name} AS nameAndMovies +---- + +.Result +[role="queryresult",options="header,footer",cols="1* Predicates -> List operators]. diff --git a/modules/ROOT/pages/values-and-types/maps.adoc b/modules/ROOT/pages/values-and-types/maps.adoc index a3e005a04..9cd982c7d 100644 --- a/modules/ROOT/pages/values-and-types/maps.adoc +++ b/modules/ROOT/pages/values-and-types/maps.adoc @@ -4,12 +4,11 @@ = Maps Cypher supports the construction of maps. -This section first discusses literal maps and then moves on to map projection. [NOTE] ==== -Information regarding property access operators such as `.` and `[]` can be found xref::syntax/operators.adoc#query-operators-map[here]. -The behavior of the `[]` operator with respect to `null` is detailed xref::values-and-types/working-with-null.adoc#cypher-null-bracket-operator[here]. +For information about the property access operators `.` and `[]`, see xref:expressions/map-expressions#map-operators[Map expressions -> Map operators]. + +For information about how the `[]` operator behaves with respect to `null`, see xref::values-and-types/working-with-null.adoc#cypher-null-bracket-operator[Working with `null` -> The `[\]` operator and `null`]. ==== @@ -36,137 +35,3 @@ RETURN {key: 'Value', listKey: [{inner: 'Map1'}, {inner: 'Map2'}]} AS map |=== -[[cypher-map-projection]] -== Map projection - -Cypher supports map projections, which allows for the construction of 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 comma-separated map elements, enclosed by `{` and `}`. - -.Map projection -[source, syntax] ----- -map_variable {map_element, [, ...n]} ----- - -A map element projects one or more key-value pairs to the map projection. -There exist 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 an arbitrary expression `key: `. -* Variable selector - Projects a variable, with the variable name as the key, and the value the variable is pointing to as the value of the projection. -Its syntax is just the variable. -* All-properties selector - projects all key-value pairs from the `map_variable` value. - -The following conditions apply: - -* If the `map_variable` points to a `null` value, the whole map projection will evaluate to `null`. -* The key names in a map must be of type `STRING`. - - -[[cypher-map-projection-examples]] -=== Example graph - -The following graph is used for the examples below: - -image::values_and_types_maps_graph.svg[] - -To recreate the graph, run the following query against an empty Neo4j database: - -[source, cypher, role=test-setup] ----- -CREATE - (keanu:Person {name: 'Keanu Reeves', nationality: 'Canadian'}), - (carrieAnne:Person {name: 'Carrie-Anne Moss'}), - (theMatrixRevolutions:Movie {title: 'The Matrix Revolutions', released: 2003}), - (theMatrixReloaded:Movie {title: 'The Matrix Reloaded', released: 2003}), - (theMatrix:Movie {title: 'The Matrix', released: 1999}), - (theDevilsAdvocate:Movie {title: 'The Devils Advocate', released: 1997}), - (theMatrixResurrections:Movie {title: 'The Matrix Resurrections', released: 2021}), - (keanu)-[:ACTED_IN]->(theMatrix), - (keanu)-[:ACTED_IN]->(theMatrixRevolutions), - (keanu)-[:ACTED_IN]->(theMatrixReloaded), - (keanu)-[:ACTED_IN]->(theMatrixResurrections), - (keanu)-[:ACTED_IN]->(theDevilsAdvocate), - (carrieAnne)-[:ACTED_IN]->(theMatrix), - (carrieAnne)-[:ACTED_IN]->(theMatrixRevolutions), - (carrieAnne)-[:ACTED_IN]->(theMatrixReloaded), - (carrieAnne)-[:ACTED_IN]->(theMatrixResurrections) ----- - -=== Examples - -The below query finds the `Keanu Reeves` node and the movies he has acted in. -It is an example of a map projection with a literal entry, which in turn also uses map projection inside the aggregating xref:functions/aggregating.adoc#functions-collect[collect()] function. - -.Query -[source, cypher, indent=0] ----- -MATCH (keanu:Person {name: 'Keanu Reeves'})-[:ACTED_IN]->(movie:Movie) -WITH keanu, collect(movie{.title, .released}) AS movies -RETURN keanu{.name, movies: movies} ----- - -.Result -[role="queryresult",options="header,footer",cols="1*(movie:Movie) -WITH actor, count(movie) AS numberOfMovies -RETURN actor{.name, numberOfMovies} ----- - -.Result -[role="queryresult",options="header,footer",cols="1*