From 017ef7bfbd021740369bcb45e7bf8d73a8e54895 Mon Sep 17 00:00:00 2001 From: Mark Dixon <1756429+mnd999@users.noreply.github.com> Date: Tue, 15 Oct 2024 07:49:29 +0100 Subject: [PATCH 01/77] Deprecate `existingDataSeedInstance` option to CREATE DATABASE (#1047) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace with new option `existingDataSeedServer` Documenting https://github.com/neo-technology/neo4j/pull/27123 --------- Co-authored-by: Jens Pryce-Åklundh <112686610+JPryce-Aklundh@users.noreply.github.com> --- ...ions-additions-removals-compatibility.adoc | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index 2aef91c68..d5442a8ab 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -16,6 +16,45 @@ New features are added to the language continuously, and occasionally, some feat This section lists all of the features that have been removed, deprecated, added, or extended in different Cypher versions. Replacement syntax for deprecated and removed features are also indicated. +[[cypher-deprecations-additions-removals-5.25]] +== Neo4j 5.25 + +=== Deprecated features + +[cols="2", options="header"] +|=== +| Feature +| Details + +a| +label:functionality[] +label:deprecated[] +[source, cypher, role="noheader"] +---- +CREATE DATABASE db OPTIONS { existingDataSeedInstance: ... } +---- +| The `CREATE DATABASE` option `existingDataSeedInstance` has been deprecated and replaced with the option link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/standard-databases/create-database/#manage-databases-create-database-options[`existingDataSeedServer`]. The functionality is unchanged. +|=== + +=== New features + +[cols="2", options="header"] +|=== +| Feature +| Details + +a| +label:functionality[] +label:new[] +[source, cypher, role="noheader"] +---- +CREATE DATABASE db OPTIONS { existingDataSeedServer: ... } +---- +| The option link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/standard-databases/create-database/#manage-databases-create-database-options[`existingDataSeedServer`] has been added to `CREATE DATABASE`. The functionality is the same as the deprecated option `existingDataSeedServer`, which this replaces. +|=== + + + [[cypher-deprecations-additions-removals-5.24]] == Neo4j 5.24 From 6a9effcffe09e13d6ed89ddc56df5144eb23e003 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Tue, 15 Oct 2024 10:11:38 +0200 Subject: [PATCH 02/77] clarify point.distance function (#1064) --- .../pages/appendix/gql-conformance/additional-cypher.adoc | 4 +++- modules/ROOT/pages/functions/index.adoc | 4 +++- modules/ROOT/pages/functions/spatial.adoc | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/modules/ROOT/pages/appendix/gql-conformance/additional-cypher.adoc b/modules/ROOT/pages/appendix/gql-conformance/additional-cypher.adoc index 2a33e5d4c..166c50e57 100644 --- a/modules/ROOT/pages/appendix/gql-conformance/additional-cypher.adoc +++ b/modules/ROOT/pages/appendix/gql-conformance/additional-cypher.adoc @@ -301,7 +301,9 @@ Either the pattern already exists, or it needs to be created. | Returns a 2D or 3D point object, given two or respectively three coordinate values in the Cartesian coordinate system or WGS 84 geographic coordinate system. | xref:functions/spatial.adoc#functions-point-distance[`point.distance()`] -| Returns a `FLOAT` representing the geodesic distance between any two points in the same CRS. +| Returns a `FLOAT` representing the distance between any two points in the same CRS. +If the points are in the WGS 84 CRS, the function returns the geodesic distance (i.e., the shortest path along the curved surface of the Earth). +If the points are in a Cartesian CRS, the function returns the Euclidean distance (i.e., the shortest straight-line distance in a flat, planar space). | xref:functions/spatial.adoc#functions-point-withinBBox[`point.withinBBox()`] | Returns true if the provided point is within the bounding box defined by the two provided points. diff --git a/modules/ROOT/pages/functions/index.adoc b/modules/ROOT/pages/functions/index.adoc index 315171f5c..d10e1c1ef 100644 --- a/modules/ROOT/pages/functions/index.adoc +++ b/modules/ROOT/pages/functions/index.adoc @@ -573,7 +573,9 @@ These functions are used to specify 2D or 3D points in a geographic or cartesian 1.1+| xref::functions/spatial.adoc#functions-distance[`point.distance()`] | `point.distance(from :: POINT, to :: POINT) :: FLOAT` -| Returns a `FLOAT` representing the geodesic distance between any two points in the same CRS. +| Returns a `FLOAT` representing the distance between any two points in the same CRS. +If the points are in the WGS 84 CRS, the function returns the geodesic distance (i.e., the shortest path along the curved surface of the Earth). +If the points are in a Cartesian CRS, the function returns the Euclidean distance (i.e., the shortest straight-line distance in a flat, planar space). 1.1+| xref::functions/spatial.adoc#functions-withinBBox[`point.withinBBox()`] | `point.withinBBox(point :: POINT, lowerLeft :: POINT, upperRight :: POINT) :: BOOLEAN` diff --git a/modules/ROOT/pages/functions/spatial.adoc b/modules/ROOT/pages/functions/spatial.adoc index 83686c2d0..e83511990 100644 --- a/modules/ROOT/pages/functions/spatial.adoc +++ b/modules/ROOT/pages/functions/spatial.adoc @@ -250,7 +250,9 @@ If `null` is provided as the argument, `null` is returned. .Details |=== | *Syntax* 3+| `point.distance(from, to)` -| *Description* 3+| Returns a `FLOAT` representing the geodesic distance between any two points in the same CRS. +| *Description* 3+| Returns a `FLOAT` representing the distance between any two points in the same CRS. +If the points are in the WGS 84 CRS, the function returns the geodesic distance (i.e., the shortest path along the curved surface of the Earth). +If the points are in a Cartesian CRS, the function returns the Euclidean distance (i.e., the shortest straight-line distance in a flat, planar space). .3+| *Arguments* | *Name* | *Type* | *Description* | `from` | `POINT` | A start point. | `to` | `POINT` | An end point in the same CRS as the start point. From 94c56476d3d33d6ca99e24ecfa4ecc009d50dc02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Tue, 15 Oct 2024 10:23:45 +0200 Subject: [PATCH 03/77] fix functions table (Logarithmic was missing) (#1065) --- modules/ROOT/pages/functions/index.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ROOT/pages/functions/index.adoc b/modules/ROOT/pages/functions/index.adoc index d10e1c1ef..bb324d520 100644 --- a/modules/ROOT/pages/functions/index.adoc +++ b/modules/ROOT/pages/functions/index.adoc @@ -208,7 +208,7 @@ LOAD CSV functions can be used to get information about the file that is process [[header-query-functions-logarithmic]] -**xref::functions/mathematical-logarithmic.adoc[Logarithmic functions]** +== Logarithmic functions These functions all operate on numerical expressions only, and will return an error if used on any other values. From c1774e0f3f0054f2a16f774aabe44a761db9c445 Mon Sep 17 00:00:00 2001 From: Gem Lamont <106068376+gem-neo4j@users.noreply.github.com> Date: Fri, 18 Oct 2024 09:32:09 +0200 Subject: [PATCH 04/77] Document unicode changes for Cypher 25 (#1059) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit One unicode was turned into whitespace, the others were just removed as valid in non-delimited identifiers --------- Co-authored-by: Jens Pryce-Åklundh <112686610+JPryce-Aklundh@users.noreply.github.com> --- ...ions-additions-removals-compatibility.adoc | 53 ++++++++++++++++++- modules/ROOT/pages/syntax/parsing.adoc | 1 + 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index d5442a8ab..0f00ed6b5 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -16,6 +16,57 @@ New features are added to the language continuously, and occasionally, some feat This section lists all of the features that have been removed, deprecated, added, or extended in different Cypher versions. Replacement syntax for deprecated and removed features are also indicated. +[[cypher-deprecations-additions-removals-2025.01]] +== Neo4j 2025.01 + +=== Removed features + +[cols="2", options="header"] +|=== +| Feature +| Details + +a| +label:functionality[] +label:removed[] +[source, cypher, role="noheader"] +---- +RETURN 1 as my\u0085identifier +---- +a| +The Unicode character \`\u0085` has been removed for unescaped identifiers and is now considered a whitespace character. +To continue using it, escape the identifier by adding backticks around it. +This applies to all unescaped identifiers in Cypher, such as label expressions, properties, variable names, or parameters. +In the given example, the quoted identifier would be \`my�identifier`. + +a| +label:functionality[] +label:removed[] +[source, cypher, role="noheader"] +---- +RETURN 1 as my$Identifier +---- +a| +The character with the Unicode representation \`\u0024` has been removed for unescaped identifiers. To continue using it, escape the identifier by adding backticks around the identifier. +This applies to all unescaped identifiers in Cypher, such as label expressions, properties, variable names, or parameters. In the given example, the quoted identifier would be \`my$identifier`. + +The following Unicode Characters are removed in identifiers: +'\u0000', '\u0001', '\u0002', '\u0003', '\u0004', '\u0005', '\u0006', '\u0007', +'\u0008', '\u000E', '\u000F', '\u0010', '\u0011', '\u0012', '\u0013', '\u0014', +'\u0015', '\u0016', '\u0017', '\u0018', '\u0019', '\u001A', '\u001B', '\u007F', +'\u0080', '\u0081', '\u0082', '\u0083', '\u0084', '\u0086', '\u0087', '\u0088', +'\u0089', '\u008A', '\u008B', '\u008C', '\u008D', '\u008E', '\u008F', '\u0090', +'\u0091', '\u0092', '\u0093', '\u0094', '\u0095', '\u0096', '\u0097', '\u0098', +'\u0099', '\u009A', '\u009B', '\u009C', '\u009D', '\u009E', '\u009F', '\u0024', +'\u00A2', '\u00A3', '\u00A4', '\u00A5', '\u00AD', '\u0600', '\u0601', '\u0602', +'\u0603', '\u0604', '\u0605', '\u061C', '\u06DD', '\u070F', '\u08E2', '\u180E', +'\u200B', '\u200C', '\u200D', '\u200E', '\u200F', '\u202A', '\u202B', '\u202C', +'\u202D', '\u202E', '\u2060', '\u2061', '\u2062', '\u2063', '\u2064', '\u2066', +'\u2067', '\u2068', '\u2069', '\u206A', '\u206B', '\u206C', '\u206D', '\u206E', +'\u206F', '\u2E2F', '\uFEFF', '\uFFF9', '\uFFFA', '\uFFFB' +|=== + + [[cypher-deprecations-additions-removals-5.25]] == Neo4j 5.25 @@ -25,7 +76,6 @@ Replacement syntax for deprecated and removed features are also indicated. |=== | Feature | Details - a| label:functionality[] label:deprecated[] @@ -55,6 +105,7 @@ CREATE DATABASE db OPTIONS { existingDataSeedServer: ... } +>>>>>>> cypher-25 [[cypher-deprecations-additions-removals-5.24]] == Neo4j 5.24 diff --git a/modules/ROOT/pages/syntax/parsing.adoc b/modules/ROOT/pages/syntax/parsing.adoc index 54db83bde..93cab6d53 100644 --- a/modules/ROOT/pages/syntax/parsing.adoc +++ b/modules/ROOT/pages/syntax/parsing.adoc @@ -56,6 +56,7 @@ The following unicode characters are considered as whitespace: | Group separator | `\u001D` | Record separator | `\u001E` | Unit separator | `\u001F` +| Next Line | `\u0085` |=== It is possible to have multiple whitespace characters in a row, and will have the same effect as using a single whitespace. From 3a35e3a260195236dfa3070fb5ffc5e694d14367 Mon Sep 17 00:00:00 2001 From: Gem Lamont <106068376+gem-neo4j@users.noreply.github.com> Date: Fri, 18 Oct 2024 09:48:11 +0200 Subject: [PATCH 05/77] Document change in behaviour for db.schema.nodeTypeProperties() and db.schema.relTypeProperties() (#1062) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The column propertyTypes is a LIST, currently it outputs runtime types, but in Cypher25 it outputs Cypher Types. --------- Co-authored-by: Jens Pryce-Åklundh <112686610+JPryce-Aklundh@users.noreply.github.com> --- ...ions-additions-removals-compatibility.adoc | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index 0f00ed6b5..5047cd1bb 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -67,6 +67,28 @@ The following Unicode Characters are removed in identifiers: |=== +=== Updated features + +[cols="2", options="header"] +|=== +| Feature +| Details + +a| +label:functionality[] +label:updated[] +[source, cypher, role="noheader"] +---- +CALL db.schema.nodeTypeProperties() YIELD propertyTypes RETURN propertyTypes; +CALL db.schema.relTypeProperties() YIELD propertyTypes RETURN propertyTypes; +---- +a| +The column `propertyTypes` returned by the procedures link:{neo4j-docs-base-uri}/operations-manual/{page-version}/procedures/#procedure_db_schema_nodetypeproperties[`db.schema.nodeTypeProperties()`] and link:{neo4j-docs-base-uri}/operations-manual/{page-version}/procedures/#procedure_db_schema_reltypeproperties[`db.schema.relTypeProperties()`] previously returned a list of strings representing the potential Java types for a given property. +It now returns a list of strings representing the possible Cypher Types the given property has. +For all available Cypher types, see the section on xref::values-and-types/property-structural-constructed.adoc#types-synonyms[types and their synonyms]. +|=== + + [[cypher-deprecations-additions-removals-5.25]] == Neo4j 5.25 @@ -104,8 +126,6 @@ CREATE DATABASE db OPTIONS { existingDataSeedServer: ... } |=== - ->>>>>>> cypher-25 [[cypher-deprecations-additions-removals-5.24]] == Neo4j 5.24 From 901afa54c538231dbb5d58bf637f6a48b2736f6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Fri, 18 Oct 2024 10:56:22 +0200 Subject: [PATCH 06/77] Cherry-pick new Constraints section to Cypher 25 (#1067) Co-authored-by: Therese Magnusson --- modules/ROOT/content-nav.adoc | 2 +- .../gql-conformance/additional-cypher.adoc | 28 +- modules/ROOT/pages/clauses/load-csv.adoc | 6 +- modules/ROOT/pages/clauses/merge.adoc | 4 +- .../ROOT/pages/clauses/optional-match.adoc | 2 +- modules/ROOT/pages/constraints/examples.adoc | 2939 ----------------- modules/ROOT/pages/constraints/index.adoc | 126 +- .../constraints/managing-constraints.adoc | 1804 ++++++++++ modules/ROOT/pages/constraints/syntax.adoc | 309 +- ...ions-additions-removals-compatibility.adoc | 12 +- .../managing-indexes.adoc | 12 +- .../using-indexes.adoc | 18 +- .../ROOT/pages/introduction/cypher-neo4j.adoc | 14 +- .../pages/introduction/cypher-overview.adoc | 2 +- .../ROOT/pages/patterns/shortest-paths.adoc | 2 +- .../property-structural-constructed.adoc | 4 +- 16 files changed, 1956 insertions(+), 3328 deletions(-) delete mode 100644 modules/ROOT/pages/constraints/examples.adoc create mode 100644 modules/ROOT/pages/constraints/managing-constraints.adoc diff --git a/modules/ROOT/content-nav.adoc b/modules/ROOT/content-nav.adoc index 2eabb7c4c..35d451b4d 100644 --- a/modules/ROOT/content-nav.adoc +++ b/modules/ROOT/content-nav.adoc @@ -94,8 +94,8 @@ ** xref:indexes/syntax.adoc[] * xref:constraints/index.adoc[] +** xref:constraints/managing-constraints.adoc[] ** xref:constraints/syntax.adoc[] -** xref:constraints/examples.adoc[] * xref:planning-and-tuning/index.adoc[] ** xref:planning-and-tuning/execution-plans.adoc[] diff --git a/modules/ROOT/pages/appendix/gql-conformance/additional-cypher.adoc b/modules/ROOT/pages/appendix/gql-conformance/additional-cypher.adoc index 166c50e57..46134dceb 100644 --- a/modules/ROOT/pages/appendix/gql-conformance/additional-cypher.adoc +++ b/modules/ROOT/pages/appendix/gql-conformance/additional-cypher.adoc @@ -509,29 +509,17 @@ GQL supports `GRAPH TYPES` as a way of constraining a graph schema, but does not | Cypher feature | Description -| xref:constraints/examples.adoc#constraints-examples-node-uniqueness[Node property uniqueness constraints] -| Ensures that certain nodes have a set of specified properties whose combined value is unique when all properties exist on the node +| xref:constraints/managing-constraints.adoc#create-property-uniqueness-constraints[Property uniqueness constraints] +| Ensures that the combined property values are unique for all nodes with a specific label or all relationships with a specific type. -| xref:constraints/examples.adoc#constraints-examples-relationship-uniqueness[Relationship property uniqueness constraints] -| Ensures that certain relationships have a set of specified properties whose combined value is unique when all properties exist on the relationship. +| xref:constraints/managing-constraints.adoc#create-property-existence-constraints[Property existence constraints] +| Ensures that a property exists either for all nodes with a specific label or for all relationships with a specific type. -| xref:constraints/examples.adoc#constraints-examples-node-property-existence[Node property existence constraints] -| Ensures that certain nodes have a specified property. +| xref:constraints/managing-constraints.adoc#create-property-type-constraints[Property type constraints] +| Ensures that a property has the required property type for all nodes with a specific label or for all relationships with a specific type. -| xref:constraints/examples.adoc#constraints-examples-relationship-property-existence[Relationship property existence constraints] -| Ensures that certain relationships have a specified property. - -| xref:constraints/examples.adoc#constraints-examples-node-property-type[Node property type constraints] -| Ensures that certain nodes have a property of the required property type when the property exists on the node. - -| xref:constraints/examples.adoc#constraints-examples-relationship-property-type[Relationship property type constraints] -| Ensures that certain relationships have a property of the required property type when the property exists on the relationship. - -| xref:constraints/examples.adoc#constraints-examples-node-key[Node key constraints] -| Ensures that certain nodes have a set of specified properties whose combined value is unique and all properties in the set are present. - -| xref:constraints/examples.adoc#constraints-examples-relationship-key[Relationship key constraints] -| Ensures that certain relationships have a set of defined properties whose combined value is unique. It also ensures that all properties in the set are present. +| xref:constraints/managing-constraints.adoc#create-key-constraints[Key constraints] +| Ensures that all properties exist and that the combined property values are unique for all nodes with a specific label or all relationships with a specific type. |=== diff --git a/modules/ROOT/pages/clauses/load-csv.adoc b/modules/ROOT/pages/clauses/load-csv.adoc index de374e266..fa5804f1b 100644 --- a/modules/ROOT/pages/clauses/load-csv.adoc +++ b/modules/ROOT/pages/clauses/load-csv.adoc @@ -601,12 +601,12 @@ For more `STRING` manipulation functions, see xref:functions/string.adoc[String == Recommendations -=== Create uniqueness constraints +=== Create property uniqueness constraints -Always create uniqueness xref:constraints/index.adoc[constraints] prior to importing data, to avoid duplicates or colliding entities. +Always create xref:constraints/managing-constraints.adoc#create-property-uniqueness-constraints[property uniqueness constraints] prior to importing data, to avoid duplicates or colliding entities. If the source file contains duplicated data and the right constraints are in place, Cypher raises an error. -.Create xref:constraints/examples.adoc#constraints-examples-node-uniqueness[node property uniqueness constraints] on person ID +.Create a node property uniqueness constraints on person ID ==== .persons.csv diff --git a/modules/ROOT/pages/clauses/merge.adoc b/modules/ROOT/pages/clauses/merge.adoc index 1b93c98d3..669409c6a 100644 --- a/modules/ROOT/pages/clauses/merge.adoc +++ b/modules/ROOT/pages/clauses/merge.adoc @@ -25,7 +25,7 @@ If partial matches are needed, this can be accomplished by splitting a pattern i [NOTE] ==== Under concurrent updates, `MERGE` only guarantees the existence of the `MERGE` pattern, but not uniqueness. -To guarantee uniqueness of nodes with certain properties, a xref::constraints/index.adoc[property uniqueness constraint] should be used. +To guarantee uniqueness of nodes with certain properties, a xref:constraints/managing-constraints.adoc#create-property-uniqueness-constraints[property uniqueness constraint] should be used. See xref::clauses/merge.adoc#query-merge-using-unique-constraints[Using property uniqueness constraints with `MERGE`]. ==== @@ -511,7 +511,7 @@ This is in contrast to the example shown above in xref::clauses/merge.adoc#merge [[query-merge-using-unique-constraints]] == Using node property uniqueness constraints with `MERGE` -Cypher prevents getting conflicting results from `MERGE` when using patterns that involve property uniqueness constraints. +Cypher prevents getting conflicting results from `MERGE` when using patterns that involve xref:constraints/managing-constraints.adoc#create-property-uniqueness-constraints[property uniqueness constraints]. In this case, there must be at most one node that matches that pattern. For example, given two property node uniqueness constraints on `:Person(id)` and `:Person(ssn)`, a query such as `MERGE (n:Person {id: 12, ssn: 437})` will fail, if there are two different nodes (one with `id` 12 and one with `ssn` 437), or if there is only one node with only one of the properties. diff --git a/modules/ROOT/pages/clauses/optional-match.adoc b/modules/ROOT/pages/clauses/optional-match.adoc index ac59b099c..44e2dba20 100644 --- a/modules/ROOT/pages/clauses/optional-match.adoc +++ b/modules/ROOT/pages/clauses/optional-match.adoc @@ -54,7 +54,7 @@ For example, the matching variables from one `MATCH` clause will provide the con However, there are two important differences between Neo4j and SQL which helps to explain `OPTIONAL MATCH` further. . While it is both possible and advised to enforce partial schemas using indexes and constraints, Neo4j offers a greater degree of schema flexibility than a relational database. -Nodes and relationships in a Neo4j database do not have to have a specific property set to them because other nodes or relationships in the same graph have that property (unless there is a existence constraint created on the specific property). +Nodes and relationships in a Neo4j database do not have to have a specific property set to them because other nodes or relationships in the same graph have that property (unless there is a xref:constraints/managing-constraints.adoc#create-property-existence-constraints[property existence constraint] created on the specific property). . Queries in Cypher are run as pipelines. If a clause returns no results, it will effectively end the query as subsequent clauses will have no data to execute upon. diff --git a/modules/ROOT/pages/constraints/examples.adoc b/modules/ROOT/pages/constraints/examples.adoc deleted file mode 100644 index e84df4470..000000000 --- a/modules/ROOT/pages/constraints/examples.adoc +++ /dev/null @@ -1,2939 +0,0 @@ -:description: Examples of how to manage constraints used for ensuring data integrity. -:page-toclevels: 1 -include::https://raw.githubusercontent.com/neo4j-graphacademy/courses/main/asciidoc/courses/cypher-indexes-constraints/ad.adoc[] - -[[constraints-examples]] -= Examples - -This page contains examples of how to manage constraints used for ensuring data integrity. - -[[constraints-examples-node-uniqueness]] -== Node property uniqueness constraints - -A node property uniqueness constraint ensures that certain nodes have a set of specified properties whose combined value is unique when all properties exist on the node. - -* xref::constraints/examples.adoc#constraints-create-a-node-uniqueness-constraint[] -* xref::constraints/examples.adoc#constraints-create-a-node-uniqueness-constraint-by-param[] -* xref::constraints/examples.adoc#constraints-create-a-node-uniqueness-constraint-if-not-exist[] -* xref::constraints/examples.adoc#constraints-create-a-node-uniqueness-constraint-with-index-provider[] -* xref::constraints/examples.adoc#constraints-create-an-already-existing-node-uniqueness-constraint[] -* xref::constraints/examples.adoc#constraints-create-a-node-uniqueness-constraint-on-same-schema-as-existing-index[] -* xref::constraints/examples.adoc#constraints-create-a-node-that-complies-with-a-uniqueness-constraint[] -* xref::constraints/examples.adoc#constraints-create-a-node-that-violates-a-uniqueness-constraint[] -* xref::constraints/examples.adoc#constraints-fail-to-create-a-uniqueness-constraint-due-to-conflicting-nodes[] - - -[[constraints-create-a-node-uniqueness-constraint]] -=== Create a node property uniqueness constraint - -When creating a property uniqueness constraint, it is recommended to provide a constraint name. - - -.+CREATE CONSTRAINT+ -====== - -.Query -[source, cypher] ----- -CREATE CONSTRAINT book_isbn -FOR (book:Book) REQUIRE book.isbn IS UNIQUE ----- - -.Result -[queryresult] ----- -Added 1 constraint. ----- - -[NOTE] -==== -The detailed statistics view currently says `Unique constraints added: 1`. -It will be updated to say `Node property uniqueness constraints added: 1` in Neo4j 6.0. -==== - -====== - -[role=label--new-5.16] -[[constraints-create-a-node-uniqueness-constraint-by-param]] -=== Create a node property uniqueness constraint using a parameter - -The constraint name can also be given as a parameter. - -.+CREATE CONSTRAINT+ -====== - -.Parameters -[source, parameters] ----- -{ - "name": "node_uniqueness_param" -} ----- - -.Query -[source, cypher] ----- -CREATE CONSTRAINT $name -FOR (book:Book) REQUIRE book.prop1 IS UNIQUE ----- - -.Result -[queryresult] ----- -Added 1 constraint. ----- - -[NOTE] -==== -The detailed statistics view currently says `Unique constraints added: 1`. -It will be updated to say `Node property uniqueness constraints added: 1` in Neo4j 6.0. -==== - -====== - - -[[constraints-create-a-node-uniqueness-constraint-if-not-exist]] -=== Handling existing constraints when creating a constraint - -Creating an already existing constraint will fail. -To avoid such an error, `IF NOT EXISTS` can be added to the `CREATE` command. -This will ensure that no error is thrown and that no constraint is created if any other constraint with the given name, or another node property uniqueness constraint on the same schema, already exists. -As of Neo4j 5.17, an informational notification is instead returned showing the existing constraint which blocks the creation. - -.+CREATE CONSTRAINT+ -====== - -.Query -[source, cypher] ----- -CREATE CONSTRAINT book_isbn2 IF NOT EXISTS -FOR (book:Book) REQUIRE book.isbn2 IS UNIQUE ----- - -Assuming no constraint with the given name or other node property uniqueness constraint on the same schema already exists, the query will return: - -.Result -[queryresult] ----- -Added 1 constraint. ----- - -[NOTE] -==== -The detailed statistics view currently says `Unique constraints added: 1`. -It will be updated to say `Node property uniqueness constraints added: 1` in Neo4j 6.0. -==== - -====== - - -[[constraints-create-a-node-uniqueness-constraint-with-index-provider]] -=== Specifying an index provider when creating a constraint - -To create a property uniqueness constraint with a specific index provider for the backing index, the `OPTIONS` clause is used. - -The index type of the backing index is set with the `indexProvider` option. - -The only valid value for the index provider is: - -* `range-1.0` label:default[] - -// Only one valid value exists for the index provider in Neo4j 5.0 - - -.+CREATE CONSTRAINT+ -====== - -.Query -[source, cypher] ----- -CREATE CONSTRAINT constraint_with_options -FOR (book:Book) REQUIRE (book.prop1, book.prop2) IS UNIQUE -OPTIONS { - indexProvider: 'range-1.0' -} ----- - -.Result -[queryresult] ----- -Added 1 constraint. ----- - -[NOTE] -==== -The detailed statistics view currently says `Unique constraints added: 1`. -It will be updated to say `Node property uniqueness constraints added: 1` in Neo4j 6.0. -==== - -====== - -There is no valid index configuration values for the constraint-backing range indexes. - - -[[constraints-create-an-already-existing-node-uniqueness-constraint]] -=== Creating an already existing constraint will fail - - -.+CREATE CONSTRAINT+ -====== - -Create a property uniqueness constraint on the property `published` on nodes with the `Book` label, when that constraint already exists: - -//// -[source, cypher, role=test-setup] ----- -CREATE CONSTRAINT preExisting_book_published FOR (book:Book) REQUIRE book.published IS UNIQUE ----- -//// - -.Query -[source, cypher, role=test-fail] ----- -CREATE CONSTRAINT book_published FOR (book:Book) REQUIRE book.published IS UNIQUE ----- - -In this case, the constraint cannot be created because it already exists. - -.Error message -[source, error] ----- -Constraint already exists: -Constraint( id=4, name='preExisting_book_published', type='UNIQUENESS', schema=(:Book {published}), ownedIndex=3 ) ----- - -[NOTE] -==== -The constraint type will be updated to say `NODE PROPERTY UNIQUENESS` in Neo4j 6.0. -==== - -====== - - -[[constraints-create-a-node-uniqueness-constraint-on-same-schema-as-existing-index]] -=== Creating a constraint on the same schema as an existing index will fail - - -.+CREATE CONSTRAINT+ -====== - -Create a property uniqueness constraint on the property `wordCount` on nodes with the `Book` label, when an index already exists on that label and property combination: - -//// -[source, cypher, role=test-setup] ----- -CREATE INDEX preExisting_book_word_count FOR (book:Book) ON (book.wordCount) ----- -//// - -.Query -[source, cypher, role=test-fail] ----- -CREATE CONSTRAINT book_word_count FOR (book:Book) REQUIRE book.wordCount IS UNIQUE ----- - -In this case, the constraint cannot be created because there already exists an index covering that schema. - -.Error message -[source, error] ----- -There already exists an index (:Book {wordCount}). -A constraint cannot be created until the index has been dropped. ----- - -====== - - -[[constraints-create-a-node-that-complies-with-a-uniqueness-constraint]] -=== Creating a node that complies with an existing constraint - - -.+CREATE NODE+ -====== - -Create a `Book` node with an `isbn` that is not already in the graph: - -.Query -[source, cypher] ----- -CREATE (book:Book {isbn: '1449356265', title: 'Graph Databases'}) ----- - -.Result -[queryresult] ----- -Added 1 label, created 1 node, set 2 properties ----- - -====== - - -[[constraints-create-a-node-that-violates-a-uniqueness-constraint]] -=== Creating a node that violates an existing constraint will fail - - -.+CREATE NODE+ -====== - -Create a `Book` node with an `isbn` that is already used in the graph: - -.Query -[source, cypher, role=test-fail] ----- -CREATE (book:Book {isbn: '1449356265', title: 'Graph Databases'}) ----- - -In this case, the node is not created because the `isbn` property is in conflict with an existing constraint. - -.Error message -[source, error] ----- -Node(0) already exists with label `Book` and property `isbn` = '1449356265' ----- - -====== - - -[[constraints-fail-to-create-a-uniqueness-constraint-due-to-conflicting-nodes]] -=== Creating a constraint when there exist conflicting nodes will fail - - -.+CREATE CONSTRAINT+ -====== - -Create a property uniqueness constraint on the property `title` on nodes with the `Book` label, when there are two nodes with the same `title`: - -//// -[source, cypher, role=test-setup] ----- -CREATE (book:Book {isbn: '9780393972832', title: 'Moby Dick'}); -CREATE (book:Book {isbn: '9780763630188', title: 'Moby Dick'}) ----- -//// - -.Query -[source, cypher, role=test-fail] ----- -CREATE CONSTRAINT book_title FOR (book:Book) REQUIRE book.title IS UNIQUE ----- - -In this case, the constraint cannot be created because it is in conflict with the existing graph. -Either use xref:indexes/search-performance-indexes/managing-indexes.adoc[] instead, or remove/correct the offending nodes and then re-apply the constraint. - -.Error message -[source, error] ----- -Unable to create Constraint( name='book_title', type='UNIQUENESS', schema=(:Book {title}) ): -Both Node(0) and Node(1) have the label `Book` and property `title` = 'Moby Dick' ----- - -[NOTE] -==== -The constraint type will be updated to say `NODE PROPERTY UNIQUENESS` in Neo4j 6.0. -==== - -====== - -The constraint creation fails on the first offending nodes that are found. -This does not guarantee that there are no other offending nodes in the graph. -Therefore, all the data should be checked and cleaned up before re-attempting the constraint creation. - -This is an example `MATCH` query to find all offending nodes with the non-unique property values for the constraint above: - -.Query -[source, cypher] ----- -MATCH (book1:Book), (book2:Book) -WHERE book1.title = book2.title AND NOT book1 = book2 -RETURN book1, book2 ----- - -[role=label--new-5.7] -[[constraints-examples-relationship-uniqueness]] -== Relationship property uniqueness constraints - -A relationship property uniqueness constraint ensures that certain relationships have a set of specified properties whose combined value is unique when all properties exist on the relationship. - -* xref::constraints/examples.adoc#constraints-create-a-relationship-uniqueness-constraints[] -* xref::constraints/examples.adoc#constraints-create-a-relationship-uniqueness-constraints-by-param[] -* xref::constraints/examples.adoc#constraints-create-a-relationship-uniqueness-constraints-if-not-exist[] -* xref::constraints/examples.adoc#constraints-create-a-relationship-uniqueness-constraints-with-index-provider[] -* xref::constraints/examples.adoc#constraints-create-an-already-existing-relationship-uniqueness-constraint[] -* xref::constraints/examples.adoc#constraints-create-a-relationship-uniqueness-constraint-on-same-schema-as-existing-index[] -* xref::constraints/examples.adoc#constraints-create-a-relationship-that-complies-with-a-uniqueness-constraint[] -* xref::constraints/examples.adoc#constraints-create-a-relationship-that-violates-a-uniqueness-constraint[] -* xref::constraints/examples.adoc#constraints-fail-to-create-a-uniqueness-constraint-due-to-conflicting-relationships[] - - -[[constraints-create-a-relationship-uniqueness-constraints]] -=== Create a relationship property uniqueness constraint - -When creating a property uniqueness constraint, it is recommended to provide a constraint name. - - -.+CREATE CONSTRAINT+ -====== - -.Query -[source, cypher] ----- -CREATE CONSTRAINT sequels -FOR ()-[sequel:SEQUEL_OF]-() REQUIRE (sequel.order, sequel.seriesTitle) IS UNIQUE ----- - -.Result -[queryresult] ----- -Added 1 constraint. ----- - -[NOTE] -==== -The detailed statistics view currently says `Relationship uniqueness constraints added: 1`. -It will be updated to say `Relationship property uniqueness constraints added: 1` in Neo4j 6.0. -==== - -====== - - -[role=label--new-5.16] -[[constraints-create-a-relationship-uniqueness-constraints-by-param]] -=== Create a relationship property uniqueness constraint using a parameter - -The constraint name can also be given as a parameter. - -.+CREATE CONSTRAINT+ -====== - -.Parameters -[source, parameters] ----- -{ - "name": "rel_uniqueness_param" -} ----- - -.Query -[source, cypher] ----- -CREATE CONSTRAINT $name -FOR ()-[sequel:SEQUEL_OF]-() REQUIRE (sequel.prop1) IS UNIQUE ----- - -.Result -[queryresult] ----- -Added 1 constraint. ----- - -[NOTE] -==== -The detailed statistics view currently says `Relationship uniqueness constraints added: 1`. -It will be updated to say `Relationship property uniqueness constraints added: 1` in Neo4j 6.0. -==== - -====== - - -[[constraints-create-a-relationship-uniqueness-constraints-if-not-exist]] -=== Handling existing constraints when creating a constraint - -Creating an already existing constraint will fail. -To avoid such an error, `IF NOT EXISTS` can be added to the `CREATE` command. -This will ensure that no error is thrown and that no constraint is created if any other constraint with the given name, or another relationship property uniqueness constraint on the same schema, already exists. -As of Neo4j 5.17, an informational notification is instead returned showing the existing constraint which blocks the creation. - -.+CREATE CONSTRAINT+ -====== - -.Query -[source, cypher] ----- -CREATE CONSTRAINT sequels IF NOT EXISTS -FOR ()-[sequel:SEQUEL_OF]-() REQUIRE (sequel.order) IS UNIQUE ----- - -Assuming a constraint with the name `sequels` already exists: - -.Result -[queryresult] ----- -(no changes, no records) ----- - -.Notification -[source] ----- -`CREATE CONSTRAINT sequels IF NOT EXISTS FOR ()-[e:SEQUEL_OF]-() REQUIRE (e.order) IS UNIQUE` has no effect. -`CONSTRAINT sequels FOR ()-[e:SEQUEL_OF]-() REQUIRE (e.order, e.seriesTitle) IS UNIQUE` already exists. ----- - -[NOTE] -==== -The detailed statistics view currently says `Relationship uniqueness constraints added: 1`. -It will be updated to say `Relationship property uniqueness constraints added: 1` in Neo4j 6.0. -==== - -====== - - -[[constraints-create-a-relationship-uniqueness-constraints-with-index-provider]] -=== Specifying an index provider when creating a constraint - -To create a property uniqueness constraint with a specific index provider for the backing index, the `OPTIONS` clause is used. - -The index type of the backing index is set with the `indexProvider` option. - -The only valid value for the index provider is: - -* `range-1.0` label:default[] - -// Only one valid value exists for the index provider in Neo4j 5.0 - - -.+CREATE CONSTRAINT+ -====== - -.Query -[source, cypher] ----- -CREATE CONSTRAINT rel_constraint_with_options -FOR ()-[sequel:SEQUEL_OF]-() REQUIRE (sequel.order, sequel.seriesTitle, sequel.number) IS UNIQUE -OPTIONS { - indexProvider: 'range-1.0' -} ----- - -.Result -[queryresult] ----- -Added 1 constraint. ----- - -[NOTE] -==== -The detailed statistics view currently says `Relationship uniqueness constraints added: 1`. -It will be updated to say `Relationship property uniqueness constraints added: 1` in Neo4j 6.0. -==== - -====== - -There are no valid index configuration values for the constraint-backing range indexes. - - -[[constraints-create-an-already-existing-relationship-uniqueness-constraint]] -=== Creating an already existing constraint will fail - - -.+CREATE CONSTRAINT+ -====== - -Create a property uniqueness constraint on the properties `order` and `seriesTitle` on relationships with the `SEQUEL_OF` relationship type, when that constraint already exists: - -.Query -[source, cypher, role=test-fail] ----- -CREATE CONSTRAINT sequel_order_seriestitle FOR ()-[sequel:SEQUEL_OF]-() REQUIRE (sequel.order, sequel.seriesTitle) IS UNIQUE ----- - -In this case, the constraint cannot be created because it already exists. - -.Error message -[source, error] ----- -Constraint already exists: -Constraint( id=13, name='sequels', type='RELATIONSHIP UNIQUENESS', schema=()-[:SEQUEL_OF {order, seriesTitle}]-(), ownedIndex=12 ) ----- - -[NOTE] -==== -The constraint type will be updated to say `RELATIONSHIP PROPERTY UNIQUENESS` in Neo4j 6.0. -==== - -====== - - -[[constraints-create-a-relationship-uniqueness-constraint-on-same-schema-as-existing-index]] -=== Creating a constraint on the same schema as an existing index will fail - - -.+CREATE CONSTRAINT+ -====== - -Create a property uniqueness constraint on the property `order` on relationships with the `SEQUEL_OF` relationship type, when an index already exists on that relationship type and property combination: - -//// -[source, cypher, role=test-setup] ----- -CREATE INDEX sequel_order FOR ()-[sequel:SEQUEL_OF]-() ON (sequel.order) ----- -//// - -.Query -[source, cypher, role=test-fail] ----- -CREATE CONSTRAINT sequel_series_title FOR ()-[sequel:SEQUEL_OF]-() REQUIRE (sequel.order) IS UNIQUE ----- - -In this case, the constraint cannot be created because there already exists an index covering that schema. - -.Error message -[source, error] ----- -There already exists an index ()-[:SEQUEL_OF {order}]-(). -A constraint cannot be created until the index has been dropped. ----- - -====== - - -[[constraints-create-a-relationship-that-complies-with-a-uniqueness-constraint]] -=== Creating a relationship that complies with an existing constraint - - -.+CREATE RELATIONSHIP+ -====== - -Create a `SEQUEL_OF` relationship with values for properties `order` and `seriesTitle` that are not already in the graph: - -.Query -[source, cypher] ----- -CREATE (:Book {title: 'Spirit Walker'})-[:SEQUEL_OF {order: 1, seriesTitle: 'Chronicles of Ancient Darkness'}]->(:Book {title: 'Wolf Brother'}) ----- - -.Result -[queryresult] ----- -Added 2 labels, created 2 nodes, set 4 properties, created 1 relationship. ----- - -====== - - -[[constraints-create-a-relationship-that-violates-a-uniqueness-constraint]] -=== Creating a relationship that violates an existing constraint will fail - - -.+CREATE RELATIONSHIP+ -====== - -Create a `SEQUEL_OF` relationship with values for properties `order` and `seriesTitle` that are already used in the graph: - -.Query -[source, cypher, role=test-fail] ----- -MATCH (wolfBrother:Book {title: 'Wolf Brother'}), (spiritWalker:Book {title: 'Spirit Walker'}) -CREATE (spiritWalker)-[:SEQUEL_OF {order: 1, seriesTitle: 'Chronicles of Ancient Darkness'}]->(wolfBrother) ----- - -In this case, the relationship is not created because the combination of the `order` and `seriesTitle` properties are in conflict with an existing constraint. - -.Error message -[source, error] ----- -Relationship(0) already exists with type `SEQUEL_OF` and properties `order` = 1, `seriesTitle` = 'Chronicles of Ancient Darkness' ----- - -====== - - -[[constraints-fail-to-create-a-uniqueness-constraint-due-to-conflicting-relationships]] -=== Creating a constraint when there exist conflicting relationships will fail - - -.+CREATE CONSTRAINT+ -====== - -Create a property uniqueness constraint on the property `seriesTitle` on relationships with the `SEQUEL_OF` relationship type, when two relationships with the same `seriesTitle` already exist: - -//// -[source, cypher, role=test-setup] ----- -MATCH (spiritWalker:Book {title: 'Spirit Walker'}) -CREATE (:Book {title: 'Soul Eater'})-[:SEQUEL_OF {order: 2, seriesTitle: 'Chronicles of Ancient Darkness'}]->(spiritWalker) ----- -//// - -.Query -[source, cypher, role=test-fail] ----- -CREATE CONSTRAINT series_title FOR ()-[sequel:SEQUEL_OF]-() REQUIRE (sequel.seriesTitle) IS UNIQUE ----- - -In this case, the constraint cannot be created because it is in conflict with the existing graph. -Either use xref:indexes/search-performance-indexes/managing-indexes.adoc[] instead, or remove/correct the offending relationships and then re-apply the constraint. - -.Error message -[source, error] ----- -Unable to create Constraint( name='series_title', type='RELATIONSHIP UNIQUENESS', schema=()-[:SEQUEL_OF {seriesTitle}]-() ): -Both Relationship(0) and Relationship(1) have the type `SEQUEL_OF` and property `seriesTitle` = 'Chronicles of Ancient Darkness' ----- - -====== - -The constraint creation fails on the first offending relationships that are found. -This does not guarantee that there are no other offending relationships in the graph. -Therefore, all the data should be checked and cleaned up before re-attempting the constraint creation. - -This is an example `MATCH` query to find all offending relationships for the constraint above: - -.Query -[source, cypher] ----- -MATCH ()-[knows1:KNOWS]->(), ()-[knows2:KNOWS]->() -WHERE knows1.level = knows2.level AND NOT knows1 = knows2 -RETURN knows1, knows2 ----- - - -[role=label--enterprise-edition] -[[constraints-examples-node-property-existence]] -== Node property existence constraints - -A node property existence constraint ensures that certain nodes have a specified property. - -* xref::constraints/examples.adoc#constraints-create-a-node-property-existence-constraint[] -* xref::constraints/examples.adoc#constraints-create-a-node-property-existence-constraint-by-param[] -* xref::constraints/examples.adoc#constraints-create-a-node-property-existence-constraint-if-not-exist[] -* xref::constraints/examples.adoc#constraints-create-an-already-existing-node-property-existence-constraint[] -* xref::constraints/examples.adoc#constraints-create-a-node-that-complies-with-a-property-existence-constraint[] -* xref::constraints/examples.adoc#constraints-create-a-node-that-violates-a-property-existence-constraint[] -* xref::constraints/examples.adoc#constraints-removing-an-existence-constrained-node-property[] -* xref::constraints/examples.adoc#constraints-fail-to-create-a-property-existence-constraint-due-to-existing-node[] - - -[[constraints-create-a-node-property-existence-constraint]] -=== Create a node property existence constraint - -When creating a node property existence constraint, it is recommended to provide a constraint name. - - -.+CREATE CONSTRAINT+ -====== - -.Query -[source, cypher] ----- -CREATE CONSTRAINT author_name -FOR (author:Author) REQUIRE author.name IS NOT NULL ----- - -.Result -[queryresult] ----- -Added 1 constraint. ----- - -[NOTE] -==== -The detailed statistics view for property existence constraints, `Property existence constraints added: 1`, will be split between nodes and relationships in Neo4j 6.0. -For the node property existence constraints, they will say `Node property existence constraints added: 1`. -==== - -====== - - -[role=label--new-5.16] -[[constraints-create-a-node-property-existence-constraint-by-param]] -=== Create a node property existence constraint using a parameter - -The constraint name can also be given as a parameter. - -.+CREATE CONSTRAINT+ -====== - -.Parameters -[source, parameters] ----- -{ - "name": "node_exist_param" -} ----- - -.Query -[source, cypher] ----- -CREATE CONSTRAINT $name -FOR (author:Author) REQUIRE author.surname IS NOT NULL ----- - -.Result -[queryresult] ----- -Added 1 constraint. ----- - -[NOTE] -==== -The detailed statistics view for property existence constraints, `Property existence constraints added: 1`, will be split between nodes and relationships in Neo4j 6.0. -For the node property existence constraints, they will say `Node property existence constraints added: 1`. -==== - -====== - - -[[constraints-create-a-node-property-existence-constraint-if-not-exist]] -=== Handling existing constraints when creating a constraint - -Creating an already existing constraint will fail. -To avoid such an error, `IF NOT EXISTS` can be added to the `CREATE` command. -This will ensure that no error is thrown and that no constraint is created if any other constraint with the given name, or another node property existence constraint on the same schema, already exists. -As of Neo4j 5.17, an informational notification is instead returned showing the existing constraint which blocks the creation. - -.+CREATE CONSTRAINT+ -====== - -//// -[source, cypher, role=test-setup] ----- -CREATE CONSTRAINT author_pseudonym -FOR (author:Author) REQUIRE author.pseudonym IS UNIQUE ----- -//// - -.Query -[source, cypher] ----- -CREATE CONSTRAINT author_pseudonym IF NOT EXISTS -FOR (author:Author) REQUIRE author.pseudonym IS NOT NULL ----- - -Assuming a constraint with the name `author_pseudonym` already exists: - -.Result -[queryresult] ----- -(no changes, no records) ----- - -.Notification -[source] ----- -`CREATE CONSTRAINT author_pseudonym IF NOT EXISTS FOR (e:Author) REQUIRE (e.pseudonym) IS NOT NULL` has no effect. -`CONSTRAINT author_pseudonym FOR (e:Author) REQUIRE (e.pseudonym) IS UNIQUE` already exists. ----- - -====== - - -[[constraints-create-an-already-existing-node-property-existence-constraint]] -=== Creating an already existing constraint will fail - - -.+CREATE CONSTRAINT+ -====== - -Create a node property existence constraint on the property `name` on nodes with the `Author` label, when that constraint already exists: - -.Query -[source, cypher, role=test-fail] ----- -CREATE CONSTRAINT author_name -FOR (author:Author) REQUIRE author.name IS NOT NULL ----- - -In this case, the constraint cannot be created because it already exists. - -.Error message -[source, error] ----- -An equivalent constraint already exists, 'Constraint( id=10, name='author_name', type='NODE PROPERTY EXISTENCE', schema=(:Author {name}) )'. ----- - -====== - - -[[constraints-create-a-node-that-complies-with-a-property-existence-constraint]] -=== Creating a node that complies with an existing constraint - - -.+CREATE NODE+ -====== - -Create an `Author` node with a `name` property: - -.Query -[source, cypher] ----- -CREATE (author:Author {name:'Virginia Woolf', surname: 'Woolf'}) ----- - -.Result -[queryresult] ----- -Added 1 label, created 1 node, set 2 properties ----- - -====== - - -[[constraints-create-a-node-that-violates-a-property-existence-constraint]] -=== Creating a node that violates an existing constraint will fail - - -.+CREATE NODE+ -====== - -Create an `Author` node without a `name` property, given a property existence constraint on `:Author(name)`: - -.Query -[source, cypher, role=test-fail] ----- -CREATE (author:Author {surname: 'Austen'}) ----- - -In this case, the node is not created because it is missing the `name` property which is in conflict with an existing constraint. - -.Error message -[source, error] ----- -Node(0) with label `Author` must have the property `name` ----- - -====== - - -[[constraints-removing-an-existence-constrained-node-property]] -=== Removing an existence constrained node property will fail - - -.+REMOVE PROPERTY+ -====== - -Remove the `name` property from an existing node `Author`, given a property existence constraint on `:Author(name)`: - -.Query -[source, cypher, role=test-fail] ----- -MATCH (author:Author {name: 'Virginia Woolf'}) -REMOVE author.name ----- - -In this case, the property is not removed because it is in conflict with an existing constraint. - -.Error message -[source, error] ----- -Node(0) with label `Author` must have the property `name` ----- - -====== - - -[[constraints-fail-to-create-a-property-existence-constraint-due-to-existing-node]] -=== Creating a constraint when there exist conflicting nodes will fail - - -.+CREATE CONSTRAINT+ -====== - -Create a constraint on the property `nationality` on nodes with the `Author` label, when there already exists a node without a `nationality` property: - -.Query -[source, cypher, role=test-fail] ----- -CREATE CONSTRAINT author_nationality FOR (author:Author) REQUIRE author.nationality IS NOT NULL ----- - -In this case, the constraint cannot be created because it is in conflict with the existing graph. -Remove or correct the offending nodes and then re-apply the constraint. - -.Error message -[source, error] ----- -Unable to create Constraint( type='NODE PROPERTY EXISTENCE', schema=(:Author {nationality}) ): -Node(0) with label `Author` must have the property `nationality` ----- - -====== - -The constraint creation fails on the first offending node that is found. -This does not guarantee that there are no other offending nodes in the graph. -Therefore, all the data should be checked and cleaned up before re-attempting the constraint creation. - -This is an example `MATCH` query to find all offending nodes missing the property for the constraint above: - -.Query -[source, cypher] ----- -MATCH (author:Author) -WHERE author.nationality IS NULL -RETURN author ----- - - -[role=label--enterprise-edition] -[[constraints-examples-relationship-property-existence]] -== Relationship property existence constraints - -A relationship property existence constraint ensures that certain relationships have a certain property. - -* xref::constraints/examples.adoc#constraints-create-a-relationship-property-existence-constraint[] -* xref::constraints/examples.adoc#constraints-create-a-relationship-property-existence-constraint-by-param[] -* xref::constraints/examples.adoc#constraints-create-a-relationship-property-existence-constraint-if-not-exist[] -* xref::constraints/examples.adoc#constraints-create-an-already-existing-relationship-property-existence-constraint[] -* xref::constraints/examples.adoc#constraints-create-a-relationship-that-complies-with-a-property-existence-constraint[] -* xref::constraints/examples.adoc#constraints-create-a-relationship-that-violates-a-property-existence-constraint[] -* xref::constraints/examples.adoc#constraints-removing-an-existence-constrained-relationship-property[] -* xref::constraints/examples.adoc#constraints-fail-to-create-a-property-existence-constraint-due-to-existing-relationship[] - - -[[constraints-create-a-relationship-property-existence-constraint]] -=== Create a relationship property existence constraint - -When creating a relationship property existence constraint, it is recommended to provide a constraint name. - - -.+CREATE CONSTRAINT+ -====== - -.Query -[source, cypher] ----- -CREATE CONSTRAINT wrote_year -FOR ()-[wrote:WROTE]-() REQUIRE wrote.year IS NOT NULL ----- - -.Result -[queryresult] ----- -Added 1 constraint. ----- - -[NOTE] -==== -The detailed statistics view for property existence constraints, `Property existence constraints added: 1`, will be split between nodes and relationships in Neo4j 6.0. -For the relationship property existence constraints, they will say `Relationship property existence constraints added: 1`. -==== - -====== - -[role=label--new-5.16] -[[constraints-create-a-relationship-property-existence-constraint-by-param]] -=== Create a relationship property existence constraint using a parameter - -The constraint name can also be given as a parameter. - -.+CREATE CONSTRAINT+ -====== - -.Parameters -[source, parameters] ----- -{ - "name": "rel_exist_param" -} ----- - -.Query -[source, cypher] ----- -CREATE CONSTRAINT $name -FOR ()-[wrote:WROTE]-() REQUIRE wrote.published IS NOT NULL ----- - -.Result -[queryresult] ----- -Added 1 constraint. ----- - -[NOTE] -==== -The detailed statistics view for property existence constraints, `Property existence constraints added: 1`, will be split between nodes and relationships in Neo4j 6.0. -For the relationship property existence constraints, they will say `Relationship property existence constraints added: 1`. -==== - -====== - - -[[constraints-create-a-relationship-property-existence-constraint-if-not-exist]] -=== Handling existing constraints when creating a constraint - -Creating an already existing constraint will fail. -To avoid such an error, `IF NOT EXISTS` can be added to the `CREATE` command. -This will ensure that no error is thrown and that no constraint is created if any other constraint with the given name, or another relationship property existence constraint on the same schema, already exists. -As of Neo4j 5.17, an informational notification is instead returned showing the existing constraint which blocks the creation. - -.+CREATE CONSTRAINT+ -====== - -.Query -[source, cypher] ----- -CREATE CONSTRAINT wrote_year IF NOT EXISTS -FOR ()-[wrote:WROTE]-() REQUIRE wrote.year IS NOT NULL ----- - -Assuming that such a constraint already exists: - -.Result -[queryresult] ----- -(no changes, no records) ----- - -.Notification -[source] ----- -`CREATE CONSTRAINT wrote_year IF NOT EXISTS FOR ()-[e:WROTE]-() REQUIRE (e.year) IS NOT NULL` has no effect. -`CONSTRAINT wrote_year FOR ()-[e:WROTE]-() REQUIRE (e.year) IS NOT NULL` already exists. ----- - -====== - - -[[constraints-create-an-already-existing-relationship-property-existence-constraint]] -=== Creating an already existing constraint will fail - - -.+CREATE CONSTRAINT+ -====== - -Create a named relationship property existence constraint on the property `locations` on relationships with the `WROTE` relationship type, when a constraint with the given name already exists: - -//// -[source, cypher, role=test-setup] ----- -CREATE CONSTRAINT wrote_locations FOR ()-[wrote:WROTE]-() REQUIRE wrote.location IS NOT NULL ----- -//// - -.Query -[source, cypher, role=test-fail] ----- -CREATE CONSTRAINT wrote_locations -FOR ()-[wrote:WROTE]-() REQUIRE wrote.locations IS NOT NULL ----- - -In this case, the constraint cannot be created because there already exists a constraint with the given name. - -.Error message -[source, error] ----- -There already exists a constraint called 'wrote_locations'. ----- - -====== - - -[[constraints-create-a-relationship-that-complies-with-a-property-existence-constraint]] -=== Creating a relationship that complies with an existing constraint - - -.+CREATE RELATIONSHIP+ -====== - -Create a `WROTE` relationship with a `year` and `location` property, given property existence constraints on `:WROTE(year)` and `:WROTE(location)`: - -.Query -[source, cypher] ----- -CREATE (author:Author {name: 'Emily Brontë', surname: 'Brontë'})-[wrote:WROTE {year: 1847, location: 'Haworth, United Kingdom', published: true}]->(book:Book {title:'Wuthering Heights', isbn: 9789186579296}) ----- - -.Result -[queryresult] ----- -Added 2 labels, created 2 nodes, set 7 properties, created 1 relationship ----- - -====== - - -[[constraints-create-a-relationship-that-violates-a-property-existence-constraint]] -=== Creating a relationship that violates an existing constraint will fail - - -.+CREATE RELATIONSHIP+ -====== - -Create a `WROTE` relationship without a `location` property, given a property existence constraint `:WROTE(location)`: - -.Query -[source, cypher, role=test-fail] ----- -CREATE (author:Author {name: 'Charlotte Brontë', surname: 'Brontë'})-[wrote:WROTE {year: 1847, published: true}]->(book:Book {title: 'Jane Eyre', isbn:9780194241762}) ----- - -In this case, the relationship is not created because it is missing the `location` property which is in conflict with an existing constraint. - -.Error message -[source, error] ----- -Relationship(0) with type `WROTE` must have the property `location` ----- - -====== - - -[[constraints-removing-an-existence-constrained-relationship-property]] -=== Removing an existence constrained relationship property will fail - - -.+REMOVE PROPERTY+ -====== - -Remove the `location` property from an existing relationship of relationship type `WROTE`, given a property existence constraint `:WROTE(location)`: - -.Query -[source, cypher, role=test-fail] ----- -MATCH (author:Author)-[wrote:WROTE]->(book:Book) REMOVE wrote.location ----- - -In this case, the property is not removed because it is in conflict with an existing constraint. - -.Error message -[source, error] ----- -Relationship(0) with type `WROTE` must have the property `location` ----- - -====== - - -[[constraints-fail-to-create-a-property-existence-constraint-due-to-existing-relationship]] -=== Creating a constraint when there exist conflicting relationships will fail - - -.+CREATE CONSTRAINT+ -====== - -Create a constraint on the property `language` on relationships with the `WROTE` relationship type, when there already exists a relationship without a property named `language`: - -.Query -[source, cypher, role=test-fail] ----- -CREATE CONSTRAINT wrote_language FOR ()-[wrote:WROTE]-() REQUIRE wrote.language IS NOT NULL ----- - -In this case, the constraint cannot be created because it is in conflict with the existing graph. -Remove or correct the offending relationships and then re-apply the constraint. - -.Error message -[source, error] ----- -Unable to create Constraint( type='RELATIONSHIP PROPERTY EXISTENCE', schema=()-[:WROTE {language}]-() ): -Relationship(0) with type `WROTE` must have the property `language` ----- - -====== - -The constraint creation fails on the first offending relationship that is found. -This does not guarantee that there are no other offending relationships in the graph. -Therefore, all the data should be checked and cleaned up before re-attempting the constraint creation. - -This is an example `MATCH` query to find all offending relationships missing the property for the constraint above: - -.Query -[source, cypher] ----- -MATCH ()-[wrote:WROTE]-() -WHERE wrote.language IS NULL -RETURN wrote ----- - - -[role=label--enterprise-edition label--new-5.9] -[[constraints-examples-node-property-type]] -== Node property type constraints - -A node property type constraint ensures that certain nodes have a property of the required property type when the property exists on the node. - -The allowed property types for the constraints are: - -* `BOOLEAN` -* `STRING` -* `INTEGER` -* `FLOAT` -* `DATE` -* `LOCAL TIME` -* `ZONED TIME` -* `LOCAL DATETIME` -* `ZONED DATETIME` -* `DURATION` -* `POINT` -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* Any closed dynamic union of the above types, e.g. `INTEGER | FLOAT | STRING`. label:new[Introduced in 5.11] - -For a complete reference describing all types available in Cypher, see the section on xref::values-and-types/property-structural-constructed.adoc#types-synonyms[types and their synonyms]. - -* xref::constraints/examples.adoc#constraints-create-a-node-property-type-constraint[] -* xref::constraints/examples.adoc#constraints-create-a-node-property-type-constraint-by-param[] -* xref::constraints/examples.adoc#constraints-create-a-node-property-type-constraint-if-not-exist[] -* xref::constraints/examples.adoc#constraints-create-an-already-existing-node-property-type-constraint[] -* xref::constraints/examples.adoc#constraints-create-a-different-than-existing-node-property-type-constraint[] -* xref::constraints/examples.adoc#constraints-create-node-property-type-constraints-on-invalid-types[] -* xref::constraints/examples.adoc#constraints-create-a-node-that-complies-with-a-property-type-constraint[] -* xref::constraints/examples.adoc#constraints-create-a-node-that-violates-a-property-type-constraint[] -* xref::constraints/examples.adoc#constraints-fail-to-create-a-property-type-constraint-due-to-existing-node[] - - -[[constraints-create-a-node-property-type-constraint]] -=== Create a node property type constraint - -When creating a node property type constraint, it is recommended to provide a constraint name. - - -.+CREATE CONSTRAINT+ -====== - -.Query -[source, cypher] ----- -CREATE CONSTRAINT movie_title -FOR (movie:Movie) REQUIRE movie.title IS :: STRING ----- - -.Result -[queryresult] ----- -Added 1 constraint. ----- - -====== - -[role=label--new-5.16] -[[constraints-create-a-node-property-type-constraint-by-param]] -=== Create a node property type constraint using a parameter - -The constraint name can also be given as a parameter. - -.+CREATE CONSTRAINT+ -====== - -.Parameters -[source, parameters] ----- -{ - "name": "node_prop_type_param" -} ----- - -.Query -[source, cypher] ----- -CREATE CONSTRAINT $name -FOR (movie:Movie) REQUIRE movie.prop1 IS :: INT ----- - -.Result -[queryresult] ----- -Added 1 constraint. ----- - -====== - - -[role=label--new-5.11] -[[constraints-create-a-node-property-type-constraint-union]] -=== Create a node property type constraint with a union type - -A closed dynamic union allows a node property to maintain some type flexibility whilst preventing unexpected values from being stored. - - -.+CREATE CONSTRAINT+ -====== - -.Query -[source, cypher] ----- -CREATE CONSTRAINT movie_tagline -FOR (movie:Movie) REQUIRE movie.tagline IS :: STRING | LIST ----- - -.Result -[queryresult] ----- -Added 1 constraint. ----- - -====== - - -[[constraints-create-a-node-property-type-constraint-if-not-exist]] -=== Handling existing constraints when creating a constraint - -Creating an already existing constraint will fail. -To avoid such an error, `IF NOT EXISTS` can be added to the `CREATE` command. -This will ensure that no error is thrown and that no constraint is created if any other constraint with the given name, or another node property type constraint on the same schema and property type, already exists. -As of Neo4j 5.17, an informational notification is instead returned showing the existing constraint which blocks the creation. - -.+CREATE CONSTRAINT+ -====== - -.Query -[source, cypher] ----- -CREATE CONSTRAINT movie_titles IF NOT EXISTS -FOR (movie:Movie) REQUIRE movie.title :: STRING ----- - -Assuming a node property type constraint on the label `Movie` which restricts the property `title` to `STRING` values already exists: - -.Result -[queryresult] ----- -(no changes, no records) ----- - -.Notification -[source] ----- -`CREATE CONSTRAINT movie_titles IF NOT EXISTS FOR (e:Movie) REQUIRE (e.title) IS :: STRING` has no effect. -`CONSTRAINT movie_title FOR (e:Movie) REQUIRE e.title IS :: STRING` already exists. ----- - -====== - - -[[constraints-create-an-already-existing-node-property-type-constraint]] -=== Creating an already existing constraint will fail - - -.+CREATE CONSTRAINT+ -====== - -Create a node property type constraint restricting the property `title` to `STRING` values on nodes with the `Movie` label, when that constraint already exists: - -.Query -[source, cypher, role=test-fail] ----- -CREATE CONSTRAINT movies -FOR (movie:Movie) REQUIRE movie.title IS TYPED STRING ----- - -In this case, the constraint cannot be created because it already exists. - -.Error message -[source, error] ----- -Constraint already exists: Constraint( id=22, name='movie_title', type='NODE PROPERTY TYPE', schema=(:Movie {title}), propertyType=STRING ) ----- - -====== - - -[[constraints-create-a-different-than-existing-node-property-type-constraint]] -=== Creating a constraint when there is an existing constraint with a different property type will fail - - -.+CREATE CONSTRAINT+ -====== - -Create a node property type constraint restricting the property `seriesOrder` to float values on nodes with the `Movie` label, when a node property type constraint restricting the property `seriesOrder` to integer values already exists: - -//// -[source, cypher, role=test-setup] ----- -CREATE CONSTRAINT seriesOrder -FOR (movie:Movie) REQUIRE movie.seriesOrder IS :: INTEGER ----- -//// - -.Query -[source, cypher, role=test-fail] ----- -CREATE CONSTRAINT order -FOR (movie:Movie) REQUIRE movie.seriesOrder IS :: FLOAT ----- - -In this case, the constraint cannot be created because there exists a conflicting constraint. - -.Error message -[source, error] ----- -Constraint already exists: Constraint( id=23, name='seriesOrder', type='NODE PROPERTY TYPE', schema=(:Movie {seriesOrder}), propertyType=INTEGER ) ----- - -====== - - -[[constraints-create-node-property-type-constraints-on-invalid-types]] -=== Creating constraints on invalid types will fail - - -.+CREATE CONSTRAINT+ -====== - -Create a node property type constraint restricting the property `imdbScore` to map values on nodes with the `Movie` label: - -.Query -[source, cypher, role=test-fail] ----- -CREATE CONSTRAINT score -FOR (movie:Movie) REQUIRE movie.imdbScore IS :: MAP ----- - -In this case, the constraint cannot be created because values of type `MAP` cannot be stored in properties and therefore are not permitted in property type constraints. - -.Error message -[source, error] ----- -Failed to create node property type constraint: Invalid property type `MAP`. ----- - -====== - -.+CREATE CONSTRAINT+ -====== - -Create a node property type constraint restricting the property `imdbScore` to list of nullable float values on nodes with the `Movie` label: - -.Query -[source, cypher, role=test-fail] ----- -CREATE CONSTRAINT score -FOR (movie:Movie) REQUIRE movie.imdbScore IS :: LIST ----- - -In this case, the constraint cannot be created because the inner type of list types cannot be nullable. -The correct type to use for the constraint is `LIST` because `null` values cannot be stored as part of a list. - -.Error message -[source, error] ----- -Failed to create node property type constraint: Invalid property type `LIST`. Lists cannot have nullable inner types. ----- - -====== - -.+CREATE CONSTRAINT+ -====== - -Create a node property type constraint restricting the property `imdbScore` to list of lists of float values on nodes with the `Movie` label: - -.Query -[source, cypher, role=test-fail] ----- -CREATE CONSTRAINT score -FOR (movie:Movie) REQUIRE movie.imdbScore IS :: LIST> ----- - -In this case, the constraint cannot be created because the inner type of list types cannot be other lists. - -.Error message -[source, error] ----- -Failed to create node property type constraint: Invalid property type `LIST>`. Lists cannot have lists as an inner type. ----- - -====== - - -[[constraints-create-a-node-that-complies-with-a-property-type-constraint]] -=== Creating a node that complies with an existing constraint - - -.+CREATE NODE+ -====== - -Create an `Movie` node with a `STRING` `title` property: - -.Query -[source, cypher] ----- -CREATE (movie:Movie {title:'Iron Man'}) ----- - -.Result -[queryresult] ----- -Added 1 label, created 1 node, set 1 properties ----- - -====== - - -[[constraints-create-a-node-that-violates-a-property-type-constraint]] -=== Creating a node that violates an existing constraint will fail - - -.+CREATE NODE+ -====== - -Create a `Movie` node with an integer `title` property, given a property type constraint on the label `Movie` restricting the `title` property to `STRING` values: - -.Query -[source, cypher, role=test-fail] ----- -CREATE (movie:Movie {title: 123}) ----- - -In this case, the node is not created because the `title` property is in conflict with an existing constraint. - -.Error message -[source, error] ----- -Node(0) with label `Movie` has property `title` of wrong type `Long`. Allowed types: STRING ----- - -====== - - -[[constraints-fail-to-create-a-property-type-constraint-due-to-existing-node]] -=== Creating a constraint when there exist conflicting nodes will fail - - -.+CREATE CONSTRAINT+ -====== - -Create a constraint restricting the property `franchise` to `STRING` values on nodes with the `Movie` label, when there already exists a node with a `BOOLEAN` `franchise` property: - -//// -[source, cypher, role=test-setup] ----- -CREATE (movie:Movie {title:'Captain America: The First Avenger', franchise: true}) ----- -//// - -.Query -[source, cypher, role=test-fail] ----- -CREATE CONSTRAINT movie_franchise FOR (movie:Movie) REQUIRE movie.franchise IS :: STRING ----- - -In this case, the constraint cannot be created because it is in conflict with the existing graph. -Remove or correct the offending nodes and then re-apply the constraint. - -.Error message -[source, error] ----- -Unable to create Constraint( name='movie_franchise', type='NODE PROPERTY TYPE', schema=(:Movie {franchise}), propertyType=STRING ): -Node(0) with label `Movie` has property `franchise` of wrong type `Boolean`. Allowed types: STRING ----- - -====== - -The constraint creation fails on the first offending node that is found. -This does not guarantee that there are no other offending nodes in the graph. -Therefore, all the data should be checked and cleaned up before re-attempting the constraint creation. - -This is an example `MATCH` query to find all offending nodes with the wrong property type for the constraint above: - -.Query -[source, cypher] ----- -MATCH (movie:Movie) -WHERE movie.franchise IS NOT :: STRING -RETURN movie ----- - - -[role=label--enterprise-edition label--new-5.9] -[[constraints-examples-relationship-property-type]] -== Relationship property type constraints - -A relationship property type constraint ensures that certain relationships have a property of the required property type when the property exists on the relationship. - -The allowed property types for the constraints is: - -* `BOOLEAN` -* `STRING` -* `INTEGER` -* `FLOAT` -* `DATE` -* `LOCAL TIME` -* `ZONED TIME` -* `LOCAL DATETIME` -* `ZONED DATETIME` -* `DURATION` -* `POINT` -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* Any closed dynamic union of the above types, e.g. `INTEGER | FLOAT | STRING`. label:new[Introduced in 5.11] - -For a complete reference describing all types available in Cypher, see the section on xref::values-and-types/property-structural-constructed.adoc#types-synonyms[types and their synonyms]. - -* xref::constraints/examples.adoc#constraints-create-a-relationship-property-type-constraint[] -* xref::constraints/examples.adoc#constraints-create-a-relationship-property-type-constraint-by-param[] -* xref::constraints/examples.adoc#constraints-create-a-relationship-property-type-constraint-if-not-exist[] -* xref::constraints/examples.adoc#constraints-create-an-already-existing-relationship-property-type-constraint[] -* xref::constraints/examples.adoc#constraints-create-a-different-than-existing-relationship-property-type-constraint[] -* xref::constraints/examples.adoc#constraints-create-relationship-property-type-constraints-on-invalid-types[] -* xref::constraints/examples.adoc#constraints-create-a-relationship-that-complies-with-a-property-type-constraint[] -* xref::constraints/examples.adoc#constraints-create-a-relationship-that-violates-a-property-type-constraint[] -* xref::constraints/examples.adoc#constraints-fail-to-create-a-property-type-constraint-due-to-existing-relationship[] - - -[[constraints-create-a-relationship-property-type-constraint]] -=== Create a relationship property type constraint - -When creating a relationship property type constraint, it is recommended to provide a constraint name. - - -.+CREATE CONSTRAINT+ -====== - -.Query -[source, cypher] ----- -CREATE CONSTRAINT part_of -FOR ()-[part:PART_OF]-() REQUIRE part.order IS :: INTEGER ----- - -.Result -[queryresult] ----- -Added 1 constraint. ----- - -====== - -[role=label--new-5.16] -[[constraints-create-a-relationship-property-type-constraint-by-param]] -=== Create a relationship property type constraint using a parameter - -The constraint name can also be given as a parameter. - -.+CREATE CONSTRAINT+ -====== - -.Parameters -[source, parameters] ----- -{ - "name": "rel_prop_type_param" -} ----- - -.Query -[source, cypher] ----- -CREATE CONSTRAINT $name -FOR ()-[part:PART_OF]-() REQUIRE part.prop1 IS :: FLOAT ----- - -.Result -[queryresult] ----- -Added 1 constraint. ----- - -====== - -[role=label--new-5.11] -[[constraints-create-a-relationship-property-type-constraint-union]] -=== Create a relationship property type constraint with a union type - -A closed dynamic union allows a relationship property to maintain some type flexibility whilst preventing unexpected values from being stored. - - -.+CREATE CONSTRAINT+ -====== - -.Query -[source, cypher] ----- -CREATE CONSTRAINT part_of_tags -FOR ()-[part:PART_OF]-() REQUIRE part.tags IS :: STRING | LIST ----- - -.Result -[queryresult] ----- -Added 1 constraint. ----- - -====== - -[[constraints-create-a-relationship-property-type-constraint-if-not-exist]] -=== Handling existing constraints when creating a constraint - -Creating an already existing constraint will fail. -To avoid such an error, `IF NOT EXISTS` can be added to the `CREATE` command. -This will ensure that no error is thrown and that no constraint is created if any other constraint with the given name, or another relationship property type constraint on the same schema and property type, already exists. -As of Neo4j 5.17, an informational notification is instead returned showing the existing constraint which blocks the creation. - -.+CREATE CONSTRAINT+ -====== - -.Query -[source, cypher] ----- -CREATE CONSTRAINT part_of IF NOT EXISTS -FOR ()-[part:PART_OF]-() REQUIRE part.order IS TYPED INTEGER ----- - -Assuming that such a constraint already exists: - -.Result -[queryresult] ----- -(no changes, no records) ----- - -.Notification -[source] ----- -`CREATE CONSTRAINT part_of IF NOT EXISTS FOR ()-[e:PART_OF]-() REQUIRE (e.order) IS :: INTEGER` has no effect. -`CONSTRAINT part_of FOR ()-[e:PART_OF]-() REQUIRE (e.order) IS :: INTEGER` already exists. ----- - -====== - - -[[constraints-create-an-already-existing-relationship-property-type-constraint]] -=== Creating an already existing constraint will fail - - -.+CREATE CONSTRAINT+ -====== - -Create a relationship property type constraint restricting the property `order` to integer values on relationships with the `PART_OF` relationship type, when that constraint already exists: - -.Query -[source, cypher, role=test-fail] ----- -CREATE CONSTRAINT belongs_to -FOR ()-[part:PART_OF]-() REQUIRE part.order :: INTEGER ----- - -In this case, the constraint cannot be created because it already exists (but with a different name). - -.Error message -[source, error] ----- -Constraint already exists: Constraint( id=24, name='part_of', type='RELATIONSHIP PROPERTY TYPE', schema=()-[:PART_OF {order}]-(), propertyType=INTEGER ) ----- - -====== - - -[[constraints-create-a-different-than-existing-relationship-property-type-constraint]] -=== Creating a constraint when there is an existing constraint with a different property type will fail - - -.+CREATE CONSTRAINT+ -====== - -Create a relationship property type constraint restricting the property `order` to float values on relationships with the `PART_OF` relationship type, when a relationship property type constraint restricting the property `order` to integer values already exists: - -.Query -[source, cypher, role=test-fail] ----- -CREATE CONSTRAINT order -FOR ()-[part:PART_OF]-() REQUIRE part.order IS :: FLOAT ----- - -In this case, the constraint cannot be created because there exists a conflicting constraint. - -.Error message -[source, error] ----- -Constraint already exists: Constraint( id=24, name='part_of', type='RELATIONSHIP PROPERTY TYPE', schema=()-[:PART_OF {order}]-(), propertyType=INTEGER ) ----- - -====== - - -[[constraints-create-relationship-property-type-constraints-on-invalid-types]] -=== Creating constraints on invalid types will fail - - -.+CREATE CONSTRAINT+ -====== - -Create a relationship property type constraint restricting the property `releaseOrder` to integer values excluding `null` on relationships with the `PART_OF` relationship type: - -.Query -[source, cypher, role=test-fail] ----- -CREATE CONSTRAINT score -FOR ()-[part:PART_OF]-() REQUIRE part.releaseOrder IS :: INTEGER NOT NULL ----- - -In this case, the constraint cannot be created because excluding `null` is not allowed in property type constraints. -To also ensure that the property exists (is not `null`), add an existence constraint on the property. - -.Error message -[source, error] ----- -Failed to create relationship property type constraint: Invalid property type `INTEGER NOT NULL`. ----- - -====== - -.+CREATE CONSTRAINT+ -====== - -Create a relationship property type constraint restricting the property `releaseOrder` to list of nullable integer values on relationships with the `PART_OF` relationship type: - -.Query -[source, cypher, role=test-fail] ----- -CREATE CONSTRAINT score -FOR ()-[part:PART_OF]-() REQUIRE part.releaseOrder IS :: LIST ----- - -In this case, the constraint cannot be created because the inner type of list types cannot be nullable. -The correct type to use for the constraint is `LIST` because `null` values cannot be stored as part of a list. - -.Error message -[source, error] ----- -Failed to create relationship property type constraint: Invalid property type `LIST`. Lists cannot have nullable inner types. ----- - -====== - -.+CREATE CONSTRAINT+ -====== - -Create a relationship property type constraint restricting the property `releaseOrder` to list of lists of integer values on relationships with the `PART_OF` relationship type: - -.Query -[source, cypher, role=test-fail] ----- -CREATE CONSTRAINT score -FOR ()-[part:PART_OF]-() REQUIRE part.releaseOrder IS :: LIST> ----- - -In this case, the constraint cannot be created because the inner type of list types cannot be other lists. - -.Error message -[source, error] ----- -Failed to create relationship property type constraint: Invalid property type `LIST>`. Lists cannot have lists as an inner type. ----- - -====== - - -[[constraints-create-a-relationship-that-complies-with-a-property-type-constraint]] -=== Creating a relationship that complies with an existing constraint - - -.+CREATE RELATIONSHIP+ -====== - -Create a `PART_OF` relationship with an integer `order` property: - -//// -[source, cypher, role=test-setup] ----- -CREATE (franchise:Franchise {name:'MCU'}) ----- -//// - -.Query -[source, cypher] ----- -MATCH (movie:Movie {title:'Iron Man'}), (franchise:Franchise {name:'MCU'}) -CREATE (movie)-[part:PART_OF {order: 3}]->(franchise) ----- - -.Result -[queryresult] ----- -Set 1 property, created 1 relationship ----- - -====== - - -[[constraints-create-a-relationship-that-violates-a-property-type-constraint]] -=== Creating a relationship that violates an existing constraint will fail - - -.+CREATE RELATIONSHIP+ -====== - -Create a `PART_OF` relationship with a `STRING` `order` property, given a property type constraint on the relationship type `PART_OF` restricting the `order` property to integer values: - -.Query -[source, cypher, role=test-fail] ----- -MATCH (movie:Movie {title:'Captain America: The First Avenger'}), (franchise:Franchise {name:'MCU'}) -CREATE (movie)-[part:PART_OF {order: '1'}]->(franchise) ----- - -In this case, the relationship is not created because the `order` property is in conflict with an existing constraint. - -.Error message -[source, error] ----- -Relationship(0) with type `PART_OF` has property `order` of wrong type `String`. Allowed types: INTEGER ----- - -====== - - -[[constraints-fail-to-create-a-property-type-constraint-due-to-existing-relationship]] -=== Creating a constraint when there exist conflicting relationships will fail - - -.+CREATE CONSTRAINT+ -====== - -Create a constraint restricting the property `releaseOrder` to integer values on relationships with the `PART_OF` relationship type, when there already exists a relationship with a `STRING` `releaseOrder` property: - -//// -[source, cypher, role=test-setup] ----- -MATCH (movie:Movie {title:'Captain America: The First Avenger'}), (franchise:Franchise {name:'MCU'}) -CREATE (movie)-[part:PART_OF {order: 1, releaseOrder: '5'}]->(franchise) ----- -//// - -.Query -[source, cypher, role=test-fail] ----- -CREATE CONSTRAINT release_order -FOR ()-[part:PART_OF]-() REQUIRE part.releaseOrder IS :: INTEGER ----- - -In this case, the constraint cannot be created because it is in conflict with the existing graph. -Remove or correct the offending relationships and then re-apply the constraint. - -.Error message -[source, error] ----- -Unable to create Constraint( name='release_order', type='RELATIONSHIP PROPERTY TYPE', schema=()-[:PART_OF {releaseOrder}]-(), propertyType=INTEGER ): -Relationship(0) with type `PART_OF` has property `releaseOrder` of wrong type `String`. Allowed types: INTEGER ----- - -====== - -The constraint creation fails on the first offending relationship that is found. -This does not guarantee that there are no other offending relationships in the graph. -Therefore, all the data should be checked and cleaned up before re-attempting the constraint creation. - -This is an example `MATCH` query to find all offending relationships with the wrong property type for the constraint above: - -.Query -[source, cypher] ----- -MATCH ()-[part:PART_OF]-() -WHERE part.releaseOrder IS NOT :: INTEGER -RETURN part ----- - - -[role=label--enterprise-edition] -[[constraints-examples-node-key]] -== Node key constraints - -A node key constraint ensures that certain nodes have a set of specified properties whose combined value is unique and all properties in the set are present. - -* xref::constraints/examples.adoc#constraints-create-a-node-key-constraint[] -* xref::constraints/examples.adoc#constraints-create-a-node-key-constraint-by-param[] -* xref::constraints/examples.adoc#constraints-create-a-node-key-constraint-if-not-exist[] -* xref::constraints/examples.adoc#constraints-create-a-node-key-constraint-with-index-provider[] -* xref::constraints/examples.adoc#constraints-node-key-and-uniqueness-constraint-on-the-same-schema[] -* xref::constraints/examples.adoc#constraints-create-a-node-key-constraint-with-the-same-name-as-existing-index[] -* xref::constraints/examples.adoc#constraints-create-a-node-that-complies-with-a-node-key-constraint[] -* xref::constraints/examples.adoc#constraints-create-a-node-that-violates-a-node-key-constraint[] -* xref::constraints/examples.adoc#constraints-removing-a-node-key-constrained-property[] -* xref::constraints/examples.adoc#constraints-fail-to-create-a-node-key-constraint-due-to-existing-node[] - - -[[constraints-create-a-node-key-constraint]] -=== Create a node key constraint - -When creating a node key constraint, it is recommended to provide a constraint name. - - -.+CREATE CONSTRAINT+ -====== - -.Query -[source, cypher] ----- -CREATE CONSTRAINT actor_fullname -FOR (actor:Actor) REQUIRE (actor.firstname, actor.surname) IS NODE KEY ----- - -.Result -[queryresult] ----- -Added 1 constraint. ----- - -====== - -[role=label--new-5.16] -[[constraints-create-a-node-key-constraint-by-param]] -=== Create a node key constraint using a parameter - -The constraint name can also be given as a parameter. - -.+CREATE CONSTRAINT+ -====== - -.Parameters -[source, parameters] ----- -{ - "name": "node_key_param" -} ----- - -.Query -[source, cypher] ----- -CREATE CONSTRAINT $name -FOR (actor:Actor) REQUIRE actor.firstname IS KEY ----- - -.Result -[queryresult] ----- -Added 1 constraint. ----- - -====== - - -[[constraints-create-a-node-key-constraint-if-not-exist]] -=== Handling existing constraints when creating a constraint - -Creating an already existing constraint will fail. -To avoid such an error, `IF NOT EXISTS` can be added to the `CREATE` command. -This will ensure that no error is thrown and that no constraint is created if any other constraint with the given name, or another node key constraint on the same schema, already exists. -As of Neo4j 5.17, an informational notification is instead returned showing the existing constraint which blocks the creation. - -.+CREATE CONSTRAINT+ -====== - -.Query -[source, cypher] ----- -CREATE CONSTRAINT actor_names IF NOT EXISTS -FOR (actor:Actor) REQUIRE (actor.firstname, actor.surname) IS NODE KEY ----- - -Assuming a node key constraint on `(:Actor {firstname, surname})` already exists: - -.Result -[queryresult] ----- -(no changes, no records) ----- - -.Notification -[source] ----- -`CREATE CONSTRAINT actor_names IF NOT EXISTS FOR (e:Actor) REQUIRE (e.firstname, e.surname) IS NODE KEY` has no effect. -`CONSTRAINT actor_fullname FOR (e:Actor) REQUIRE (e.firstname, e.surname) IS NODE KEY` already exists. ----- - -====== - - -[[constraints-create-a-node-key-constraint-with-index-provider]] -=== Specifying an index provider when creating a constraint - -To create a node key constraint with a specific index provider for the backing index, the `OPTIONS` clause is used. - -The index type of the backing index is set with the `indexProvider` option. - -The only valid value for the index provider is: - -* `range-1.0` label:default[] - - -.+CREATE CONSTRAINT+ -====== - -.Query -[source, cypher] ----- -CREATE CONSTRAINT constraint_with_provider -FOR (actor:Actor) REQUIRE (actor.surname) IS NODE KEY -OPTIONS { - indexProvider: 'range-1.0' -} ----- - -.Result -[queryresult] ----- -Added 1 constraint. ----- - -====== - -There is no valid index configuration values for the constraint-backing range indexes. - - -[[constraints-node-key-and-uniqueness-constraint-on-the-same-schema]] -=== Node key and property uniqueness constraints are not allowed on the same schema - - -.+CREATE CONSTRAINT+ -====== - -Create a node key constraint on the properties `firstname` and `age` on nodes with the `Actor` label, when a property uniqueness constraint already exists on the same label and property combination: - -//// -[source, cypher, role=test-setup] ----- -CREATE CONSTRAINT preExisting_actor_name_age FOR (actor:Actor) REQUIRE (actor.firstname, actor.age) IS UNIQUE ----- -//// - -.Query -[source, cypher, role=test-fail] ----- -CREATE CONSTRAINT actor_name_age FOR (actor:Actor) REQUIRE (actor.firstname, actor.age) IS NODE KEY ----- - -In this case, the constraint cannot be created because there already exist a conflicting constraint on that label and property combination. - -.Error message -[source, error] ----- -Constraint already exists: -Constraint( id=10, name='preExisting_actor_name_age', type='UNIQUENESS', schema=(:Actor {firstname, age}), ownedIndex=9 ) ----- - -====== - - -[[constraints-create-a-node-key-constraint-with-the-same-name-as-existing-index]] -=== Creating a constraint on same name as an existing index will fail - - -.+CREATE CONSTRAINT+ -====== - -Create a named node key constraint on the property `citizenship` on nodes with the `Actor` label, when an index already exists with the given name: - -//// -[source, cypher, role=test-setup] ----- -CREATE INDEX citizenship FOR (person:Person) ON (person.citizenship) ----- -//// - -.Query -[source, cypher, role=test-fail] ----- -CREATE CONSTRAINT citizenship -FOR (actor:Actor) REQUIRE actor.citizenship IS NODE KEY ----- - -In this case, the constraint cannot be created because there already exists an index with the given name. - -.Error message -[source, error] ----- -There already exists an index called 'citizenship'. ----- - -====== - - -[[constraints-create-a-node-that-complies-with-a-node-key-constraint]] -=== Creating a node that complies with an existing constraint - - -.+CREATE NODE+ -====== - -Create an `Actor` node with `firstname` and `surname` properties: - -.Query -[source, cypher] ----- -CREATE (actor:Actor {firstname: 'Keanu', surname: 'Reeves'}) ----- - -.Result -[queryresult] ----- -Added 1 label, created 1 node, set 2 properties. ----- - -====== - - -[[constraints-create-a-node-that-violates-a-node-key-constraint]] -=== Creating a node that violates an existing constraint will fail - - -.+CREATE NODE+ -====== - -Create an `Actor` node without a `firstname` property, given a node key constraint on `:Actor(firstname, surname)`: - - -.Query -[source, cypher, role=test-fail] ----- -CREATE (actor:Actor {surname: 'Wood'}) ----- - -In this case, the node is not created because it is missing the `firstname` property which is in conflict with an existing constraint. - -.Error message -[source, error] ----- -Node(0) with label `Actor` must have the properties (`firstname`, `surname`) ----- - -====== - - -[[constraints-removing-a-node-key-constrained-property]] -=== Removing a +NODE KEY+-constrained property will fail - - -.+REMOVE PROPERTY+ -====== - -Remove the `firstname` property from an existing node `Actor`, given a `NODE KEY` constraint on `:Actor(firstname, surname)`: - -.Query -[source, cypher, role=test-fail] ----- -MATCH (actor:Actor {firstname: 'Keanu', surname: 'Reeves'}) REMOVE actor.firstname ----- - -In this case, the property is not removed because it is in conflict with an existing constraint. - -.Error message -[source, error] ----- -Node(0) with label `Actor` must have the properties (`firstname`, `surname`) ----- - -====== - - -[[constraints-fail-to-create-a-node-key-constraint-due-to-existing-node]] -=== Creating a constraint when there exist conflicting node will fail - - -.+CREATE CONSTRAINT+ -====== - -Create a node key constraint on the property `born` on nodes with the `Actor` label, when a node without a `born` property already exists in the graph: - -.Query -[source, cypher, role=test-fail] ----- -CREATE CONSTRAINT actor_born FOR (actor:Actor) REQUIRE (actor.born) IS NODE KEY ----- - -In this case, the node key constraint cannot be created because it is in conflict with the existing graph. -Either use xref:indexes/search-performance-indexes/managing-indexes.adoc[] instead, or remove/correct the offending nodes and then re-apply the constraint. - -.Error message -[source, error] ----- -Unable to create Constraint( type='NODE KEY', schema=(:Actor {born}) ): -Node(0) with label `Actor` must have the property `born` ----- - -====== - -The constraint creation fails on the first offending nodes that are found. -This does not guarantee that there are no other offending nodes in the graph. -Therefore, all the data should be checked and cleaned up before re-attempting the constraint creation. - -This is an example `MATCH` query to find all offending nodes for the constraint above: - -.Query -[source, cypher] ----- -MATCH (actor1:Actor), (actor2:Actor) -WHERE actor1.born = actor2.born AND NOT actor1 = actor2 -UNWIND [actor1, actor2] AS actor -RETURN actor, 'non-unique' AS reason - -UNION - -MATCH (actor:Actor) -WHERE actor.born IS NULL -RETURN actor, 'non-existing' AS reason ----- - - -[role=label--enterprise-edition label--new-5.7] -[[constraints-examples-relationship-key]] -== Relationship key constraints - -A relationship key constraint ensures that certain relationships have a set of defined properties whose combined value is unique. -It also ensures that all properties in the set are present. - -* xref::constraints/examples.adoc#constraints-create-a-relationship-key-constraint[] -* xref::constraints/examples.adoc#constraints-create-a-relationship-key-constraint-by-param[] -* xref::constraints/examples.adoc#constraints-create-a-relationship-key-constraint-if-not-exist[] -* xref::constraints/examples.adoc#constraints-create-a-relationship-key-constraint-with-index-provider[] -* xref::constraints/examples.adoc#constraints-relationship-key-and-uniqueness-constraint-on-the-same-schema[] -* xref::constraints/examples.adoc#constraints-create-a-relationship-key-constraint-with-the-same-name-as-existing-index[] -* xref::constraints/examples.adoc#constraints-create-a-relationship-that-complies-with-a-relationship-key-constraint[] -* xref::constraints/examples.adoc#constraints-create-a-relationship-that-violates-a-relationship-key-constraint[] -* xref::constraints/examples.adoc#constraints-removing-a-relationship-key-constrained-property[] -* xref::constraints/examples.adoc#constraints-fail-to-create-a-relationship-key-constraint-due-to-existing-relationship[] - - -[[constraints-create-a-relationship-key-constraint]] -=== Create a relationship key constraint - -When creating a relationship key constraint, it is recommended to provide a constraint name. - - -.+CREATE CONSTRAINT+ -====== - -.Query -[source, cypher] ----- -CREATE CONSTRAINT knows_since_how -FOR ()-[knows:KNOWS]-() REQUIRE (knows.since, knows.how) IS RELATIONSHIP KEY ----- - -.Result -[queryresult] ----- -Added 1 constraint. ----- - -====== - -[role=label--new-5.16] -[[constraints-create-a-relationship-key-constraint-by-param]] -=== Create a relationship key constraint using a parameter - -The constraint name can also be given as a parameter. - -.+CREATE CONSTRAINT+ -====== - -.Parameters -[source, parameters] ----- -{ - "name": "rel_key_param" -} ----- - -.Query -[source, cypher] ----- -CREATE CONSTRAINT $name -FOR ()-[knows:KNOWS]-() REQUIRE knows.friend IS KEY ----- - -.Result -[queryresult] ----- -Added 1 constraint. ----- - -====== - - -[[constraints-create-a-relationship-key-constraint-if-not-exist]] -=== Handling existing constraints when creating a constraint - -Creating an already existing constraint will fail. -To avoid such an error, `IF NOT EXISTS` can be added to the `CREATE` command. -This will ensure that no error is thrown and that no constraint is created if any other constraint with the given name, or another relationship key constraint on the same schema, already exists. -As of Neo4j 5.17, an informational notification is instead returned showing the existing constraint which blocks the creation. - -.+CREATE CONSTRAINT+ -====== - -.Query -[source, cypher] ----- -CREATE CONSTRAINT knows IF NOT EXISTS -FOR ()-[knows:KNOWS]-() REQUIRE (knows.since, knows.how) IS RELATIONSHIP KEY ----- - -Assuming a relationship key constraint on `()-[:KNOWS {since, how}]-()` already exists: - -.Result -[queryresult] ----- -(no changes, no records) ----- - -.Notification -[source] ----- -`CREATE CONSTRAINT knows IF NOT EXISTS FOR ()-[e:KNOWS]-() REQUIRE (e.since, e.how) IS RELATIONSHIP KEY` has no effect. -`CONSTRAINT knows_since_how FOR ()-[e:KNOWS]-() REQUIRE (e.since, e.how) IS RELATIONSHIP KEY` already exists. ----- - -====== - - -[[constraints-create-a-relationship-key-constraint-with-index-provider]] -=== Specifying an index provider when creating a constraint - -To create a relationship key constraint with a specific index provider for the backing index, the `OPTIONS` clause is used. - -The index type of the backing index is set with the `indexProvider` option. - -The only valid value for the index provider is: - -* `range-1.0` label:default[] - - -.+CREATE CONSTRAINT+ -====== - -.Query -[source, cypher] ----- -CREATE CONSTRAINT rel_constraint_with_provider -FOR ()-[knows:KNOWS]-() REQUIRE (knows.since) IS REL KEY -OPTIONS { - indexProvider: 'range-1.0' -} ----- - -.Result -[queryresult] ----- -Added 1 constraint. ----- - -====== - -There is no valid index configuration values for the constraint-backing range indexes. - - -[[constraints-relationship-key-and-uniqueness-constraint-on-the-same-schema]] -=== Relationship key and property uniqueness constraints are not allowed on the same schema - - -.+CREATE CONSTRAINT+ -====== - -Create a relationship key constraint on the property `how` on relationships with the `KNOWS` relationship type, when a property uniqueness constraint already exists on the same relationship type and property combination: - -//// -[source, cypher, role=test-setup] ----- -CREATE CONSTRAINT preExisting_how FOR ()-[knows:KNOWS]-() REQUIRE (knows.how) IS UNIQUE ----- -//// - -.Query -[source, cypher, role=test-fail] ----- -CREATE CONSTRAINT knows_how FOR ()-[knows:KNOWS]-() REQUIRE (knows.how) IS REL KEY ----- - -In this case, the constraint cannot be created because there already exists a conflicting constraint on that relationship type and property combination. - -.Error message -[source, error] ----- -Constraint already exists: -Constraint( id=34, name='preExisting_how', type='RELATIONSHIP UNIQUENESS', schema=()-[:KNOWS {how}]-(), ownedIndex=33 ) ----- - -[NOTE] -==== -The constraint type for relationship property uniqueness constraints will be updated to say `RELATIONSHIP PROPERTY UNIQUENESS` in Neo4j 6.0. -==== - -====== - - -[[constraints-create-a-relationship-key-constraint-with-the-same-name-as-existing-index]] -=== Creating a constraint on same name as an existing index will fail - - -.+CREATE CONSTRAINT+ -====== - -Create a named relationship key constraint on the property `level` on relationships with the `KNOWS` relationship type, when an index already exists with the given name: - -//// -[source, cypher, role=test-setup] ----- -CREATE INDEX knows FOR ()-[know:KNOW]-() ON (know.levels) ----- -//// - -.Query -[source, cypher, role=test-fail] ----- -CREATE CONSTRAINT knows -FOR ()-[knows:KNOWS]-() REQUIRE (knows.level) IS REL KEY ----- - -In this case, the constraint cannot be created because there already exists an index with the given name. - -.Error message -[source, error] ----- -There already exists an index called 'knows'. ----- - -====== - - -[[constraints-create-a-relationship-that-complies-with-a-relationship-key-constraint]] -=== Creating a relationship that complies with an existing constraint - - -.+CREATE RELATIONSHIP+ -====== - -Create a `KNOWS` relationship with both `since` and `how` properties and a relationship key constraint on `:KNOWS(since, how)`: - -.Query -[source, cypher] ----- -CREATE (:Actor {firstname: 'Jensen', surname: 'Ackles'})-[:KNOWS {since: 2008, how: 'coworkers', friend: true}]->(:Actor {firstname: 'Misha', surname: 'Collins'}) ----- - -.Result -[queryresult] ----- -Added 2 labels, created 2 nodes, set 6 properties, created 1 relationship. ----- - -====== - - -[[constraints-create-a-relationship-that-violates-a-relationship-key-constraint]] -=== Creating a relationship that violates an existing constraint will fail - - -.+CREATE RELATIONSHIP+ -====== - -Create a `KNOWS` relationship without a `since` property, given a relationship key constraint on `:KNOWS(since, how)`: - -.Query -[source, cypher, role=test-fail] ----- -MATCH (jensen:Actor {firstname: 'Jensen', surname: 'Ackles'}), (misha:Actor {firstname: 'Misha', surname: 'Collins'}) -CREATE (misha)-[:KNOWS {how: 'coworkers'}]->(jensen) ----- - -In this case, the relationship is not created because it is missing the `since` property which is in conflict with an existing constraint. - -.Error message -[source, error] ----- -Relationship(0) already exists with type `KNOWS` and property `how` = 'coworkers' ----- - -====== - - -[[constraints-removing-a-relationship-key-constrained-property]] -=== Removing a +RELATIONSHIP KEY+-constrained property will fail - - -.+REMOVE PROPERTY+ -====== - -Remove the `since` property from an existing relationship `KNOWS`, given a `RELATIONSHIP KEY` constraint on `:KNOWS(since, how)`: - -.Query -[source, cypher, role=test-fail] ----- -MATCH ()-[knows:KNOWS {since: 2008, how: 'coworkers'}]->() REMOVE knows.since ----- - -In this case, the property is not removed because it is in conflict with an existing constraint. - -.Error message -[source, error] ----- -Relationship(0) with type `KNOWS` must have the properties (`since`, `how`) ----- - -====== - - -[[constraints-fail-to-create-a-relationship-key-constraint-due-to-existing-relationship]] -=== Creating a constraint when there exist conflicting relationships will fail - - -.+CREATE CONSTRAINT+ -====== - -Create a relationship key constraint on the property `level` on relationships with the `KNOWS` relationship type, when two relationships with identical `level` property values already exist in the graph: - -//// -[source, cypher, role=test-setup] ----- -MATCH (jensen:Actor {firstname: 'Jensen', surname: 'Ackles'})-[knows:KNOWS {since: 2008, how: 'coworkers'}]->(:Actor {firstname: 'Misha', surname: 'Collins'}) -SET knows.level = 10 -CREATE (jensen)-[:KNOWS {since: 2005, how: 'costars', friend: false, level: 10}]->(:Actor {firstname: 'Jared', surname: 'Padalecki'}) ----- -//// - -.Query -[source, cypher, role=test-fail] ----- -CREATE CONSTRAINT knows_level FOR ()-[knows:KNOWS]-() REQUIRE (knows.level) IS REL KEY ----- - -In this case, the relationship key constraint cannot be created because it is in conflict with the existing graph. -Either use xref:indexes/search-performance-indexes/managing-indexes.adoc[] instead, or remove or correct the offending relationships and then re-apply the constraint. - -.Error message -[source, error] ----- -Unable to create Constraint( name='knows_level', type='RELATIONSHIP KEY', schema=()-[:KNOWS {level}]-() ): -Both Relationship(0) and Relationship(1) have the type `KNOWS` and property `level` = 10 ----- - -====== - -The constraint creation fails on the first offending relationships that are found. -This does not guarantee that there are no other offending relationships in the graph. -Therefore, all the data should be checked and cleaned up before re-attempting the constraint creation. - -This is an example `MATCH` query to find all offending relationships for the constraint above: - -.Query -[source, cypher] ----- -MATCH ()-[knows1:KNOWS]->(), ()-[knows2:KNOWS]->() -WHERE knows1.level = knows2.level AND NOT knows1 = knows2 -UNWIND [knows1, knows2] AS knows -RETURN knows, 'non-unique' AS reason -UNION -MATCH ()-[knows:KNOWS]->() -WHERE knows.level IS NULL -RETURN knows, 'non-existing' AS reason ----- - - -[[constraints-examples-drop-constraint]] -== Drop a constraint by name - -A constraint can be dropped using the name with the `DROP CONSTRAINT constraint_name` command. -It is the same command for all constraint types. -The name of the constraint can be found using the xref::constraints/syntax.adoc#constraints-syntax-list[`SHOW CONSTRAINTS` command], given in the output column `name`. - -* xref::constraints/examples.adoc#constraints-drop-a-constraint[] -* xref::constraints/examples.adoc#constraints-drop-a-constraint-by-param[] -* xref::constraints/examples.adoc#constraints-drop-a-non-existing-constraint[] - - -[[constraints-drop-a-constraint]] -=== Drop a constraint - -A constraint can be dropped using the name with the `DROP CONSTRAINT` command. - - -.+DROP CONSTRAINT+ -====== - -.Query -[source, cypher] ----- -DROP CONSTRAINT book_isbn ----- - -.Result -[queryresult] ----- -Removed 1 constraint. ----- - -====== - - -[role=label--new-5.16] -[[constraints-drop-a-constraint-by-param]] -=== Drop a constraint using a parameter - -The constraint name can also be given as a parameter. - -.+DROP CONSTRAINT+ -====== - -.Parameters -[source, parameters] ----- -{ - "name": "node_uniqueness_param" -} ----- - -.Query -[source, cypher] ----- -DROP CONSTRAINT $name ----- - -.Result -[queryresult] ----- -Removed 1 constraint. ----- - -====== - - -[[constraints-drop-a-non-existing-constraint]] -=== Drop a non-existing constraint - -If it is uncertain if any constraint with a given name exists and you want to drop it if it does but not get an error should it not, use `IF EXISTS`. - -.+DROP CONSTRAINT+ -====== - -.Query -[source, cypher] ----- -DROP CONSTRAINT missing_constraint_name IF EXISTS ----- - -.Result -[queryresult] ----- -(no changes, no records) ----- - -.Notification -[source] ----- -`DROP CONSTRAINT missing_constraint_name IF EXISTS` has no effect. `missing_constraint_name` does not exist. ----- - -====== - - -[[constraints-examples-list-constraint]] -== Listing constraints - -* xref::constraints/examples.adoc#constraints-listing-all-constraints[] -* xref::constraints/examples.adoc#constraints-listing-constraints-with-filtering[] - - -[[constraints-listing-all-constraints]] -=== Listing all constraints - -To list all constraints with the default output columns, the `SHOW CONSTRAINTS` command can be used. -If all columns are required, use `SHOW CONSTRAINTS YIELD *`. - -[NOTE] -==== -One of the output columns from `SHOW CONSTRAINTS` is the name of the constraint. -This can be used to drop the constraint with the xref::constraints/syntax.adoc#constraints-syntax-drop[`DROP CONSTRAINT` command]. -==== - - -.+SHOW CONSTRAINTS+ -====== - -.Query -[source, cypher, test-exclude-cols=id] ----- -SHOW CONSTRAINTS ----- - -[queryresult] ----- -+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| id | name | type | entityType | labelsOrTypes | properties | ownedIndex | propertyType | -+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 36 | "actor_fullname" | "NODE_KEY" | "NODE" | ["Actor"] | ["firstname", "surname"] | "actor_fullname" | null | -| 21 | "author_name" | "NODE_PROPERTY_EXISTENCE" | "NODE" | ["Author"] | ["name"] | null | null | -| 24 | "author_pseudonym" | "UNIQUENESS" | "NODE" | ["Author"] | ["pseudonym"] | "author_pseudonym" | null | -| 8 | "book_isbn2" | "UNIQUENESS" | "NODE" | ["Book"] | ["isbn2"] | "book_isbn2" | null | -| 10 | "constraint_with_options" | "UNIQUENESS" | "NODE" | ["Book"] | ["prop1", "prop2"] | "constraint_with_options" | null | -| 40 | "constraint_with_provider" | "NODE_KEY" | "NODE" | ["Actor"] | ["surname"] | "constraint_with_provider" | null | -| 45 | "knows_since_how" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["KNOWS"] | ["since", "how"] | "knows_since_how" | null | -| 30 | "movie_tagline" | "NODE_PROPERTY_TYPE" | "NODE" | ["Movie"] | ["tagline"] | null | "STRING | LIST" | -| 28 | "movie_title" | "NODE_PROPERTY_TYPE" | "NODE" | ["Movie"] | ["title"] | null | "STRING" | -| 22 | "node_exist_param" | "NODE_PROPERTY_EXISTENCE" | "NODE" | ["Author"] | ["surname"] | null | null | -| 38 | "node_key_param" | "NODE_KEY" | "NODE" | ["Actor"] | ["firstname"] | "node_key_param" | null | -| 29 | "node_prop_type_param" | "NODE_PROPERTY_TYPE" | "NODE" | ["Movie"] | ["prop1"] | null | "INTEGER" | -| 32 | "part_of" | "RELATIONSHIP_PROPERTY_TYPE" | "RELATIONSHIP" | ["PART_OF"] | ["order"] | null | "INTEGER" | -| 34 | "part_of_tags" | "RELATIONSHIP_PROPERTY_TYPE" | "RELATIONSHIP" | ["PART_OF"] | ["tags"] | null | "STRING | LIST" | -| 42 | "preExisting_actor_name_age" | "UNIQUENESS" | "NODE" | ["Actor"] | ["firstname", "age"] | "preExisting_actor_name_age" | null | -| 12 | "preExisting_book_published" | "UNIQUENESS" | "NODE" | ["Book"] | ["published"] | "preExisting_book_published" | null | -| 51 | "preExisting_how" | "RELATIONSHIP_UNIQUENESS" | "RELATIONSHIP" | ["KNOWS"] | ["how"] | "preExisting_how" | null | -| 19 | "rel_constraint_with_options" | "RELATIONSHIP_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order", "seriesTitle", "number"] | "rel_constraint_with_options" | null | -| 49 | "rel_constraint_with_provider" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["KNOWS"] | ["since"] | "rel_constraint_with_provider" | null | -| 26 | "rel_exist_param" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["published"] | null | null | -| 47 | "rel_key_param" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["KNOWS"] | ["friend"] | "rel_key_param" | null | -| 33 | "rel_prop_type_param" | "RELATIONSHIP_PROPERTY_TYPE" | "RELATIONSHIP" | ["PART_OF"] | ["prop1"] | null | "FLOAT" | -| 17 | "rel_uniqueness_param" | "RELATIONSHIP_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["prop1"] | "rel_uniqueness_param" | null | -| 15 | "sequels" | "RELATIONSHIP_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order", "seriesTitle"] | "sequels" | null | -| 31 | "seriesOrder" | "NODE_PROPERTY_TYPE" | "NODE" | ["Movie"] | ["seriesOrder"] | null | "INTEGER" | -| 27 | "wrote_locations" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["location"] | null | null | -| 25 | "wrote_year" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["year"] | null | null | -+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -27 rows ----- - -[NOTE] -==== -The `type` column returns `UNIQUENESS` for the node property uniqueness constraint and `RELATIONSHIP_UNIQUENESS` for the relationship property uniqueness constraint. -This will be updated in Neo4j 6.0. -Node property uniqueness constraints will be updated to `NODE_PROPERTY_UNIQUENESS` and relationship property uniqueness constraints to `RELATIONSHIP_PROPERTY_UNIQUENESS`. -==== - -====== - - -[[constraints-listing-constraints-with-filtering]] -=== Listing constraints with filtering - -One way of filtering the output from `SHOW CONSTRAINTS` by constraint type is the use of constraint type keywords, -listed in the xref::constraints/syntax.adoc#constraints-syntax-list-type-filter[syntax for listing constraints type filter table]. -For example, to show only property uniqueness constraints, use `SHOW UNIQUENESS CONSTRAINTS`. -Another more flexible way of filtering the output is to use the `WHERE` clause. -An example is to only show constraints on relationships. - - -.+SHOW CONSTRAINTS+ -====== - -.Query -[source, cypher, test-exclude-cols=id] ----- -SHOW EXISTENCE CONSTRAINTS -WHERE entityType = 'RELATIONSHIP' ----- - -This will only return the default output columns. -To get all columns, use `+SHOW INDEXES YIELD * WHERE ...+`. - -[queryresult] ----- -+-----------------------------------------------------------------------------------------------------------------------------------------+ -| id | name | type | entityType | labelsOrTypes | properties | ownedIndex | propertyType | -+-----------------------------------------------------------------------------------------------------------------------------------------+ -| 26 | "rel_exist_param" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["published"] | null | null | -| 27 | "wrote_locations" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["location"] | null | null | -| 25 | "wrote_year" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["year"] | null | null | -+-----------------------------------------------------------------------------------------------------------------------------------------+ -3 rows ----- - -====== - diff --git a/modules/ROOT/pages/constraints/index.adoc b/modules/ROOT/pages/constraints/index.adoc index 2d5677e04..f906e317b 100644 --- a/modules/ROOT/pages/constraints/index.adoc +++ b/modules/ROOT/pages/constraints/index.adoc @@ -1,124 +1,16 @@ -:description: This section explains how to manage constraints used for ensuring data integrity. +:description: Overview of Neo4j's constraints used for ensuring data integrity. include::https://raw.githubusercontent.com/neo4j-graphacademy/courses/main/asciidoc/courses/cypher-indexes-constraints/ad.adoc[] - -[[constraints]] = Constraints -This page contains an overview of the available constraints in Cypher, and information about how constraints can impact indexes. - -Adding constraints is an atomic operation that can take a while -- all existing data has to be scanned before a Neo4j DBMS can use a constraint. - -[[unique-node-property]] -== Unique node property constraints -Unique node property constraints, or node property uniqueness constraints, ensure that property values are unique for all nodes with a specific label. -For property uniqueness constraints on multiple properties, the combination of the property values is unique. -Node property uniqueness constraints do not require all nodes to have a unique value for the properties listed (nodes without all properties on which the constraint exists are not subject to this rule). - -For more information, see xref:constraints/examples.adoc#constraints-examples-node-uniqueness[examples of node property uniqueness constraints]. - -[role=label--new-5.7] -[[unique-relationship-property]] -== Unique relationship property constraints - -Unique relationship property constraints, or relationship property uniqueness constraints, ensure that property values are unique for all relationships with a specific type. -For property uniqueness constraints on multiple properties, the combination of the property values is unique. -Relationship property uniqueness constraints do not require all relationships to have a unique value for the properties listed (relationships without all properties on which the constraint exists are not subject to this rule). - -For more information, see xref:constraints/examples.adoc#constraints-examples-relationship-uniqueness[examples of relationship property uniqueness constraints]. - -[[node-property-existence]] -[role=label--enterprise-edition] -== Node property existence constraints - -Node property existence constraints ensure that a property exists for all nodes with a specific label. -Queries that try to create new nodes of the specified label, but without this property, will fail. -The same is true for queries that try to remove the mandatory property. - -For more information, see xref:constraints/examples.adoc#constraints-examples-node-property-existence[examples of node property existence constraints]. - -[[relationship-property-existence]] -[role=label--enterprise-edition] -== Relationship property existence constraints - -Relationship property existence constraints ensure that a property exists for all relationships with a specific type. -All queries that try to create relationships of the specified type, but without this property, will fail. -The same is true for queries that try to remove the mandatory property. - -For more information, see xref:constraints/examples.adoc#constraints-examples-relationship-property-existence[examples of relationship property existence constraints]. - -[[node-property-type]] -[role=label--enterprise-edition label--new-5.9] -== Node property type constraints - -Node property type constraints ensure that a property have the required property type for all nodes with a specific label. -Queries that try to add or modify this property to nodes of the specified label, but with a different property type, will fail. -Node property type constraints do not require all nodes to have the property (nodes without the property on which the constraint exists are not subject to this rule). - -For more information, see xref:constraints/examples.adoc#constraints-examples-node-property-type[examples of node property type constraints]. - -[[relationship-property-type]] -[role=label--enterprise-edition label--new-5.9] -== Relationship property type constraints - -Relationship property type constraints ensure that a property have the required property type for all relationships with a specific type. -Queries that try to add or modify this property to relationships of the specified type, but with a different property type, will fail. -Relationship property type constraints do not require all relationships to have the property (relationships without the property on which the constraint exists are not subject to this rule). - -For more information, see xref:constraints/examples.adoc#constraints-examples-relationship-property-type[examples of relationship property type constraints]. - -[[node-key]] -[role=label--enterprise-edition] -== Node key constraints - -Node key constraints ensure that, for a given label and set of properties: - -. All the properties exist on all the nodes with that label. -. The combination of the property values is unique. - -+ -Queries attempting to do any of the following will fail: - -* Create new nodes without all the properties or where the combination of property values is not unique. -* Remove one of the mandatory properties. -* Update the properties so that the combination of property values is no longer unique. - -For more information, see xref:constraints/examples.adoc#constraints-examples-node-key[examples of node key constraints]. - -[[relationship-key]] -[role=label--enterprise-edition label--new-5.7] -== Relationship key constraints - -Relationship key constraints ensure that, for a given type and set of properties: - -[lowerroman] -. All the properties exist on all the relationships with that type. -. The combination of the property values is unique. - -+ -Queries attempting to do any of the following will fail: - -* Create new relationships without all the properties or where the combination of property values is not unique. -* Remove one of the mandatory properties. -* Update the properties so that the combination of property values is no longer unique. - -For more information, see xref:constraints/examples.adoc#constraints-examples-relationship-key[examples of relationship key constraints]. - -[[multiple-constrains]] -== Multiple constraints on the same property combinations - - -Some constraint types are allowed on the same label/relationship type and property combination. -For example, it is possible to have a uniqueness and an existence constraint on the same label/relationship type and property combination, though this would be the equivalent of having a node or relationship key constraint. -A more useful example would be to combine a property type and an existence constraint to ensure that the property exists and has the given type. +Neo4j offers several constraints to ensure the quality and integrity of data in a graph. +The following constraints are available in Neo4j: -[[index-implications]] -== Implications on indexes +* *Property uniqueness constraints* ensure that the combined property values are unique for all nodes with a specific label or all relationships with a specific type. +* *Property existence constraints* ensure that a property exists either for all nodes with a specific label or for all relationships with a specific type. label:enterprise-edition[] +* *Property type constraints* ensure that a property has the required property type for all nodes with a specific label or for all relationships with a specific type. label:enterprise-edition[] +* *Key constraints* ensure that all properties exist and that the combined property values are unique for all nodes with a specific label or all relationships with a specific type.label:enterprise-edition[] -Creating a constraint has the following implications on indexes: +To learn more about creating, listing, and dropping these constraints, as well as information about index-backed constraints, constraint creation failures and data violation scenarios, and more, see xref:constraints/managing-constraints.adoc[]. -* Adding a node key, relationship key, or property uniqueness constraint on a single property also adds an index on that property, and therefore, an index of the same index type, label/relationship type, and property combination cannot be added separately. -* Adding a node key, relationship key, or property uniqueness constraint for a set of properties also adds an index on those properties, and therefore, an index of the same index type, label/relationship type, and properties combination cannot be added separately. -* Cypher will use these indexes for lookups just like other indexes. - Refer to xref:indexes/search-performance-indexes/managing-indexes.adoc[] for more details on indexes. -* If a node key, relationship key, or property uniqueness constraint is dropped and the backing index is still required, the index need to be created explicitly. +For reference material about the Cypher commands used to manage constraints, see xref:constraints/syntax.adoc[]. diff --git a/modules/ROOT/pages/constraints/managing-constraints.adoc b/modules/ROOT/pages/constraints/managing-constraints.adoc new file mode 100644 index 000000000..76d08beac --- /dev/null +++ b/modules/ROOT/pages/constraints/managing-constraints.adoc @@ -0,0 +1,1804 @@ +:description: Information about creating, listing, and dropping Neo4j's constraints. +include::https://raw.githubusercontent.com/neo4j-graphacademy/courses/main/asciidoc/courses/cypher-indexes-constraints/ad.adoc[] +:page-aliases: constraints/examples.adoc += Create, show, and drop constraints + +This page describes how to create, list, and drop constraints. +The following constraint types are available in Neo4j: + +* xref:constraints/managing-constraints.adoc#create-property-uniqueness-constraints[Property uniqueness constraints] +* xref:constraints/managing-constraints.adoc#create-property-existence-constraints[Property existence constraints] label:enterprise-edition[] +* xref:constraints/managing-constraints.adoc#create-property-type-constraints[Property type constraints] label:enterprise-edition[] +* xref:constraints/managing-constraints.adoc#create-key-constraints[Key constraints] label:enterprise-edition[] + + +[[create-constraint]] +== CREATE CONSTRAINT + +Constraints are created with the `CREATE CONSTRAINT` command. +When creating a constraint, it is recommended to provide a constraint name. +This name must be unique among both indexes and constraints. +If a name is not explicitly given, a unique name will be auto-generated. + + +[NOTE] +Creating a constraint requires the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/database-administration/#access-control-database-administration-constraints[`CREATE CONSTRAINT` privilege]. + +[NOTE] +Adding constraints is an atomic operation that can take a while -- all existing data has to be scanned before a Neo4j DBMS can use a constraint. + +[[create-property-uniqueness-constraints]] +=== Create property uniqueness constraints + +Property uniqueness constraints ensure that the property values are unique for all nodes with a specific label or all relationships with a specific type. +For composite property uniqueness constraints on multiple properties, it is the combination of property values that must be unique. +Queries that try to add duplicated property values will fail. + +Property uniqueness constraints do not require all nodes or relationships to have values for the properties listed in the constraint. +Only nodes or relationships that contain all properties specified in the constraint are subject to the uniqueness rule. +Nodes or relationships missing one or more of the specified properties are not subject to this rule. + +* xref:constraints/managing-constraints.adoc#create-single-property-uniqueness-constraint[] +* xref:constraints/managing-constraints.adoc#create-composite-property-uniqueness-constraint[] +* xref:constraints/managing-constraints.adoc#create-property-uniqueness-constraint-compliant-data[] + +[[create-single-property-uniqueness-constraint]] +==== Create a single property uniqueness constraint + +Single property uniqueness constraints are created with the following commands: + +* Node property uniqueness constraints: `CREATE CONSTRAINT constraint_name FOR (n:Label) REQUIRE n.property IS UNIQUE`. +* Relationship property uniqueness constraints: `CREATE CONSTRAINT constraint_name +FOR ()-[r:REL_TYPE]-() REQUIRE r.property IS UNIQUE`. + +For the full command syntax to create a property uniqueness constraint, see xref:constraints/syntax.adoc#create-property-uniqueness-constraints[Syntax -> Create property uniqueness constraints]. + +.Create a node property uniqueness constraint on a single property +====== + +.Create a constraint requiring `Book` nodes to have unique `isbn` properties +[source, cypher] +---- +CREATE CONSTRAINT book_isbn +FOR (book:Book) REQUIRE book.isbn IS UNIQUE +---- + +.Result +[source, queryresult] +---- +Added 1 constraint. +---- + + +====== + + +.Create a relationship property uniqueness constraint on a single property +====== + +.Create a constraint requiring `SEQUEL_OF` relationships to have unique `order` properties +[source, cypher] +---- +CREATE CONSTRAINT sequels +FOR ()-[sequel:SEQUEL_OF]-() REQUIRE sequel.order IS UNIQUE +---- + +.Result +[source, queryresult] +---- +Added 1 constraint. +---- + +====== + +[[create-composite-property-uniqueness-constraint]] +==== Create a composite property uniqueness constraint + +Constraints created for multiple properties are called composite constraints. +Note that the constrained properties must be parenthesized when creating composite property uniqueness constraints. + +* Node property uniqueness constraints: `CREATE CONSTRAINT constraint_name FOR (n:Label) REQUIRE (n.propertyName_1, ..., n.propertyName_n) IS UNIQUE`. +* Relationship property uniqueness constraints: `CREATE CONSTRAINT constraint_name FOR ()-[r:REL_TYPE]-() REQUIRE (r.propertyName_1, ..., r.propertyName_n) IS UNIQUE`. + +For the full command syntax to create a property uniqueness constraint, see xref:constraints/syntax.adoc#create-property-uniqueness-constraints[Syntax -> Create property uniqueness constraints]. + +.Create a composite node property uniqueness constraint on several properties +====== + +.Create a constraint requiring `Book` nodes to have unique combinations of `title` and `publicationYear` properties +[source, cypher] +---- +CREATE CONSTRAINT book_title_year +FOR (book:Book) REQUIRE (book.title, book.publicationYear) IS UNIQUE +---- + +.Result +[source, queryresult] +---- +Added 1 constraint. +---- + +====== + + +.Create a composite relationship property uniqueness constraint on several properties +====== + +.Create a constraint requiring `PREQUEL_OF` relationships to have unique combinations of `order` and `author` properties +[source, cypher] +---- +CREATE CONSTRAINT prequels +FOR ()-[prequel:PREQUEL_OF]-() REQUIRE (prequel.order, prequel.author) IS UNIQUE +---- + +.Result +[source, queryresult] +---- +Added 1 constraint. +---- + +====== + +[[create-property-uniqueness-constraint-compliant-data]] +==== Create data that complies with existing property uniqueness constraints + +.Create a node that complies with existing property uniqueness constraints +====== + +.Create a `Book` node with a unique `isbn` property +[source, cypher] +---- +CREATE (book:Book {isbn: '1449356265', title: 'Graph Databases'}) +---- + +.Result +[source, queryresult] +---- +Added 1 label, created 1 node, set 2 properties +---- + +====== + + +.Create a relationship that complies with existing property uniqueness constraints +====== + +.Create a `SEQUEL_OF` relationship with a unique `order` property +[source, cypher] +---- +CREATE (:Book {title: 'Spirit Walker'})-[:SEQUEL_OF {order: 1, seriesTitle: 'Chronicles of Ancient Darkness'}]->(:Book {title: 'Wolf Brother'}) +---- + +.Result +[source, queryresult] +---- +Added 2 labels, created 2 nodes, set 4 properties, created 1 relationship. +---- + +====== + +[role=label--enterprise-edition] +[[create-property-existence-constraints]] +=== Create property existence constraints + +Property existence constraints ensure that a property exists either for all nodes with a specific label or for all relationships with a specific type. +Queries that try to create new nodes of the specified label, or relationships of the specified type, without the constrained property will fail. +The same is true for queries that try to remove the mandatory property. + +* xref:constraints/managing-constraints.adoc#create-single-property-existence-constraint[] +* xref:constraints/managing-constraints.adoc#create-property-existence-constraint-compliant-data[] + + +[[create-single-property-existence-constraint]] +==== Create a single property existence constraint + +Property existence constraints on single properties are created with the following commands: + +* Node property existence constraint: `CREATE CONSTRAINT constraint_name FOR (n:Label) REQUIRE n.property IS NOT NULL`. +* Relationship property existence constraint: `CREATE CONSTRAINT constraint_name FOR ()-[r:REL_TYPE]-() REQUIRE r.property IS NOT NULL`. + +For the full command syntax to create an existence constraint, see xref:constraints/syntax.adoc#create-property-existence-constraints[Syntax -> Create property existence constraints]. + +[NOTE] +It is not possible to create composite existence constraints on several properties. + +.Create a node property existence constraint +====== + +.Create a constraint requiring `Author` nodes to have a `name` property +[source, cypher] +---- +CREATE CONSTRAINT author_name +FOR (author:Author) REQUIRE author.name IS NOT NULL +---- + +.Result +[source, queryresult] +---- +Added 1 constraint. +---- + +====== + + +.Create a relationship property existence constraint +====== + +.Create a constraint requiring `WROTE` relationships to have a `year` property +[source, cypher] +---- +CREATE CONSTRAINT wrote_year +FOR ()-[wrote:WROTE]-() REQUIRE wrote.year IS NOT NULL +---- + +.Result +[source, queryresult] +---- +Added 1 constraint. +---- + +====== + +[[create-property-existence-constraint-compliant-data]] +==== Create data that complies with existing property existence constraints + +.Create a node that complies with existing node property existence constraints +====== + +.Create an `Author` node with a `name` property: +[source, cypher] +---- +CREATE (author:Author {name:'Virginia Woolf', surname: 'Woolf'}) +---- + +.Result +[source, queryresult] +---- +Added 1 label, created 1 node, set 2 properties +---- + +====== + + +.Create a relationship that complies with existing relationship property existence constraints +====== + +.Create a `WROTE` relationship with a `year` property +[source, cypher] +---- +CREATE (author:Author {name: 'Emily Brontë', surname: 'Brontë'})-[wrote:WROTE {year: 1847, location: 'Haworth, United Kingdom', published: true}]->(book:Book {title:'Wuthering Heights', isbn: 9789186579296}) +---- + +.Result +[source, queryresult] +---- +Added 2 labels, created 2 nodes, set 7 properties, created 1 relationship +---- + +====== + + +[role=label--enterprise-edition] +[[create-property-type-constraints]] +=== Create property type constraints + +Property type constraints ensure that a property has the required data type for all nodes with a specific label or for all relationships with a specific type. +Queries that attempt to add this property with the wrong data type or modify this property in a way that changes its data type for nodes of the specified label or relationships of the specified type will fail. + +Property type constraints do not require all nodes or relationships to have the property. +Nodes or relationships without the constrained property are not subject to this rule. + +* xref:constraints/managing-constraints.adoc#create-single-property-type-constraint[] +* xref:constraints/managing-constraints.adoc#create-property-type-constraint-union-type[] +* xref:constraints/managing-constraints.adoc#type-constraints-allowed-properties[] +* xref:constraints/managing-constraints.adoc#fail-to-create-property-type-constraint-invalid-type[] +* xref:constraints/managing-constraints.adoc#create-property-type-constraint-compliant-data[] + +[[create-single-property-type-constraint]] +==== Create a single property type constraint + +Property type constraints are created with the following commands: + +* Node property type constraints: `CREATE CONSTRAINT constraint_name FOR (n:Label) REQUIRE n.property IS :: `. +* Relationship property type constraints: `CREATE CONSTRAINT constraint_name FOR ()-[r:REL_TYPE]-() REQUIRE r.property IS :: `. + +`` refers to a specific Cypher data type, such as `STRING` or `INTEGER`. +For the types that properties can be constrained by, see xref:constraints/managing-constraints.adoc#type-constraints-allowed-properties[], and for information about different data types in Cypher, see xref:values-and-types/index.adoc[]. +For the full command syntax to create a property type constraint, see xref:constraints/syntax.adoc#create-property-type-constraints[Syntax -> Create property type constraints]. + +[NOTE] +It is not possible to create composite property type constraints on several properties. + +.Create a node property type constraint +====== + +.Create a constraint requiring `title` properties on `Movie` nodes to be of type `STRING` +[source, cypher] +---- +CREATE CONSTRAINT movie_title +FOR (movie:Movie) REQUIRE movie.title IS :: STRING +---- + +.Result +[source, queryresult] +---- +Added 1 constraint. +---- +====== + +.Create a relationship property type constraint +====== + +.Create a constraint requiring `order` properties on `PART_OF` relationships to be of type `INTEGER` +[source, cypher] +---- +CREATE CONSTRAINT part_of +FOR ()-[part:PART_OF]-() REQUIRE part.order IS :: INTEGER +---- + +.Result +[source, queryresult] +---- +Added 1 constraint. +---- + +====== + +[[create-property-type-constraint-union-type]] +==== Create property type constraints with a union type + +A closed dynamic union allows a node or relationship property to maintain some type flexibility whilst preventing unexpected values from being stored. + +.Create a node property type constraint with a union type +====== + +.Create a constraint requiring `tagline` properties on `Movie` nodes to be either of type `STRING` or `LIST` +[source, cypher] +---- +CREATE CONSTRAINT movie_tagline +FOR (movie:Movie) REQUIRE movie.tagline IS :: STRING | LIST +---- + +.Result +[source, queryresult] +---- +Added 1 constraint. +---- + +====== + +.Create a relationship property type constraint with a union type +====== + +.Create a constraint requiring `tags` properties on `PART_OF` relationships to either of type `STRING` or `LIST` +[source, cypher] +---- +CREATE CONSTRAINT part_of_tags +FOR ()-[part:PART_OF]-() REQUIRE part.tags IS :: STRING | LIST +---- + +.Result +[source, queryresult] +---- +Added 1 constraint. +---- + +====== + +[[type-constraints-allowed-properties]] +==== Allowed types + +The allowed property types for property type constraints are: + +* `BOOLEAN` +* `STRING` +* `INTEGER` +* `FLOAT` +* `DATE` +* `LOCAL TIME` +* `ZONED TIME` +* `LOCAL DATETIME` +* `ZONED DATETIME` +* `DURATION` +* `POINT` +* `LIST` +* `LIST` +* `LIST` +* `LIST` +* `LIST` +* `LIST` +* `LIST` +* `LIST` +* `LIST` +* `LIST` +* `LIST` +* Any closed dynamic union of the above types, e.g. `INTEGER | FLOAT | STRING`. + +For a complete reference describing all types available in Cypher, see the section on xref::values-and-types/property-structural-constructed.adoc#types-synonyms[types and their synonyms]. + +[[fail-to-create-property-type-constraint-invalid-type]] +==== Creating property type constraints on invalid types will fail + +.Create a node property type constraint with an invalid type +====== + +.Create a constraint requiring `imdbScore` properties on `Movie` nodes to be of type `MAP` +[source, cypher, role=test-fail] +---- +CREATE CONSTRAINT score FOR (movie:Movie) REQUIRE movie.imdbScore IS :: MAP +---- + +.Error message +[source, error] +---- +Failed to create node property type constraint: Invalid property type `MAP`. +---- + +====== + +[[create-property-type-constraint-compliant-data]] +==== Create data that complies with existing property type constraints + +.Create a node that complies with existing node property type constraint +====== + +.Create an `Movie` node with a `STRING` `title` property +[source, cypher] +---- +CREATE (movie:Movie {title:'Iron Man'}) +---- + +.Result +[source, queryresult] +---- +Added 1 label, created 1 node, set 1 properties +---- + +====== + +.Create a relationship that complies with existing relationship property type constraint +====== + +.Create a `PART_OF` relationship with an `INTEGER` `order` property +[source, cypher] +---- +MATCH (movie:Movie {title:'Iron Man'}) +CREATE (movie)-[part:PART_OF {order: 3}]->(franchise:Franchise {name:'MCU'}) +---- + +.Result +[queryresult] +---- +Added 1 label, added 1 node, created 1 relationship, set 2 properties +---- + +====== + + + +[role=label--enterprise-edition] +[[create-key-constraints]] +=== Create key constraints + +Key constraints ensure that the property exist and the property value is unique for all nodes with a specific label or all relationships with a specific type. +For composite key constraints on multiple properties, all properties must exists and the combination of property values must be unique. + +Queries that try to create new nodes of the specified label, or relationships of the specified type, without the constrained property will fail. +The same is true for queries that try to remove the mandatory property or add duplicated property values. + +* xref:constraints/managing-constraints.adoc#create-single-property-key-constraint[] +* xref:constraints/managing-constraints.adoc#create-composite-key-constraint[] +* xref:constraints/managing-constraints.adoc#create-key-constraint-compliant-data[] + +[[create-single-property-key-constraint]] +==== Create a single property key constraint + +Single property key constraints are created with the following commands: + +* Node key constraints: `CREATE CONSTRAINT constraint_name FOR (n:Label) REQUIRE n.property IS NODE KEY`. +* Relationship key constraints: `CREATE CONSTRAINT constraint_name FOR ()-[r:REL_TYPE]-() REQUIRE r.property IS RELATIONSHIP KEY`. + +For the full command syntax to create a key constraint, see xref:constraints/syntax.adoc#create-key-constraints[Syntax -> Create key constraints]. + +.Create a node key constraint on a single property +====== + +.Create a constraint requiring `Director` nodes to have a unique `imdbId` property as a node key. +[source, cypher] +---- +CREATE CONSTRAINT director_imdbId +FOR (director:Director) REQUIRE (director.imdbId) IS NODE KEY +---- + +.Result +[source, queryresult] +---- +Added 1 constraint. +---- + +====== + + +.Create a relationship key constraint on a single property +====== + +.Create a constraint requiring `OWNS` relationships to have a unique `ownershipId` property as a relationship key +[source, cypher] +---- +CREATE CONSTRAINT ownershipId +FOR ()-[owns:OWNS]-() REQUIRE owns.ownershipId IS RELATIONSHIP KEY +---- + +.Result +[source, queryresult] +---- +Added 1 constraint. +---- + +====== + +[[create-composite-key-constraint]] +==== Create a composite key constraint + +Constraints created for multiple properties are called composite constraints. +Note that the constrained properties must be parenthesized when creating composite key constraints. + +Composite key constraints are created with the following commands: + +* Node key constraints: `CREATE CONSTRAINT constraint_name FOR (n:Label) REQUIRE (n.propertyName_1, ..., n.propertyName_n) IS NODE KEY`. +* Relationship key constraints: `CREATE CONSTRAINT constraint_name FOR ()-[r:REL_TYPE]-() REQUIRE (r.propertyName_1, ..., r.propertyName_n) IS RELATIONSHIP KEY`. + +For the full command syntax to create a key constraint, see xref:constraints/syntax.adoc#create-key-constraints[Syntax -> Create key constraints]. + +.Create a composite node key constraint on multiple properties +====== + +.Create a constraint requiring `Actor` nodes to have a unique combination of `firstname` and `surname` properties as a node key +[source, cypher] +---- +CREATE CONSTRAINT actor_fullname +FOR (actor:Actor) REQUIRE (actor.firstname, actor.surname) IS NODE KEY +---- + +.Result +[source, queryresult] +---- +Added 1 constraint. +---- + +====== + +.Create a composite relationship key constraint label on multiple properties +====== + +.Create a constraint requiring `KNOWS` relationships to have a unique combination of `since` and `how` properties as a relationship key +[source, cypher] +---- +CREATE CONSTRAINT knows_since_how +FOR ()-[knows:KNOWS]-() REQUIRE (knows.since, knows.how) IS RELATIONSHIP KEY +---- + +.Result +[source, queryresult] +---- +Added 1 constraint. +---- + +====== + +[[create-key-constraint-compliant-data]] +==== Create data that complies with existing key constraints + +.Create a node that complies with existing node key constraints +====== + +.Create an `Actor` node with unique `firstname` and `surname` properties +[source, cypher] +---- +CREATE (actor:Actor {firstname: 'Keanu', surname: 'Reeves'}) +---- + +.Result +[source, queryresult] +---- +Added 1 label, created 1 node, set 2 properties. +---- + +====== + + +.Create a relationship that complies with existing relationship key constraints +====== + +.Create a `KNOWS` relationship with unique `since` and `how` properties +[source, cypher] +---- +CREATE (:Actor {firstname: 'Jensen', surname: 'Ackles'})-[:KNOWS {since: 2008, how: 'coworkers', friend: true}]->(:Actor {firstname: 'Misha', surname: 'Collins'}) +---- + +.Result +[source, queryresult] +---- +Added 2 labels, created 2 nodes, set 7 properties, created 1 relationship. +---- + +====== + + +[[create-constraint-with-parameter]] +=== Create a constraint with a parameter + +All constraint types can be created with a parameterized name. + +.Create a node property uniqueness constraint using a parameter +====== + +.Parameters +[source, parameters] +---- +{ + "name": "node_uniqueness_param" +} +---- + +.Create a node property uniqueness constraint with a parameterized name +[source, cypher] +---- +CREATE CONSTRAINT $name +FOR (book:Book) REQUIRE book.prop1 IS UNIQUE +---- + +.Result +[source, queryresult] +---- +Added 1 constraint. +---- + +====== + +.Create a relationship property existence constraint using a parameter +====== + +.Parameters +[source, parameters] +---- +{ + "name": "rel_exist_param" +} +---- + +.Create a relationship property existence constraint with a parameterized name +[source, cypher] +---- +CREATE CONSTRAINT $name +FOR ()-[wrote:WROTE]-() REQUIRE wrote.published IS NOT NULL +---- + +.Result +[source, queryresult] +---- +Added 1 constraint. +---- + +====== + +[[handling-multiple-constraints]] +=== Handling multiple constraints + +Creating an already existing constraint will fail. +This includes the following scenarios: + +* Creating a constraint identical to an already existing constraint. +* Creating a constraint with a different name but on the same constraint type and same label/relationship type and property combination as an already existing constraint. +For property type constraints the property type also needs to be the same. +* Creating a constraint with the same name as an already existing constraint, regardless of what that constraint is. + +Additionally, some constraints cannot coexist and attempting to create them together will therefore fail as well. +This includes: + +* Property type constraints on the same label/relationship type and property but with different property types. +* Property uniqueness and key constraints on the same label/relationship type and property combination. + +However, some constraint types are allowed on the same label/relationship type and property combination. +For example, it is possible to have a property uniqueness and a property existence constraint on the same label/relationship type and property combination, though this would be the equivalent of having a node or relationship key constraint. +A more useful example would be to combine a property type and a property existence constraint to ensure that the property exists and has the given type. + +* xref:constraints/managing-constraints.adoc#create-a-constraint-if-not-exist[] +* xref:constraints/managing-constraints.adoc#create-an-already-existing-constraint[] + +[[create-a-constraint-if-not-exist]] +==== Handling existing constraints when creating a constraint + +To avoid failing on existing constraints, `IF NOT EXISTS` can be added to the `CREATE` command. +This will ensure that no error is thrown and that no constraint is created if any other constraint with the given name, or another constraint on the same constraint type and schema, or both, already exists. +For property type constraints the property type also needs to be the same. +Instead, an informational notification is returned showing the existing constraint which blocks the creation. + +.Create a constraint identical to an existing constraint +====== + +.Create a constraint requiring all `SEQUEL_OF` relationships to have unique `order` properties +[source, cypher] +---- +CREATE CONSTRAINT sequels IF NOT EXISTS +FOR ()-[sequel:SEQUEL_OF]-() REQUIRE sequel.order IS UNIQUE +---- + +Because the same constraint already exists, nothing will happen: + +.Result +[source, queryresult] +---- +(no changes, no records) +---- + +.Notification +[source] +---- +`CREATE CONSTRAINT sequels IF NOT EXISTS FOR ()-[e:SEQUEL_OF]-() REQUIRE (e.order) IS UNIQUE` has no effect. +`CONSTRAINT sequels FOR ()-[e:SEQUEL_OF]-() REQUIRE (e.order) IS UNIQUE` already exists. +---- + +====== + +.Create a relationship property uniqueness constraint when the same constraint with a different name already exists +====== + +.Create a constraint requiring all `SEQUEL_OF` relationships to have unique `order` properties +[source, cypher] +---- +CREATE CONSTRAINT new_sequels IF NOT EXISTS +FOR ()-[sequel:SEQUEL_OF]-() REQUIRE sequel.order IS UNIQUE +---- + +Because a constraint with a different name (`sequels`) on the same schema exists, nothing will happen: + +.Result +[source, queryresult] +---- +(no changes, no records) +---- + +.Notification +[source] +---- +`CREATE CONSTRAINT new_sequels IF NOT EXISTS FOR ()-[e:SEQUEL_OF]-() REQUIRE (e.order) IS UNIQUE` has no effect. +`CONSTRAINT sequels FOR ()-[e:SEQUEL_OF]-() REQUIRE (e.order) IS UNIQUE` already exists. +---- + +====== + +.Create a relationship property uniqueness constraint with the same name as an existing constraint of a different type +====== + +.Create a constraint requiring all `AUTHORED` relationships to have unique `name` properties +[source, cypher] +---- +CREATE CONSTRAINT author_name IF NOT EXISTS +FOR ()-[a:AUTHORED]-() REQUIRE a.name IS UNIQUE +---- + +Because a node property existence constraint named `author_name` already exists, nothing will happen: + +.Result +[source, queryresult] +---- +(no changes, no records) +---- + +.Notification +[source] +---- +`CREATE CONSTRAINT author_name IF NOT EXISTS FOR ()-[e:AUTHORED]-() REQUIRE (e.name) IS UNIQUE` has no effect. +`CONSTRAINT author_name FOR (e:Author) REQUIRE (e.name) IS NOT NULL` already exists. +---- + +====== + +[[create-an-already-existing-constraint]] +==== Creating an already existing constraint will fail + +Creating a constraint with the same name or on the same node label or relationship type and properties that are already constrained by a constraint of the same type will fail. +Property uniqueness and key constraints are also not allowed on the same schema. + +.Create a constraint identical to an existing constraint +====== + +.Create a constraint requiring all `SEQUEL_OF` relationships to have unique `order` properties, given an identical constraint already exists +[source, cypher, role=test-fail] +---- +CREATE CONSTRAINT sequels +FOR ()-[sequel:SEQUEL_OF]-() REQUIRE sequel.order IS UNIQUE +---- + +.Error message +[source, error] +---- +An equivalent constraint already exists, 'Constraint( id=5, name='sequels', type='RELATIONSHIP PROPERTY UNIQUENESS', schema=()-[:SEQUEL_OF {order}]-(), ownedIndex=4 )'. +---- + +====== + +.Create a constraint with a different name but on the same schema as an existing constraint +====== + +.Create a constraint requiring all `Book` nodes to have unique `isbn` properties, given that a constraint on that schema already exists +[source, cypher, role=test-fail] +---- +CREATE CONSTRAINT new_book_isbn +FOR (book:Book) REQUIRE book.isbn IS UNIQUE +---- + +.Error message +[source, error] +---- +Constraint already exists: Constraint( id=3, name='book_isbn', type='NODE PROPERTY UNIQUENESS', schema=(:Book {isbn}), ownedIndex=2 ) +---- + +====== + +.Creating a constraint with the same name but on a different schema as an existing constraint +====== + +.Create a constraint requiring all `AUTHORED` relationships to have unique `name` properties, given that a constraint on a different schema with the same name already exists +[source, cypher, role=test-fail] +---- +CREATE CONSTRAINT author_name +FOR ()-[a:AUTHORED]-() REQUIRE a.name IS UNIQUE +---- + +.Error message +[source, error] +---- +There already exists a constraint called 'author_name'. +---- + +====== + +.Creating a property type constraint on a property when a property type constraint constraining the property to a different type already exist +====== + +.Create a constraint requiring `order` properties on `PART_OF` relationships to be of type `FLOAT`, given a constraint requiring the same properties to be of type `INTEGER` already exists +[source, cypher, role=test-fail] +---- +CREATE CONSTRAINT new_part_of +FOR ()-[part:PART_OF]-() REQUIRE part.order IS :: FLOAT +---- + + +.Error message +[source, error] +---- +Conflicting constraint already exists: Constraint( id=21, name='part_of', type='RELATIONSHIP PROPERTY TYPE', schema=()-[:PART_OF {order}]-(), propertyType=INTEGER ) +---- + +====== + +.Creating a node key constraint on the same schema as an existing property uniqueness constraint +====== + +.Create a node key constraint on the properties `title` and `publicationYear` on nodes with the `Book` label, when a property uniqueness constraint already exists on the same label and property combination +[source, cypher, role=test-fail] +---- +CREATE CONSTRAINT book_titles FOR (book:Book) REQUIRE (book.title, book.publicationYear) IS NODE KEY +---- + +.Error message +[source, error] +---- +Constraint already exists: Constraint( id=7, name='book_title_year', type='UNIQUENESS', schema=(:Book {title, publicationYear}), ownedIndex=6 ) +---- + +====== + +[[constraints-and-indexes]] +=== Constraints and indexes + +* xref:constraints/managing-constraints.adoc#constraints-and-backing-indexes[] +* xref:constraints/managing-constraints.adoc#create-constraint-with-index-provider[] +* xref:constraints/managing-constraints.adoc#constraint-failures-and-indexes[] + +[[constraints-and-backing-indexes]] +==== Constraints and backing indexes + +Property uniqueness constraints and key constraints are backed by xref:indexes/search-performance-indexes/managing-indexes.adoc#create-range-index[range indexes]. +This means that creating a property uniqueness or key constraint will create a range index with the same name, node label/relationship type and property combination as its owning constraint. +Single property constraints will create single property indexes and multiple property composite constraints will create xref:indexes/search-performance-indexes/using-indexes.adoc#composite-indexes[composite indexes]. + +[NOTE] +Indexes of the same index type, label/relationship type, and property combination cannot be added separately. +However, dropping a property uniqueness or key constraint will also drop its backing index. +If the backing index is still required, the index needs to be explicitly re-created. + +Property uniqueness and key constraints require an index because it allows the system to quickly check if a node with the same label and property value or a relationship with the same type and property value already exists. +Without an index, the system would need to scan all nodes with the same label, which would be slow and inefficient, especially as the graph grows. +The index makes these checks much faster by enabling direct lookups instead of scanning the entire graph. +Cypher will use the indexes with an owning constraint in the same way that it utilizes other search-performance indexes. +For more information about how indexes impact query performance, see xref:indexes/search-performance-indexes/using-indexes.adoc[]. + +These indexes are listed in the `owningConstraint` column returned by the xref:indexes/search-performance-indexes/managing-indexes.adoc#list-indexes[`SHOW INDEX`] command, and the `ownedIndex` column returned by the xref:constraints/managing-constraints.adoc#list-constraints[`SHOW CONSTRAINT`] command. + +.List constraints with backing indexes +====== + +.Query +[source, cypher, test-exclude-cols=id] +---- +SHOW CONSTRAINTS WHERE ownedIndex IS NOT NULL +---- + +.Result +[source, queryresult] +---- ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| id | name | type | entityType | labelsOrTypes | properties | ownedIndex | propertyType | ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 21 | "actor_fullname" | "NODE_KEY" | "NODE" | ["Actor"] | ["firstname", "surname"] | "actor_fullname" | NULL | +| 3 | "book_isbn" | "UNIQUENESS" | "NODE" | ["Book"] | ["isbn"] | "book_isbn" | NULL | +| 7 | "book_title_year" | "UNIQUENESS" | "NODE" | ["Book"] | ["title", "publicationYear"] | "book_title_year" | NULL | +| 17 | "director_imdbId" | "NODE_KEY" | "NODE" | ["Director"] | ["imdbId"] | "director_imdbId" | NULL | +| 23 | "knows_since_how" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["KNOWS"] | ["since", "how"] | "knows_since_how" | NULL | +| 25 | "node_uniqueness_param" | "UNIQUENESS" | "NODE" | ["Book"] | ["prop1"] | "node_uniqueness_param" | NULL | +| 19 | "ownershipId" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["OWNS"] | ["ownershipId"] | "ownershipId" | NULL | +| 9 | "prequels" | "RELATIONSHIP_UNIQUENESS" | "RELATIONSHIP" | ["PREQUEL_OF"] | ["order", "author"] | "prequels" | NULL | +| 5 | "sequels" | "RELATIONSHIP_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order"] | "sequels" | NULL | ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +---- + +====== + +.List indexes with owning constraints +====== + +.Query +[source, cypher, test-exclude-cols=id] +---- +SHOW INDEXES WHERE owningConstraint IS NOT NULL +---- + +.Result +[source, queryresult] +---- ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| id | name | state | populationPercent | type | entityType | labelsOrTypes | properties | indexProvider | owningConstraint | lastRead | readCount | ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 20 | "actor_fullname" | "ONLINE" | 100.0 | "RANGE" | "NODE" | ["Actor"] | ["firstname", "surname"] | "range-1.0" | "actor_fullname" | 2024-10-07T12:12:51.893Z | 3 | +| 2 | "book_isbn" | "ONLINE" | 100.0 | "RANGE" | "NODE" | ["Book"] | ["isbn"] | "range-1.0" | "book_isbn" | 2024-10-07T11:58:09.252Z | 2 | +| 6 | "book_title_year" | "ONLINE" | 100.0 | "RANGE" | "NODE" | ["Book"] | ["title", "publicationYear"] | "range-1.0" | "book_title_year" | NULL | 0 | +| 16 | "director_imdbId" | "ONLINE" | 100.0 | "RANGE" | "NODE" | ["Director"] | ["imdbId"] | "range-1.0" | "director_imdbId" | NULL | 0 | +| 22 | "knows_since_how" | "ONLINE" | 100.0 | "RANGE" | "RELATIONSHIP" | ["KNOWS"] | ["since", "how"] | "range-1.0" | "knows_since_how" | 2024-10-07T12:12:51.894Z | 1 | +| 24 | "node_uniqueness_param" | "ONLINE" | 100.0 | "RANGE" | "NODE" | ["Book"] | ["prop1"] | "range-1.0" | "node_uniqueness_param" | NULL | 0 | +| 18 | "ownershipId" | "ONLINE" | 100.0 | "RANGE" | "RELATIONSHIP" | ["OWNS"] | ["ownershipId"] | "range-1.0" | "ownershipId" | NULL | 0 | +| 8 | "prequels" | "ONLINE" | 100.0 | "RANGE" | "RELATIONSHIP" | ["PREQUEL_OF"] | ["order", "author"] | "range-1.0" | "prequels" | NULL | 0 | +| 4 | "sequels" | "ONLINE" | 100.0 | "RANGE" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order"] | "range-1.0" | "sequels" | 2024-10-07T11:57:12.999Z | 1 | ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +---- + +====== + +[NOTE] +Property existence and property type constraints are not backed by indexes. + +[[create-constraint-with-index-provider]] +==== Creating constraints with an index provider + +Because property uniqueness and key constraints have backing indexes, an index provider can be provided when creating these constraints using the `OPTIONS` clause and the `indexProvider` option. + +The only valid value for the index provider is: + +* `range-1.0` label:default[] + + +.Create a node key constraint with a specified index provider +====== + +.Create a constraint requiring `Actor` nodes to have a unique `surname` property as a node key, specifying `range-1.0` as index provider +[source, cypher] +---- +CREATE CONSTRAINT constraint_with_provider +FOR (actor:Actor) REQUIRE actor.surname IS NODE KEY +OPTIONS { + indexProvider: 'range-1.0' +} +---- + +.Result +[source, queryresult] +---- +Added 1 constraint. +---- + +====== + +.Create a relationship property uniqueness constraint with a specified index provider +====== + +.Create a constraint requiring `SEQUEL_OF` relationships to have a unique combination of `order`, `seriesTitle`, and `number` properties, specifying `range-1.0` as index provider +[source, cypher] +---- +CREATE CONSTRAINT rel_constraint_with_options +FOR ()-[sequel:SEQUEL_OF]-() REQUIRE (sequel.order, sequel.seriesTitle, sequel.number) IS UNIQUE +OPTIONS { + indexProvider: 'range-1.0' +} +---- + +.Result +[source, queryresult] +---- +Added 1 constraint. +---- + +====== + +There are no valid index configuration values for the constraint-backing range indexes. + +[[constraint-failures-and-indexes]] +==== Constraint failures and indexes + +Attempting to create any type of constraint with the same name as an existing index will fail. + +.Creating a node property type constraint with the same name as an existing index +====== + +.Create an index with the name `directors` +[source, cypher] +---- +CREATE INDEX directors FOR (director:Director) ON (director.name) +---- + +.Create a node property type constraint with the name `directors` +[source, cypher, role=test-fail] +---- +CREATE CONSTRAINT directors FOR (movie:Movie) REQUIRE movie.director IS :: STRING +---- + +.Error message +[source, error] +---- +There already exists an index called 'directors'. +---- + +====== + +Creating key or property uniqueness constraints on the same schema as an existing index will fail. + +.Creating a node property uniqueness constraint on the same schema as an existing index +====== + +.Create an index for `wordCount` properties on `Book` nodes +[source, cypher] +---- +CREATE INDEX book_word_count FOR (book:Book) ON (book.wordCount) +---- + +.Create a constraint requiring all `Book` nodes to have unique `wordCount` properties +[source, cypher, role=test-fail] +---- +CREATE CONSTRAINT word_count FOR (book:Book) REQUIRE book.wordCount IS UNIQUE +---- + +.Error message +[source, error] +---- +There already exists an index (:Book {wordCount}). +A constraint cannot be created until the index has been dropped. +---- + +====== + + +[[constraints-and-data-violation-scenarios]] +=== Constraints and data violation scenarios + +* xref:constraints/managing-constraints.adoc#create-data-that-violates-a-constraint[] +* xref:constraints/managing-constraints.adoc#removing-an-existing-constrained-property-will-fail[] +* xref:constraints/managing-constraints.adoc#modifying-property-constrained-property-will-fail[] +* xref:constraints/managing-constraints.adoc#fail-to-create-constraint-due-to-existing-data[] + +[[create-data-that-violates-a-constraint]] +==== Creating data that violates existing constraints will fail + +.Existing constraints preventing data creation +[cols="4", options="header"] +|=== +| Constraint type +| Create nodes and relationships without an existence constrained property +| Create nodes and relationships with non-unique properties/property combinations +| Create nodes and relationships with the wrong property type + +| *Property uniqueness constraint* +| +^| ❌ +| + +| *Property existence constraint* +^| ❌ +| +| + +| *Property type constraint* +| +| +^| ❌ + +| *Key constraint* +^| ❌ +^| ❌ +| + +|=== + + +.Create a node that violates a node property uniqueness constraint +====== + +.Create a `Book` node with an `isbn` property that already exists +[source, cypher, role=test-fail] +---- +CREATE (book:Book {isbn: '1449356265', title: 'Graph Databases'}) +---- + +.Error message +[source, error] +---- +Node(0) already exists with label `Book` and property `isbn` = '1449356265' +---- + +====== + +.Create a node that violates an existing node property existence constraint +====== + +.Create an `Author` node without a `name` property, given a property existence constraint on `:Author(name)` +[source, cypher, role=test-fail] +---- +CREATE (author:Author {surname: 'Austen'}) +---- + +.Error message +[source, error] +---- +Node(0) with label `Author` must have the property `name` +---- + +====== + +.Create a relationship that violates an existing relationship property type constraint +====== + + +.Create a `PART_OF` relationship with a `STRING` `order` property, given a property type constraint on the relationship type `PART_OF` restricting the `order` property to `INTEGER` values +[source, cypher, role=test-fail] +---- +MATCH (movie:Movie {title:'Iron Man'}), (franchise:Franchise {name:'MCU'}) +CREATE (movie)-[part:PART_OF {order: '1'}]->(franchise) +---- + +.Error message +[source, error] +---- +Relationship(0) with type `PART_OF` has property `order` of wrong type `String`. Allowed types: INTEGER +---- + +====== + + +.Create a node that violates an existing node key constraint +====== + +.Create an `Actor` node without a `firstname` property, given a node key constraint on `:Actor(firstname, surname)` +[source, cypher, role=test-fail] +---- +CREATE (actor:Actor {surname: 'Wood'}) +---- + +.Error message +[source, error] +---- +Node(0) with label `Actor` must have the properties (`firstname`, `surname`) +---- + +====== + +[[removing-an-existing-constrained-property-will-fail]] +==== Removing existence and key constrained properties will fail + +.Remove a node property existence constrained property +====== + +.Remove the `name` property from an existing `Author` node, given a property existence constraint on `:Author(name)` +[source, cypher, role=test-fail] +---- +MATCH (author:Author {name: 'Virginia Woolf'}) +REMOVE author.name +---- + +.Error message +[source, error] +---- +Node(0) with label `Author` must have the property `name` +---- + +====== + + +.Remove a node key constrained property +====== + +.Remove the `firstname` property from an existing node `Actor`, given a node key constraint on `:Actor(firstname, surname)` +[source, cypher, role=test-fail] +---- +MATCH (actor:Actor {firstname: 'Keanu', surname: 'Reeves'}) +REMOVE actor.firstname +---- + +.Error message +[source, error] +---- +Node(0) with label `Actor` must have the properties (`firstname`, `surname`) +---- + +====== + +[[modifying-property-constrained-property-will-fail]] +==== Modifying type constrained properties will fail + +.Modify a type constrained property +====== + +.Modify the `title` for the `Movie` 'Iron Man' to an `INTEGER` value, given a constraint requiring `title` properties to be of type `STRING` +[source, cypher, role=test-fail] +---- +MATCH (m:Movie {title: 'Iron Man'}) +SET m.title = 13 +---- + +.Error message +[source, error] +---- +Node(9) with label `Movie` required the property `title` to be of type `STRING`, but was of type `INTEGER`. +---- + +====== + + +[[fail-to-create-constraint-due-to-existing-data]] +==== Creating constraints when there exists conflicting data will fail + +.Existing data preventing constraint creation +[cols="4", options="header"] +|=== +| Constraint type +| Non-existing property +| Non-unique property/property combination +| Property of wrong type + +| *Property uniqueness constraint* +| +^| ❌ +| + +| *Property existence constraint* +^| ❌ +| +| + +| *Property type constraint* +| +| +^| ❌ + +| *Key constraint* +^| ❌ +^| ❌ +| + +|=== + +.Create a node property uniqueness constraint when conflicting nodes exist +====== + +.Create two `Book` nodes with the same `name` property value +[source, cypher] +---- +CREATE (:Book {isbn: '9780393972832', title: 'Moby Dick'}), + (:Book {isbn: '9780763630188', title: 'Moby Dick'}) +---- + + +.Create a constraint requiring `Book` nodes to have unique `title` properties, when there already exists two `Book` nodes with the same `title` +[source, cypher, role=test-fail] +---- +CREATE CONSTRAINT book_title FOR (book:Book) REQUIRE book.title IS UNIQUE +---- + +In this case, the constraint cannot be created because it is in conflict with the existing graph. +Either use xref:indexes/search-performance-indexes/managing-indexes.adoc[indexes] instead, or remove/correct the offending nodes and then re-apply the constraint. + +.Error message +[source, error] +---- +Unable to create Constraint( name='book_title', type='UNIQUENESS', schema=(:Book {title}) ): +Both Node(0) and Node(1) have the label `Book` and property `title` = 'Moby Dick' +---- + +The constraint creation fails on the first offending nodes that are found. +This does not guarantee that there are no other offending nodes in the graph. +Therefore, all the data should be checked and cleaned up before re-attempting the constraint creation. + +.Find all offending nodes with the non-unique property values for the constraint above +[source, cypher] +---- +MATCH (book1:Book), (book2:Book) +WHERE book1.title = book2.title AND NOT book1 = book2 +RETURN book1, book2 +---- + +====== + + +.Create a relationship property existence constraint when conflicting relationships exist +====== + +.Create a constraint requiring all `WROTE` relationships to have a `language` property, when there already exists a `WROTE` relationship without a `language` property +[source, cypher, role=test-fail] +---- +CREATE CONSTRAINT wrote_language FOR ()-[wrote:WROTE]-() REQUIRE wrote.language IS NOT NULL +---- + +In this case, the constraint cannot be created because it is in conflict with the existing graph. +Remove or correct the offending relationships and then re-apply the constraint. + +.Error message +[source, error] +---- +Unable to create Constraint( type='RELATIONSHIP PROPERTY EXISTENCE', schema=()-[:WROTE {language}]-() ): +Relationship(0) with type `WROTE` must have the property `language`. Note that only the first found violation is shown. +---- + +The constraint creation fails on the first offending relationship that is found. +This does not guarantee that there are no other offending relationships in the graph. +Therefore, all the data should be checked and cleaned up before re-attempting the constraint creation. + + +.Find all offending relationships missing the property for the constraint above +[source, cypher] +---- +MATCH ()-[wrote:WROTE]-() +WHERE wrote.language IS NULL +RETURN wrote +---- + +====== + +.Generic `MATCH` queries to find the properties preventing the creation of particular constraints: +[options="header", cols="1,1m"] +|=== +| Constraint +| Query + +| Node property uniqueness constraint +a| +[source] +---- +MATCH (n1:Label), (n2:Label) +WHERE n1.prop = n2.prop AND NOT n1 = n2 +RETURN n1, n2 +---- + +| Relationship property uniqueness constraint +a| +[source] +---- +MATCH ()-[r1:REL_TYPE]->(), ()-[r2:REL_TYPE]->() +WHERE r1.prop = r2.prop AND NOT r1 = r2 +RETURN r1, r2 +---- + +| Node property existence constraint +a| +[source] +---- +MATCH (n:Label) +WHERE n.prop IS NULL +RETURN n +---- + +| Relationship property existence constraint +a| +[source] +---- +MATCH ()-[r:REL_TYPE]->() +WHERE r.prop IS NULL +RETURN r +---- + +| Node property type constraint +a| +[source] +---- +MATCH (n:Label) +WHERE n.prop IS NOT :: +RETURN n +---- + +| Relationship property type constraint +a| +[source] +---- +MATCH ()-[r:REL_TYPE]->() +WHERE r.prop IS NOT :: +RETURN r +---- + +| Node key constraint +a| +[source] +---- +MATCH (n1:Label), (n2:Label) +WHERE n1.prop = n2.prop AND NOT n1 = n2 +UNWIND [n1, n2] AS node +RETURN node, 'non-unique' AS reason +UNION +MATCH (n:Label) +WHERE n.prop IS NULL +RETURN n AS node, 'non-existing' AS reason +---- + +| Relationship key constraint +a| +[source] +---- +MATCH ()-[r1:REL_TYPE]->(), ()-[r2:REL_TYPE]->() +WHERE r1.prop = r2.prop AND NOT r1 = r2 +UNWIND [r1, r2] AS relationship +RETURN relationship, 'non-unique' AS reason +UNION +MATCH ()-[r:REL_TYPE]->() +WHERE r.prop IS NULL +RETURN r AS relationship, 'non-existing' AS reason +---- + +|=== + +[[list-constraints]] +== SHOW CONSTRAINTS + +To list all constraints with the default output columns, use `SHOW CONSTRAINTS`. +If all columns are required, use `SHOW CONSTRAINTS YIELD *`. +For the full command syntax to list constraints, see xref:constraints/syntax.adoc#list-constraints[Syntax -> SHOW CONSTRAINTS]. + +One of the output columns from `SHOW CONSTRAINTS` is the name of the constraint. +This can be used to drop the constraint with the xref::constraints/managing-constraints.adoc#drop-constraint[`DROP CONSTRAINT` command]. + +[NOTE] +Listing constraints requires the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/database-administration/#access-control-database-administration-constraints[`SHOW CONSTRAINTS` privilege]. + +.List all constraints with default output columns +====== + +.Query +[source, cypher, test-exclude-cols=id] +---- +SHOW CONSTRAINTS +---- + +.Result +[source, queryresult] +---- ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| id | name | type | entityType | labelsOrTypes | properties | ownedIndex | propertyType | ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 21 | "actor_fullname" | "NODE_KEY" | "NODE" | ["Actor"] | ["firstname", "surname"] | "actor_fullname" | NULL | +| 10 | "author_name" | "NODE_PROPERTY_EXISTENCE" | "NODE" | ["Author"] | ["name"] | NULL | NULL | +| 3 | "book_isbn" | "NODE_PROPERTY_UNIQUENESS" | "NODE" | ["Book"] | ["isbn"] | "book_isbn" | NULL | +| 7 | "book_title_year" | "NODE_PROPERTY_UNIQUENESS" | "NODE" | ["Book"] | ["title", "publicationYear"] | "book_title_year" | NULL | +| 28 | "constraint_with_provider" | "NODE_KEY" | "NODE" | ["Actor"] | ["surname"] | "constraint_with_provider" | NULL | +| 17 | "director_imdbId" | "NODE_KEY" | "NODE" | ["Director"] | ["imdbId"] | "director_imdbId" | NULL | +| 23 | "knows_since_how" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["KNOWS"] | ["since", "how"] | "knows_since_how" | NULL | +| 14 | "movie_tagline" | "NODE_PROPERTY_TYPE" | "NODE" | ["Movie"] | ["tagline"] | NULL | "STRING | LIST" | +| 12 | "movie_title" | "NODE_PROPERTY_TYPE" | "NODE" | ["Movie"] | ["title"] | NULL | "STRING" | +| 25 | "node_uniqueness_param" | "NODE_PROPERTY_UNIQUENESS" | "NODE" | ["Book"] | ["prop1"] | "node_uniqueness_param" | NULL | +| 19 | "ownershipId" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["OWNS"] | ["ownershipId"] | "ownershipId" | NULL | +| 13 | "part_of" | "RELATIONSHIP_PROPERTY_TYPE" | "RELATIONSHIP" | ["PART_OF"] | ["order"] | NULL | "INTEGER" | +| 15 | "part_of_tags" | "RELATIONSHIP_PROPERTY_TYPE" | "RELATIONSHIP" | ["PART_OF"] | ["tags"] | NULL | "STRING | LIST" | +| 9 | "prequels" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["PREQUEL_OF"] | ["order", "author"] | "prequels" | NULL | +| 30 | "rel_constraint_with_options" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order", "seriesTitle", "number"] | "rel_constraint_with_options" | NULL | +| 26 | "rel_exist_param" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["published"] | NULL | NULL | +| 5 | "sequels" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order"] | "sequels" | NULL | +| 11 | "wrote_year" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["year"] | NULL | NULL | ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +---- + +====== + +.List all constraints with full details +====== + +To return the full details of the constraints on a database, use `SHOW CONSTRAINTS YIELD *` + +.List all constraints with `YIELD *` +[source, cypher, test-exclude-cols=id] +---- +SHOW CONSTRAINTS YIELD * +---- + +.Result +[source, queryresult] +---- ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 21 | "actor_fullname" | "NODE_KEY" | "NODE" | ["Actor"] | ["firstname", "surname"] | "actor_fullname" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `actor_fullname` FOR (n:`Actor`) REQUIRE (n.`firstname`, n.`surname`) IS NODE KEY" | +| 10 | "author_name" | "NODE_PROPERTY_EXISTENCE" | "NODE" | ["Author"] | ["name"] | NULL | NULL | NULL | "CREATE CONSTRAINT `author_name` FOR (n:`Author`) REQUIRE (n.`name`) IS NOT NULL" | +| 3 | "book_isbn" | "NODE_PROPERTY_UNIQUENESS" | "NODE" | ["Book"] | ["isbn"] | "book_isbn" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `book_isbn` FOR (n:`Book`) REQUIRE (n.`isbn`) IS UNIQUE" | +| 7 | "book_title_year" | "NODE_PROPERTY_UNIQUENESS" | "NODE" | ["Book"] | ["title", "publicationYear"] | "book_title_year" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `book_title_year` FOR (n:`Book`) REQUIRE (n.`title`, n.`publicationYear`) IS UNIQUE" | +| 28 | "constraint_with_provider" | "NODE_KEY" | "NODE" | ["Actor"] | ["surname"] | "constraint_with_provider" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `constraint_with_provider` FOR (n:`Actor`) REQUIRE (n.`surname`) IS NODE KEY" | +| 17 | "director_imdbId" | "NODE_KEY" | "NODE" | ["Director"] | ["imdbId"] | "director_imdbId" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `director_imdbId` FOR (n:`Director`) REQUIRE (n.`imdbId`) IS NODE KEY" | +| 23 | "knows_since_how" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["KNOWS"] | ["since", "how"] | "knows_since_how" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `knows_since_how` FOR ()-[r:`KNOWS`]-() REQUIRE (r.`since`, r.`how`) IS RELATIONSHIP KEY" | +| 14 | "movie_tagline" | "NODE_PROPERTY_TYPE" | "NODE" | ["Movie"] | ["tagline"] | NULL | "STRING | LIST" | NULL | "CREATE CONSTRAINT `movie_tagline` FOR (n:`Movie`) REQUIRE (n.`tagline`) IS :: STRING | LIST" | +| 12 | "movie_title" | "NODE_PROPERTY_TYPE" | "NODE" | ["Movie"] | ["title"] | NULL | "STRING" | NULL | "CREATE CONSTRAINT `movie_title` FOR (n:`Movie`) REQUIRE (n.`title`) IS :: STRING" | +| 25 | "node_uniqueness_param" | "NODE_PROPERTY_UNIQUENESS" | "NODE" | ["Book"] | ["prop1"] | "node_uniqueness_param" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `node_uniqueness_param` FOR (n:`Book`) REQUIRE (n.`prop1`) IS UNIQUE" | +| 19 | "ownershipId" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["OWNS"] | ["ownershipId"] | "ownershipId" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `ownershipId` FOR ()-[r:`OWNS`]-() REQUIRE (r.`ownershipId`) IS RELATIONSHIP KEY" | +| 13 | "part_of" | "RELATIONSHIP_PROPERTY_TYPE" | "RELATIONSHIP" | ["PART_OF"] | ["order"] | NULL | "INTEGER" | NULL | "CREATE CONSTRAINT `part_of` FOR ()-[r:`PART_OF`]-() REQUIRE (r.`order`) IS :: INTEGER" | +| 15 | "part_of_tags" | "RELATIONSHIP_PROPERTY_TYPE" | "RELATIONSHIP" | ["PART_OF"] | ["tags"] | NULL | "STRING | LIST" | NULL | "CREATE CONSTRAINT `part_of_tags` FOR ()-[r:`PART_OF`]-() REQUIRE (r.`tags`) IS :: STRING | LIST" | +| 9 | "prequels" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["PREQUEL_OF"] | ["order", "author"] | "prequels" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `prequels` FOR ()-[r:`PREQUEL_OF`]-() REQUIRE (r.`order`, r.`author`) IS UNIQUE" | +| 30 | "rel_constraint_with_options" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order", "seriesTitle", "number"] | "rel_constraint_with_options" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `rel_constraint_with_options` FOR ()-[r:`SEQUEL_OF`]-() REQUIRE (r.`order`, r.`seriesTitle`, r.`number`) IS UNIQUE" | +| 26 | "rel_exist_param" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["published"] | NULL | NULL | NULL | "CREATE CONSTRAINT `rel_exist_param` FOR ()-[r:`WROTE`]-() REQUIRE (r.`published`) IS NOT NULL" | +| 5 | "sequels" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order"] | "sequels" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `sequels` FOR ()-[r:`SEQUEL_OF`]-() REQUIRE (r.`order`) IS UNIQUE" | +| 11 | "wrote_year" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["year"] | NULL | NULL | NULL | "CREATE CONSTRAINT `wrote_year` FOR ()-[r:`WROTE`]-() REQUIRE (r.`year`) IS NOT NULL" | ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +---- +====== + +[[list-constraints-with-filtering]] +=== Listing constraints with filtering + +The `SHOW CONSTRAINTS` command can be filtered in various ways. +The filtering of rows can be done using constraint type keywords or a `WHERE` clause, while filtering of columns is achieved by specifying the desired columns in a `YIELD` clause. + +.List only specific constraint types +====== + +.List only key constraints +[source, cypher, test-exclude-cols=id] +---- +SHOW KEY CONSTRAINTS +---- + +.Result +[source, queryresult] +---- ++--------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| id | name | type | entityType | labelsOrTypes | properties | ownedIndex | propertyType | ++--------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 21 | "actor_fullname" | "NODE_KEY" | "NODE" | ["Actor"] | ["firstname", "surname"] | "actor_fullname" | NULL | +| 28 | "constraint_with_provider" | "NODE_KEY" | "NODE" | ["Actor"] | ["surname"] | "constraint_with_provider" | NULL | +| 17 | "director_imdbId" | "NODE_KEY" | "NODE" | ["Director"] | ["imdbId"] | "director_imdbId" | NULL | +| 23 | "knows_since_how" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["KNOWS"] | ["since", "how"] | "knows_since_how" | NULL | +| 19 | "ownershipId" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["OWNS"] | ["ownershipId"] | "ownershipId" | NULL | ++--------------------------------------------------------------------------------------------------------------------------------------------------------------+ +---- + +For a full list of all the constraint types (and synonyms) available in this command see xref:constraints/syntax.adoc#list-constraints[Syntax -> SHOW CONSTRAINTS]. + +====== + + +.Filtering constraints using the `WHERE` clause +====== + +.List only constraints with a `RELATIONSHIP` `entityType` +[source, cypher, test-exclude-cols=id] +---- +SHOW CONSTRAINTS +WHERE entityType = 'RELATIONSHIP' +---- + +.Result +[source, queryresult] +---- ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| id | name | type | entityType | labelsOrTypes | properties | ownedIndex | propertyType | ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 23 | "knows_since_how" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["KNOWS"] | ["since", "how"] | "knows_since_how" | NULL | +| 19 | "ownershipId" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["OWNS"] | ["ownershipId"] | "ownershipId" | NULL | +| 13 | "part_of" | "RELATIONSHIP_PROPERTY_TYPE" | "RELATIONSHIP" | ["PART_OF"] | ["order"] | NULL | "INTEGER" | +| 15 | "part_of_tags" | "RELATIONSHIP_PROPERTY_TYPE" | "RELATIONSHIP" | ["PART_OF"] | ["tags"] | NULL | "STRING | LIST" | +| 9 | "prequels" | "RELATIONSHIP_UNIQUENESS" | "RELATIONSHIP" | ["PREQUEL_OF"] | ["order", "author"] | "prequels" | NULL | +| 30 | "rel_constraint_with_options" | "RELATIONSHIP_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order", "seriesTitle", "number"] | "rel_constraint_with_options" | NULL | +| 26 | "rel_exist_param" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["published"] | NULL | NULL | +| 5 | "sequels" | "RELATIONSHIP_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order"] | "sequels" | NULL | +| 11 | "wrote_year" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["year"] | NULL | NULL | ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +---- + +====== + + +.Returning specific columns for all constraints +====== + +It is possible to return only specific columns of the available constraints using the `YIELD` clause: + +.List only the `name`, `type`, and `createStatement` columns +[source, cypher, test-exclude-cols=id] +---- +SHOW CONSTRAINTS +YIELD name, type, createStatement +---- + +.Result +[source, queryresult] +---- ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| name | type | createStatement | ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| "actor_fullname" | "NODE_KEY" | "CREATE CONSTRAINT `actor_fullname` FOR (n:`Actor`) REQUIRE (n.`firstname`, n.`surname`) IS NODE KEY" | +| "author_name" | "NODE_PROPERTY_EXISTENCE" | "CREATE CONSTRAINT `author_name` FOR (n:`Author`) REQUIRE (n.`name`) IS NOT NULL" | +| "book_isbn" | "UNIQUENESS" | "CREATE CONSTRAINT `book_isbn` FOR (n:`Book`) REQUIRE (n.`isbn`) IS UNIQUE" | +| "book_title_year" | "UNIQUENESS" | "CREATE CONSTRAINT `book_title_year` FOR (n:`Book`) REQUIRE (n.`title`, n.`publicationYear`) IS UNIQUE" | +| "constraint_with_provider" | "NODE_KEY" | "CREATE CONSTRAINT `constraint_with_provider` FOR (n:`Actor`) REQUIRE (n.`surname`) IS NODE KEY" | +| "director_imdbId" | "NODE_KEY" | "CREATE CONSTRAINT `director_imdbId` FOR (n:`Director`) REQUIRE (n.`imdbId`) IS NODE KEY" | +| "knows_since_how" | "RELATIONSHIP_KEY" | "CREATE CONSTRAINT `knows_since_how` FOR ()-[r:`KNOWS`]-() REQUIRE (r.`since`, r.`how`) IS RELATIONSHIP KEY" | +| "movie_tagline" | "NODE_PROPERTY_TYPE" | "CREATE CONSTRAINT `movie_tagline` FOR (n:`Movie`) REQUIRE (n.`tagline`) IS :: STRING | LIST" | +| "movie_title" | "NODE_PROPERTY_TYPE" | "CREATE CONSTRAINT `movie_title` FOR (n:`Movie`) REQUIRE (n.`title`) IS :: STRING" | +| "node_uniqueness_param" | "UNIQUENESS" | "CREATE CONSTRAINT `node_uniqueness_param` FOR (n:`Book`) REQUIRE (n.`prop1`) IS UNIQUE" | +| "ownershipId" | "RELATIONSHIP_KEY" | "CREATE CONSTRAINT `ownershipId` FOR ()-[r:`OWNS`]-() REQUIRE (r.`ownershipId`) IS RELATIONSHIP KEY" | +| "part_of" | "RELATIONSHIP_PROPERTY_TYPE" | "CREATE CONSTRAINT `part_of` FOR ()-[r:`PART_OF`]-() REQUIRE (r.`order`) IS :: INTEGER" | +| "part_of_tags" | "RELATIONSHIP_PROPERTY_TYPE" | "CREATE CONSTRAINT `part_of_tags` FOR ()-[r:`PART_OF`]-() REQUIRE (r.`tags`) IS :: STRING | LIST" | +| "prequels" | "RELATIONSHIP_UNIQUENESS" | "CREATE CONSTRAINT `prequels` FOR ()-[r:`PREQUEL_OF`]-() REQUIRE (r.`order`, r.`author`) IS UNIQUE" | +| "rel_constraint_with_options" | "RELATIONSHIP_UNIQUENESS" | "CREATE CONSTRAINT `rel_constraint_with_options` FOR ()-[r:`SEQUEL_OF`]-() REQUIRE (r.`order`, r.`seriesTitle`, r.`number`) IS UNIQUE" | +| "rel_exist_param" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "CREATE CONSTRAINT `rel_exist_param` FOR ()-[r:`WROTE`]-() REQUIRE (r.`published`) IS NOT NULL" | +| "sequels" | "RELATIONSHIP_UNIQUENESS" | "CREATE CONSTRAINT `sequels` FOR ()-[r:`SEQUEL_OF`]-() REQUIRE (r.`order`) IS UNIQUE" | +| "wrote_year" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "CREATE CONSTRAINT `wrote_year` FOR ()-[r:`WROTE`]-() REQUIRE (r.`year`) IS NOT NULL" | ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +---- + +====== + + +[[list-constraints-result-columns]] +=== Result columns for listing constraints + +.Listing constraints output +[options="header", width="100%", cols="4m,6a,2m"] +|=== +| Column | Description | Type + +| id +| The id of the constraint. label:default-output[] +| INTEGER + +| name +| Name of the constraint (explicitly set by the user or automatically assigned). label:default-output[] +| STRING + +| type +| The ConstraintType of this constraint (`NODE_PROPERTY_UNIQUENESS`, `RELATIONSHIP_PROPERTY_UNIQUENESS`, `NODE_PROPERTY_EXISTENCE`, `RELATIONSHIP_PROPERTY_EXISTENCE`, `NODE_PROPERTY_TYPE`, `RELATIONSHIP_PROPERTY_TYPE`, `NODE_KEY`, or `RELATIONSHIP_KEY`). label:default-output[] + +| STRING + +| entityType +| Type of entities this constraint represents (`NODE` or `RELATIONSHIP`). label:default-output[] +| STRING + +| labelsOrTypes +| The labels or relationship types of this constraint. +The list returned will only include a single value (the name of the constrained node label or relationship type). label:default-output[] +| LIST + +| properties +| The properties of this constraint. label:default-output[] +| LIST + +| ownedIndex +| The name of the index associated with the constraint or `null`, in case no index is associated with it. label:default-output[] +| STRING + +| propertyType +| The property type the property is restricted to for property type constraints, or `null` for the other constraints. +label:default-output[] +| STRING + +| options +| The options passed to `CREATE` command, for the index associated to the constraint, or `null` if no index is associated with the constraint. +| MAP + +| createStatement +| Statement used to create the constraint. +| STRING + +|=== + +[[drop-constraint]] +== DROP CONSTRAINT + +Constraints are dropped using the `DROP CONSTRAINT` command. +For the full command syntax to drop constraints, see xref:constraints/syntax.adoc#drop-constraint[Syntax -> DROP CONSTRAINT]. + +[NOTE] +Dropping a constraint requires the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/database-administration/#access-control-database-administration-constraints[`DROP CONSTRAINT` privilege]. + +[[drop-constraint-by-name]] +=== Drop a constraint by name + +A constraint can be dropped using the name with the `DROP CONSTRAINT constraint_name` command. +It is the same command for all constraint types. +The name of the constraint can be found using the xref:constraints/managing-constraints.adoc#list-constraints[`SHOW CONSTRAINTS` command], given in the output column `name`. + +.Drop a constraint by name +====== + +.Drop the constraint `book_isbn` +[source, cypher] +---- +DROP CONSTRAINT book_isbn +---- + +.Result +[source, queryresult] +---- +Removed 1 constraint. +---- + +====== + +[[drop-constraint-with-parameter]] +=== Drop a constraint with a parameter + +Constraints can be dropped with a parameterized name. + +.Drop a constraint using a parameter +====== + +.Parameters +[source, parameters] +---- +{ + "name": "actor_fullname" +} +---- + +.Drop a constraint with a parameterized name +[source, cypher] +---- +DROP CONSTRAINT $name +---- + +.Result +[source, queryresult] +---- +Removed 1 constraint. +---- + +====== + +[[drop-constraint-nonexisting-constraint]] +=== Drop a non-existing constraint + +If it is uncertain if any constraint with a given name exists and you want to drop it if it does but not get an error should it not, use `IF EXISTS`. +This will ensure that no error is thrown. +Instead, an informational notification is returned stating that the constraint does not exist. + +.Drop a non-existing constraint +====== + +.Drop the non-existing constraint `missing_constraint_name` +[source, cypher] +---- +DROP CONSTRAINT missing_constraint_name IF EXISTS +---- + +.Result +[source, queryresult] +---- +(no changes, no records) +---- + +.Notification +[source] +---- +`DROP CONSTRAINT missing_constraint_name IF EXISTS` has no effect. `missing_constraint_name` does not exist. +---- + +====== \ No newline at end of file diff --git a/modules/ROOT/pages/constraints/syntax.adoc b/modules/ROOT/pages/constraints/syntax.adoc index 1a1f5a6f9..49dbe30db 100644 --- a/modules/ROOT/pages/constraints/syntax.adoc +++ b/modules/ROOT/pages/constraints/syntax.adoc @@ -4,35 +4,37 @@ = Syntax :check-mark: icon:check[] +This page contains the syntax for creating, listing, and dropping the constraints available in Neo4j. + +More details about the syntax can be found in the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/syntax/[Operations Manual -> Cypher syntax for administration commands]. + [[constraints-syntax-create]] -== Syntax for creating constraints +== CREATE CONSTRAINT -Best practice when creating a constraint is to give the constraint a name. +Constraints are created with the `CREATE CONSTRAINT` command. +When creating a constraint, it is recommended to provide a constraint name. This name must be unique among both indexes and constraints. If a name is not explicitly given, a unique name will be auto-generated. +[NOTE] +Creating a constraint requires the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/database-administration/#access-control-database-administration-constraints[`CREATE CONSTRAINT` privilege]. + The `CREATE CONSTRAINT` command is optionally idempotent. This means its default behavior is to throw an error if an attempt is made to create the same constraint twice. With the `IF NOT EXISTS` flag, no error is thrown and nothing happens should a constraint with the same name or same schema and constraint type already exist. It may still throw an error if conflicting data, indexes, or constraints exist. Examples of this are nodes with missing properties, indexes with the same name, or constraints with same schema but a different conflicting constraint type. -As of Neo4j 5.17, an informational notification is returned in case nothing happens showing the existing constraint which blocks the creation. +An informational notification is returned in case nothing happens showing the existing constraint which blocks the creation. For constraints that are backed by an index, the index provider for the backing index can be specified using the `OPTIONS` clause. Only one valid value exists for the index provider, `range-1.0`, which is the default value. There is no supported index configuration for range indexes. -[NOTE] -==== -Creating a constraint requires the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/database-administration/#access-control-database-administration-constraints[`CREATE CONSTRAINT` privilege]. -==== - -[[constraints-syntax-create-node-unique]] -=== Node property uniqueness constraint - -This command creates a property uniqueness constraint on nodes with the specified label and properties. +[[create-property-uniqueness-constraints]] +=== Create property uniqueness constraints -[source, syntax, role="noheader", indent=0] +.Syntax for creating a node property uniqueness constraint on a single property +[source, syntax] ---- CREATE CONSTRAINT [constraint_name] [IF NOT EXISTS] FOR (n:LabelName) @@ -40,7 +42,8 @@ REQUIRE n.propertyName IS [NODE] UNIQUE [OPTIONS "{" option: value[, ...] "}"] ---- -[source, syntax, role="noheader", indent=0] +.Syntax for creating a composite node property uniqueness constraint on multiple properties +[source, syntax] ---- CREATE CONSTRAINT [constraint_name] [IF NOT EXISTS] FOR (n:LabelName) @@ -48,15 +51,8 @@ REQUIRE (n.propertyName_1, ..., n.propertyName_n) IS [NODE] UNIQUE [OPTIONS "{" option: value[, ...] "}"] ---- -Index provider can be specified using the `OPTIONS` clause. - -[role=label--new-5.7] -[[constraints-syntax-create-rel-unique]] -=== Relationship property uniqueness constraint - -This command creates a property uniqueness constraint on relationships with the specified relationship type and properties. - -[source, syntax, role="noheader", indent=0] +.Syntax for creating a relationship property uniqueness constraint on a single property +[source, syntax] ---- CREATE CONSTRAINT [constraint_name] [IF NOT EXISTS] FOR ()-"["r:RELATIONSHIP_TYPE"]"-() @@ -64,7 +60,8 @@ REQUIRE r.propertyName IS [REL[ATIONSHIP]] UNIQUE [OPTIONS "{" option: value[, ...] "}"] ---- -[source, syntax, role="noheader", indent=0] +.Syntax for creating a composite relationship property uniqueness constraint on multiple properties +[source, syntax] ---- CREATE CONSTRAINT [constraint_name] [IF NOT EXISTS] FOR ()-"["r:RELATIONSHIP_TYPE"]"-() @@ -72,15 +69,17 @@ REQUIRE (r.propertyName_1, ..., r.propertyName_n) IS [REL[ATIONSHIP]] UNIQUE [OPTIONS "{" option: value[, ...] "}"] ---- -Index provider can be specified using the `OPTIONS` clause. +An index provider can be specified using the `OPTIONS` clause. -[role=label--enterprise-edition] -[[constraints-syntax-create-node-exists]] -=== Node property existence constraint +For examples on how to create property uniqueness constraints, see xref:constraints/managing-constraints.adoc#create-property-uniqueness-constraints[Create, show, and drop constraints -> Create property uniqueness constraint]. +Property uniqueness constraints are xref:constraints/managing-constraints.adoc#constraints-and-indexes[index-backed]. -This command creates a property existence constraint on nodes with the specified label and property. +[role=label--enterprise-edition] +[[create-property-existence-constraints]] +=== Create property existence constraints -[source, syntax, role="noheader", indent=0] +.Syntax for creating a node property existence constraint +[source, syntax] ---- CREATE CONSTRAINT [constraint_name] [IF NOT EXISTS] FOR (n:LabelName) @@ -88,19 +87,8 @@ REQUIRE n.propertyName IS NOT NULL [OPTIONS "{" "}"] ---- -[NOTE] -==== -There are no supported `OPTIONS` values for existence constraints, but an empty options map is allowed for consistency. -==== - - -[role=label--enterprise-edition] -[[constraints-syntax-create-rel-exists]] -=== Relationship property existence constraint - -This command creates a property existence constraint on relationships with the specified relationship type and property. - -[source, syntax, role="noheader", indent=0] +.Syntax for creating a relationship property existence constraint +[source, syntax] ---- CREATE CONSTRAINT [constraint_name] [IF NOT EXISTS] FOR ()-"["r:RELATIONSHIP_TYPE"]"-() @@ -108,18 +96,16 @@ REQUIRE r.propertyName IS NOT NULL [OPTIONS "{" "}"] ---- -[NOTE] -==== -There are no supported `OPTIONS` values for existence constraints, but an empty options map is allowed for consistency. -==== +There are no supported `OPTIONS` values for property existence constraints, but an empty options map is allowed for consistency. -[role=label--enterprise-edition label--new-5.9] -[[constraints-syntax-create-node-prop-type]] -=== Node property type constraint +For examples on how to create property existence constraints, see xref:constraints/managing-constraints.adoc#create-property-existence-constraints[Create, show, and drop constraints -> Create property existence constraints]. -This command creates a property type constraint on nodes with the specified label and property. +[role=label--enterprise-edition] +[[create-property-type-constraints]] +=== Create property type constraints -[source, syntax, role="noheader", indent=0] +.Syntax for creating a node property type constraint +[source, syntax] ---- CREATE CONSTRAINT [constraint_name] [IF NOT EXISTS] FOR (n:LabelName) @@ -127,49 +113,8 @@ REQUIRE n.propertyName {[IS] :: | IS TYPED} [OPTIONS "{" "}"] ---- -The three variations of the expression, `IS ::`, `::`, and `IS TYPED` are syntactic synonyms for the same expression. -The preferred syntax is the `IS ::` variant. - -Where `` is one of the following property types: - -* `BOOLEAN` -* `STRING` -* `INTEGER` -* `FLOAT` -* `DATE` -* `LOCAL TIME` -* `ZONED TIME` -* `LOCAL DATETIME` -* `ZONED DATETIME` -* `DURATION` -* `POINT` -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* Any closed dynamic union of the above types, e.g. `INTEGER | FLOAT | STRING`. label:new[Introduced in 5.11] - -Allowed syntax variations of these types are listed xref::values-and-types/property-structural-constructed.adoc#types-synonyms[here]. - -[NOTE] -==== -There are no supported `OPTIONS` values for property type constraints, but an empty options map is allowed for consistency. -==== - -[role=label--enterprise-edition label--new-5.9] -[[constraints-syntax-create-rel-prop-type]] -=== Relationship property type constraint - -This command creates a property type constraint on relationships with the specified relationship type and property. - -[source, syntax, role="noheader", indent=0] +.Syntax for creating a relationship property type constraint +[source, syntax] ---- CREATE CONSTRAINT [constraint_name] [IF NOT EXISTS] FOR ()-"["r:RELATIONSHIP_TYPE"]"-() @@ -193,33 +138,32 @@ Where `` is one of the following property types: * `ZONED DATETIME` * `DURATION` * `POINT` -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* `LIST` label:new[Introduced in 5.10] -* Any closed dynamic union of the above types, e.g. `INTEGER | FLOAT | STRING`. label:new[Introduced in 5.11] - -Allowed syntax variations of these types are listed xref::values-and-types/property-structural-constructed.adoc#types-synonyms[here]. +* `LIST` +* `LIST` +* `LIST` +* `LIST` +* `LIST` +* `LIST` +* `LIST` +* `LIST` +* `LIST` +* `LIST` +* `LIST` +* Any closed dynamic union of the above types, e.g. `INTEGER | FLOAT | STRING`. + +Allowed syntax variations of these types are listed in xref::values-and-types/property-structural-constructed.adoc#types-synonyms[Types and their synonyms]. -[NOTE] -==== There are no supported `OPTIONS` values for property type constraints, but an empty options map is allowed for consistency. -==== -[role=label--enterprise-edition] -[[constraints-syntax-create-node-key]] -=== Node key constraint +For examples on how to create property type constraints, see xref:constraints/managing-constraints.adoc#create-property-type-constraint[Create, show, and drop constraints -> Create property type constraints]. -This command creates a node key constraint on nodes with the specified label and properties. -[source, syntax, role="noheader", indent=0] +[role=label--enterprise-edition] +[[create-key-constraints]] +=== Create key constraints + +.Syntax for creating a node key constraint on a single property +[source, syntax] ---- CREATE CONSTRAINT [constraint_name] [IF NOT EXISTS] FOR (n:LabelName) @@ -227,7 +171,8 @@ REQUIRE n.propertyName IS [NODE] KEY [OPTIONS "{" option: value[, ...] "}"] ---- -[source, syntax, role="noheader", indent=0] +.Syntax for creating a composite node key constraint on multiple properties +[source, syntax] ---- CREATE CONSTRAINT [constraint_name] [IF NOT EXISTS] FOR (n:LabelName) @@ -235,15 +180,8 @@ REQUIRE (n.propertyName_1, ..., n.propertyName_n) IS [NODE] KEY [OPTIONS "{" option: value[, ...] "}"] ---- -Index provider can be specified using the `OPTIONS` clause. - -[role=label--enterprise-edition label--new-5.7] -[[constraints-syntax-create-rel-key]] -=== Relationship key constraint - -This command creates a relationship key constraint on relationships with the specified relationship type and properties. - -[source, syntax, role="noheader", indent=0] +.Syntax for creating a relationship key constraint on a single property +[source, syntax] ---- CREATE CONSTRAINT [constraint_name] [IF NOT EXISTS] FOR ()-"["r:RELATIONSHIP_TYPE"]"-() @@ -251,7 +189,8 @@ REQUIRE r.propertyName IS [REL[ATIONSHIP]] KEY [OPTIONS "{" option: value[, ...] "}"] ---- -[source, syntax, role="noheader", indent=0] +.Syntax for creating a composite relationship key constraint on multiple properties +[source, syntax] ---- CREATE CONSTRAINT [constraint_name] [IF NOT EXISTS] FOR ()-"["r:RELATIONSHIP_TYPE"]"-() @@ -259,42 +198,26 @@ REQUIRE (r.propertyName_1, ..., r.propertyName_n) IS [REL[ATIONSHIP]] KEY [OPTIONS "{" option: value[, ...] "}"] ---- -Index provider can be specified using the `OPTIONS` clause. - - -[[constraints-syntax-drop]] -== Syntax for dropping constraints - -Dropping a constraint is done by specifying the name of the constraint. - -[source, syntax, role="noheader", indent=0] ----- -DROP CONSTRAINT constraint_name [IF EXISTS] ----- - -This drop command is optionally idempotent. This means its default behavior is to throw an error if an attempt is made to drop the same constraint twice. -With the `IF EXISTS` flag, no error is thrown and nothing happens should the constraint not exist. -As of Neo4j 5.17, an informational notification is instead returned detailing that the constraint does not exist. +An index provider can be specified using the `OPTIONS` clause. -[NOTE] -==== -Dropping a constraint requires the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/database-administration/#access-control-database-administration-constraints[`DROP CONSTRAINT` privilege]. -==== +For examples on how to create key constraints, see xref:constraints/managing-constraints.adoc#create-key-constraints[Create, show, and drop constraints -> Create key constraints]. +Key constraints are xref:constraints/managing-constraints.adoc#constraints-and-indexes[index-backed]. -[[constraints-syntax-list]] -== Syntax for listing constraints +[[list-constraints]] +== SHOW CONSTRAINTS -List constraints in the database, either all or filtered on constraint type. +To list all constraints with the default output columns, use `SHOW CONSTRAINTS`. +If all columns are required, use `SHOW CONSTRAINTS YIELD *`. +If only specific columns are required, use `SHOW CONSTRAINTS YIELD field[, ...]`. +The `SHOW CONSTRAINTS` clause can also be filtered using the xref:clauses/where.adoc[`WHERE`] clause. [NOTE] -==== Listing constraints requires the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/database-administration/#access-control-database-administration-constraints[`SHOW CONSTRAINTS` privilege]. -==== -The simple version of the command allows for a `WHERE` clause and will give back the default set of output columns: -[source, syntax, role="noheader", indent=0] +.Syntax to list constraints with default return columns +[source, syntax] ---- SHOW [ ALL @@ -314,9 +237,8 @@ SHOW [ [WHERE expression] ---- -To get the full set of output columns, a yield clause is needed: - -[source, syntax, role="noheader", indent=0] +.Syntax for listing constraints with full return columns +[source, syntax] ---- SHOW [ ALL @@ -338,7 +260,6 @@ YIELD { * | field[, ...] } [ORDER BY field[, ...]] [SKIP n] [LIMIT n] [RETURN field[, ...] [ORDER BY field[, ...]] [SKIP n] [LIMIT n]] ---- - The type filtering keywords filters the returned constraints on constraint type: [[constraints-syntax-list-type-filter]] @@ -353,15 +274,12 @@ This is the default if none is given. |NODE UNIQUE[NESS] | Returns the node property uniqueness constraints. -label:new[Introduced in 5.7] |REL[ATIONSHIP] UNIQUE[NESS] | Returns the relationship property uniqueness constraints. -label:new[Introduced in 5.7] |UNIQUE[NESS] | Returns all property uniqueness constraints, for both nodes and relationships. -label:new[Allowing `UNIQUENESS` was introduced in 5.3] |NODE [PROPERTY] EXIST[ENCE] | Returns the node property existence constraints. @@ -374,77 +292,46 @@ label:new[Allowing `UNIQUENESS` was introduced in 5.3] |NODE PROPERTY TYPE | Returns the node property type constraints. -label:new[Introduced in 5.9] |REL[ATIONSHIP] PROPERTY TYPE | Returns the relationship property type constraints. -label:new[Introduced in 5.9] |PROPERTY TYPE | Returns all property type constraints, for both nodes and relationships. -label:new[Introduced in 5.9] |NODE KEY | Returns the node key constraints. |REL[ATIONSHIP] KEY | Returns the relationship key constraints. -label:new[Introduced in 5.7] |KEY | Returns all node and relationship key constraints. -label:new[Introduced in 5.7] - -|=== - - -The returned columns from the show command is: -.Listing constraints output -[options="header", width="100%", cols="4m,6a,2m"] |=== -| Column | Description | Type - -| id -| The id of the constraint. label:default-output[] -| INTEGER - -| name -| Name of the constraint (explicitly set by the user or automatically assigned). label:default-output[] -| STRING -| type -| The ConstraintType of this constraint (`UNIQUENESS` (node uniqueness), `RELATIONSHIP_UNIQUENESS`, `NODE_PROPERTY_EXISTENCE`, `RELATIONSHIP_PROPERTY_EXISTENCE`, `NODE_PROPERTY_TYPE`, `RELATIONSHIP_PROPERTY_TYPE`, `NODE_KEY`, or `RELATIONSHIP_KEY`). label:default-output[] -| STRING +For examples on how to list constraints, see xref:constraints/managing-constraints.adoc#list-constraints[Create, show, and drop constraints -> SHOW CONSTRAINTS]. +For full details of the result columns for the `SHOW CONSTRAINTS` command, see xref:constraints/managing-constraints.adoc#list-constraints-result-columns[Create, show, and drop constraints -> Result columns for listing constraints]. -| entityType -| Type of entities this constraint represents (nodes or relationship). label:default-output[] -| STRING +[[drop-constraint]] +== DROP CONSTRAINT -| labelsOrTypes -| The labels or relationship types of this constraint. label:default-output[] -| LIST - -| properties -| The properties of this constraint. label:default-output[] -| LIST - -| ownedIndex -| The name of the index associated with the constraint or `null`, in case no index is associated with it. label:default-output[] -| STRING +Constraints are dropped using the `DROP` CONSTRAINT command. +Dropping a constraint is done by specifying the name of the constraint. -| propertyType -| The property type the property is restricted to for property type constraints, or `null` for the other constraints. -label:default-output[] label:new[Introduced in 5.9] -| STRING +[NOTE] +Dropping a constraint requires the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/database-administration/#access-control-database-administration-constraints[`DROP CONSTRAINT` privilege]. -| options -| The options passed to `CREATE` command, for the index associated to the constraint, or `null` if no index is associated with the constraint. -| MAP -| createStatement -| Statement used to create the constraint. -| STRING +.Syntax for dropping a constraint by name +[source, syntax] +---- +DROP CONSTRAINT constraint_name [IF EXISTS] +---- -|=== +This command is optionally idempotent. +This means its default behavior is to throw an error if an attempt is made to drop the same constraint twice. +With the `IF EXISTS` flag, no error is thrown and nothing happens should the constraint not exist. +Instead, an informational notification is returned detailing that the constraint does not exist. +For examples on how to drop constraints, see xref:constraints/managing-constraints.adoc#drop-constraint[Create, show, and drop constraints -> DROP CONSTRAINT]. diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index 5047cd1bb..7b74ef3ac 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -1249,7 +1249,7 @@ CREATE CONSTRAINT name FOR ()-[r:TYPE]-() REQUIRE r.prop IS :: ---- a| -Extended xref::constraints/examples.adoc#constraints-examples-node-property-type[node] and xref::constraints/examples.adoc#constraints-examples-relationship-property-type[relationship] property type constraints. +Extended xref::constraints/managing-constraints.adoc#create-property-type-constraint-union-type[node and relationship property type constraints]. Closed dynamic union types (`type1 \| type2 \| ...`) are now supported, allowing for types such as: * `INTEGER \| FLOAT` @@ -1331,7 +1331,7 @@ CREATE CONSTRAINT name FOR ()-[r:TYPE]-() REQUIRE r.prop IS :: ---- a| -Extended xref::constraints/examples.adoc#constraints-examples-node-property-type[node] and xref::constraints/examples.adoc#constraints-examples-relationship-property-type[relationship] property type constraints. +Extended xref::constraints/managing-constraints.adoc#type-constraints-allowed-properties[node and relationship property type constraints]. The new supported types are: * `LIST` @@ -1489,7 +1489,7 @@ CREATE CONSTRAINT name FOR ()-[r:TYPE]-() REQUIRE r.prop IS :: ---- a| -Added xref::constraints/examples.adoc#constraints-examples-node-property-type[node] and xref::constraints/examples.adoc#constraints-examples-relationship-property-type[relationship] property type constraints. +Added xref::constraints/managing-constraints.adoc#create-property-type-constraints[node and relationship property type constraints]. The available property types are: * `BOOLEAN` @@ -1639,7 +1639,7 @@ CREATE CONSTRAINT name FOR ()-[r:TYPE]-() REQUIRE r.prop IS RELATIONSHIP KEY ---- a| -Added relationship xref:constraints/syntax.adoc#constraints-syntax-create-rel-key[key] and xref:constraints/syntax.adoc#constraints-syntax-create-rel-unique[uniqueness] constraints. +Added relationship xref:constraints/managing-constraints.adoc#create-key-constraint[key] and xref:constraints/managing-constraints.adoc#create--property-uniqueness-constraint[property uniqueness] constraints. a| label:functionality[] @@ -5101,7 +5101,7 @@ label:new[] DROP CONSTRAINT name ---- a| -xref:constraints/syntax.adoc#constraints-syntax-drop[New command] for dropping a constraint by name, no matter the type. +xref:constraints/managing-constraints.adoc#drop-constraint[New command] for dropping a constraint by name, no matter the type. a| @@ -5213,7 +5213,7 @@ An example of this is `CALL db.index.explicit.searchNodes('my_index','email:me*' | `MATCH (n)-[x:A\|:B\|:C*]-() RETURN n` | Syntax | Deprecated | Replaced by `MATCH (n)-[x:A\|B\|C*]-() RETURN n` | link:/docs/java-reference/5/extending-neo4j/aggregation-functions#extending-neo4j-aggregation-functions[User-defined aggregation functions] | Functionality | Added | | xref:indexes/search-performance-indexes/managing-indexes.adoc[Composite indexes] | Index | Added | -| xref:constraints/examples.adoc#constraints-examples-node-key[Node Key] | Index | Added | Neo4j Enterprise Edition only +| xref:constraints/managing-constraints.adoc#create-key-constraint[Node Key] | Index | Added | Neo4j Enterprise Edition only | `CYPHER runtime=compiled` (Compiled runtime) | Functionality | Added | Neo4j Enterprise Edition only | xref:functions/list.adoc#functions-reverse-list[reverse()] | Function | Extended | Now also allows a list as input | xref:functions/aggregating.adoc#functions-max[max()], xref:functions/aggregating.adoc#functions-min[min()] | Function | Extended | Now also supports aggregation over a set containing both strings and numbers diff --git a/modules/ROOT/pages/indexes/search-performance-indexes/managing-indexes.adoc b/modules/ROOT/pages/indexes/search-performance-indexes/managing-indexes.adoc index 9af1388a6..2487e32ad 100644 --- a/modules/ROOT/pages/indexes/search-performance-indexes/managing-indexes.adoc +++ b/modules/ROOT/pages/indexes/search-performance-indexes/managing-indexes.adoc @@ -235,7 +235,7 @@ However, other predicates are only used when it is known that the property is co * `n.prop = "string"` * `n.prop IN ["a", "b", "c"]` -This means that a text index is not able to solve, for example, e.g. `a.prop = b.prop`, unless a xref:constraints/examples.adoc#constraints-examples-node-property-type[type constraint] also exists on the property. +This means that a text index is not able to solve, for example, e.g. `a.prop = b.prop`, unless a xref:constraints/managing-constraints.adoc#create-property-type-constraints[property type constraint] also exists on the property. Text indexes support the following predicates: @@ -280,8 +280,8 @@ CONTAINS |=== -As of Neo4j 5.11, the above set of predicates can be extended with the use of type constraints. -See the section about xref:indexes/search-performance-indexes/using-indexes.adoc#type-constraints[index compatibility and type constraints] for more information. +As of Neo4j 5.11, the above set of predicates can be extended with the use of property type constraints. +See the section about xref:indexes/search-performance-indexes/using-indexes.adoc#type-constraints[index compatibility and property type constraints] for more information. [TIP] Text indexes are only used for exact query matches. To perform approximate matches (including, for example, variations and typos), and to compute a similarity score between `STRING` values, use semantic xref:indexes/semantic-indexes/full-text-indexes.adoc[full-text indexes] instead. @@ -426,8 +426,8 @@ point.distance(n.prop, center) < = distance |=== -As of Neo4j 5.11, the above set of predicates can be extended with the use of type constraints. -See xref:indexes/search-performance-indexes/using-indexes.adoc#index-compatibility-type-constraints[Index compatibility and type constraints] for more information. +As of Neo4j 5.11, the above set of predicates can be extended with the use of property type constraints. +See xref:indexes/search-performance-indexes/using-indexes.adoc#index-compatibility-type-constraints[Index compatibility and property type constraints] for more information. [TIP] To learn more about the spatial data types supported by Cypher, see the page about xref:values-and-types/spatial.adoc[Spatial values]. @@ -1109,7 +1109,7 @@ Unable to drop index: Index belongs to constraint: `uniqueBookIsbn` ---- Dropping the index-backed constraint will also remove the backing index. -For more information, see xref:constraints/examples.adoc#constraints-examples-drop-constraint[Drop a constraint by name]. +For more information, see xref:constraints/managing-constraints.adoc#drop-constraint[Drop a constraint by name]. [discrete] [[drop-a-non-existing-index]] diff --git a/modules/ROOT/pages/indexes/search-performance-indexes/using-indexes.adoc b/modules/ROOT/pages/indexes/search-performance-indexes/using-indexes.adoc index bcf88382b..7a163a8f1 100644 --- a/modules/ROOT/pages/indexes/search-performance-indexes/using-indexes.adoc +++ b/modules/ROOT/pages/indexes/search-performance-indexes/using-indexes.adoc @@ -892,15 +892,15 @@ The xref:functions/string.adoc#functions-tostring[`toString`] function can also [role=label--new-5.11] [[type-constraints]] -=== Type constraints +=== Property type constraints For indexes that are compatible only with specific types (i.e. text and point indexes), the Cypher planner needs to deduce that a predicate will evaluate to `null` for non-compatible values in order to use the index. If a predicate is not explicitly defined as the required type (`STRING` or `POINT`), this can lead to situations where a text or point index is not used. -Since xref:constraints/examples.adoc#constraints-examples-node-property-type[type constraints] guarantee that a property is always of the same type, they can be used to extend the scenarios in which text and point indexes are compatible with a predicate. +Since xref:constraints/managing-constraints.adoc#create-property-type-constraints[property type constraints] guarantee that a property is always of the same type, they can be used to extend the scenarios in which text and point indexes are compatible with a predicate. -To show this, the following example will first drop the existing range index on the `name` property (this is necessary because type constraints only extend the compatibility of type-specific indexes - range indexes are not limited by a value type). -It will then run the same query with a `WHERE` predicate on the `name` property (for which there exists a previously created text index) before and after creating a type constraint, and compare the resulting execution plans. +To show this, the following example will first drop the existing range index on the `name` property (this is necessary because property type constraints only extend the compatibility of type-specific indexes - range indexes are not limited by a value type). +It will then run the same query with a `WHERE` predicate on the `name` property (for which there exists a previously created text index) before and after creating a property type constraint, and compare the resulting execution plans. .Drop range index [source,cypher] @@ -938,7 +938,7 @@ Total database accesses: 562, total allocated memory: 472 This plan shows that the available text index on the `name` property was not used to solve the predicate. This is because the planner was not able to deduce that all `name` values are of type `STRING`. -However, if a type constraint is created to ensure that all `name` properties have a `STRING` value, a different query plan is generated. +However, if a property type constraint is created to ensure that all `name` properties have a `STRING` value, a different query plan is generated. .Create `STRING` type constraint on the `name` property [source,cypher] @@ -947,7 +947,7 @@ CREATE CONSTRAINT type_constraint FOR (n:PointOfInterest) REQUIRE n.name IS :: STRING ---- -.Rerun the query after the creation of a type constraint +.Rerun the query after the creation of a property type constraint [source,cypher] ---- PROFILE @@ -972,11 +972,11 @@ RETURN count(n) AS nodes Total database accesses: 186, total allocated memory: 472 ---- -Because of the type constraint on the `name` property, the planner is now able to deduce that all `name` properties are of type `STRING`, and therefore use the available text index. +Because of the property type constraint on the `name` property, the planner is now able to deduce that all `name` properties are of type `STRING`, and therefore use the available text index. -Point indexes can be extended in the same way if a type constraint is created to ensure that all properties are `POINT` values. +Point indexes can be extended in the same way if a property type constraint is created to ensure that all properties are `POINT` values. -Note that xref:constraints/examples.adoc#constraints-examples-node-property-existence[property existence constraints] do not currently leverage index use in the same way. +Note that xref:constraints/managing-constraints.adoc#create-property-existence-constraints[property existence constraints] do not currently leverage index use in the same way. [[Heuristics]] == Heuristics: deciding what to index diff --git a/modules/ROOT/pages/introduction/cypher-neo4j.adoc b/modules/ROOT/pages/introduction/cypher-neo4j.adoc index 11c70a69e..5d3482c59 100644 --- a/modules/ROOT/pages/introduction/cypher-neo4j.adoc +++ b/modules/ROOT/pages/introduction/cypher-neo4j.adoc @@ -32,16 +32,12 @@ All users have full access rights. | Constraints a| All constraints: -xref::constraints/examples.adoc#constraints-examples-node-property-existence[node property existence constraints], -xref::constraints/examples.adoc#constraints-examples-relationship-property-existence[relationship property existence constraints], -xref::constraints/examples.adoc#constraints-examples-node-property-type[node property type constraints], -xref::constraints/examples.adoc#constraints-examples-relationship-property-type[relationship property type constraints], -xref::constraints/examples.adoc#constraints-examples-node-uniqueness[node property uniqueness constraints], -xref::constraints/examples.adoc#constraints-examples-relationship-uniqueness[relationship property uniqueness constraints], -xref::constraints/examples.adoc#constraints-examples-node-key[node key constraints], and -xref::constraints/examples.adoc#constraints-examples-relationship-key[relationship key constraints]. +xref::constraints/managing-constraints.adoc#create-property-existence-constraints[node and relationship property existence constraints], +xref::constraints/managing-constraints.adoc#create-property-type-constraints[node and relationship property type constraints], +xref::constraints/managing-constraints.adoc#create-property-uniqueness-constraints[node and relationship property uniqueness constraints], +xref::constraints/managing-constraints.adoc#create-key-constraints[node and relationship key constraints]. a| -Only xref::constraints/examples.adoc#constraints-examples-node-uniqueness[node] and xref::constraints/examples.adoc#constraints-examples-relationship-uniqueness[relationship] property uniqueness constraints. +Only xref::constraints/managing-constraints.adoc#create-property-uniqueness-constraints[node and relationship property uniqueness constraints]. |=== diff --git a/modules/ROOT/pages/introduction/cypher-overview.adoc b/modules/ROOT/pages/introduction/cypher-overview.adoc index a8d7ea846..ebaac533c 100644 --- a/modules/ROOT/pages/introduction/cypher-overview.adoc +++ b/modules/ROOT/pages/introduction/cypher-overview.adoc @@ -36,7 +36,7 @@ However, there are some important differences between the two: *Cypher is schema-flexible*:: While it is both possible and advised to enforce partial schemas using xref:constraints/index.adoc[indexes and constraints], Cypher and Neo4j offers a greater degree of schema-flexibility than SQL and a relational database. -More specifically, nodes and relationships in a Neo4j database do not have to have a specific property set to them because other nodes or relationships in the same graph have that property (unless there is an xref:constraints/examples.adoc#constraints-examples-node-property-existence[existence constraint created on that specific property]). +More specifically, nodes and relationships in a Neo4j database do not have to have a specific property set to them because other nodes or relationships in the same graph have that property (unless there is an xref:constraints/managing-constraints.adoc#create-property-existence-constraints[property existence constraint] created on that specific property). This means that users are not required to use a fixed schema to represent data and that they can add new attributes and relationships as their graphs evolve. *Query order*:: diff --git a/modules/ROOT/pages/patterns/shortest-paths.adoc b/modules/ROOT/pages/patterns/shortest-paths.adoc index 01e61f3ba..b6f540e91 100644 --- a/modules/ROOT/pages/patterns/shortest-paths.adoc +++ b/modules/ROOT/pages/patterns/shortest-paths.adoc @@ -595,4 +595,4 @@ RETURN p [TIP] Sometimes the planner cannot make reliable estimations about how many nodes a pattern node will match. -Consider using a xref:constraints/index.adoc#unique-node-property[uniqueness constraint] where applicable to help the planner get more reliable estimates. +Consider using a xref:constraints/managing-constraints.adoc#create-property-uniqueness-constraints[property uniqueness constraint] where applicable to help the planner get more reliable estimates. diff --git a/modules/ROOT/pages/values-and-types/property-structural-constructed.adoc b/modules/ROOT/pages/values-and-types/property-structural-constructed.adoc index 618ade925..a08608f9e 100644 --- a/modules/ROOT/pages/values-and-types/property-structural-constructed.adoc +++ b/modules/ROOT/pages/values-and-types/property-structural-constructed.adoc @@ -74,7 +74,7 @@ For more details, see xref::values-and-types/working-with-null.adoc[working with The table below shows the types and their syntactic synonyms. -These types (and their synonyms) can be used in xref::values-and-types/type-predicate.adoc[type predicate expressions] and in xref::constraints/examples.adoc#constraints-examples-node-property-type[node] and xref::constraints/examples.adoc#constraints-examples-relationship-property-type[relationship] property type constraints. +These types (and their synonyms) can be used in xref::values-and-types/type-predicate.adoc[type predicate expressions] and in xref::constraints/managing-constraints.adoc#create-property-type-constraints[property type constraints]. They are also returned as a `STRING` value when using the xref::functions/scalar.adoc#functions-valueType[valueType()] function. However, not all types can be used in all places. @@ -121,7 +121,7 @@ The type `PROPERTY VALUE` is expanded to a closed dynamic union of all valid pro For example, given the closed dynamic type `BOOL | LIST | BOOLEAN | LIST`, the normalized type would be: `BOOLEAN | LIST`. -This normalization is run on types used in xref::values-and-types/type-predicate.adoc[type predicate expressions], and in xref::constraints/examples.adoc#constraints-examples-node-property-type[node] and xref::constraints/examples.adoc#constraints-examples-relationship-property-type[relationship] property type constraints. +This normalization is run on types used in xref::values-and-types/type-predicate.adoc[type predicate expressions], and in xref::constraints/managing-constraints.adoc#create-property-type-constraints[property type constraints]. Type normalization is also used to ensure the consistency of the output for the xref::functions/scalar.adoc#functions-valueType[valueType()] function. [[ordering-of-types]] From 5aacb40551f1e1e0cecf650ab47f7a26d5b3bc14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Mon, 21 Oct 2024 09:17:36 +0200 Subject: [PATCH 07/77] Fix typo and change auradb enterprise to auradb virtual dedicated cloud on parallel runtime page (#1068) --- .../ROOT/pages/planning-and-tuning/runtimes/reference.adoc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/ROOT/pages/planning-and-tuning/runtimes/reference.adoc b/modules/ROOT/pages/planning-and-tuning/runtimes/reference.adoc index 57e009abc..24d12435b 100644 --- a/modules/ROOT/pages/planning-and-tuning/runtimes/reference.adoc +++ b/modules/ROOT/pages/planning-and-tuning/runtimes/reference.adoc @@ -79,8 +79,8 @@ For more information about configuration settings in Neo4j, see the link:{neo4j- == Aura The parallel runtime can only be run on Aura instances with 3 or more CPUs. -This means that the parallel runtime is not available to users to users of AuraDB Free. -Nor is it available on instances of AuraDB Professional and AuraDB Enterprise with 2 or fewer CPUs. +This means that the parallel runtime is not available to users of AuraDB Free. +Nor is it available on instances of AuraDB Professional, AuraDB Business Critical, and AuraDB Virtual Dedicated Cloud with 2 or fewer CPUs. Attempting to run a query with the parallel runtime on instances with 2 or fewer CPUs will generate the following error message: @@ -92,7 +92,7 @@ Parallel runtime has been disabled, please enable it or upgrade to a bigger Aura [TIP] ==== -Users of AuraDB Professional and AuraDB Enterprise select the number of available CPUs when creating an instance. +Users of AuraDB Professional, AuraDB Business Critical, and AuraDB Virtual Dedicated Cloud select the number of available CPUs when creating an instance. More information about the various tiers of AuraDB can be found on the link:https://neo4j.com/pricing/[Neo4j Pricing page]. ==== From 7c14b995e7649f4deb58b2d051c384ca7a3760c0 Mon Sep 17 00:00:00 2001 From: Richard Sill <156673635+rsill-neo4j@users.noreply.github.com> Date: Mon, 21 Oct 2024 10:17:16 +0200 Subject: [PATCH 08/77] Intro with a link to ops manual for cloud URI section (#1071) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jens Pryce-Åklundh <112686610+JPryce-Aklundh@users.noreply.github.com> --- modules/ROOT/pages/clauses/load-csv.adoc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/modules/ROOT/pages/clauses/load-csv.adoc b/modules/ROOT/pages/clauses/load-csv.adoc index fa5804f1b..24050d9bb 100644 --- a/modules/ROOT/pages/clauses/load-csv.adoc +++ b/modules/ROOT/pages/clauses/load-csv.adoc @@ -171,6 +171,14 @@ Added 4 nodes, Set 8 properties, Added 4 labels [role=label--enterprise-edition label--not-on-aura] === Import from cloud URIs +You can import data from a number of different cloud storages: + +* xref:clauses/load-csv.adoc#azure-cloud-storage[Azure Cloud Storage] +* xref:clauses/load-csv.adoc#google-cloud-storage[Google Cloud Storage] +* ref:clauses/load-csv.adoc#aws-s3[AWS S3] + +See link:{neo4j-docs-base-uri}/operations-manual/current/backup-restore/restore-dump/#load-dump-cloud-storage[Operations Manual -> Load a dump from a cloud storage] on how to set up access to cloud storages. + [[azure-cloud-storage]] [role=label--new-5.24] ==== Import from an Azure Cloud Storage URI From 1d2bf8da875924575f696b71952ffc98f958922c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Mon, 21 Oct 2024 13:39:24 +0200 Subject: [PATCH 09/77] Make Cypher Manual AuraDB Business Critical aware (#1072) Co-authored-by: Jessica Wright <49636617+AlexicaWright@users.noreply.github.com> --- .../ROOT/pages/introduction/cypher-aura.adoc | 32 ++++++++----------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/modules/ROOT/pages/introduction/cypher-aura.adoc b/modules/ROOT/pages/introduction/cypher-aura.adoc index c1cd41633..bd117c999 100644 --- a/modules/ROOT/pages/introduction/cypher-aura.adoc +++ b/modules/ROOT/pages/introduction/cypher-aura.adoc @@ -2,7 +2,7 @@ = Cypher and Aura :description: This section provides an introduction to the Cypher query language. -This section gives a brief overview of Aura, and how Cypher differs to users of Aura. +This page provides a brief overview of Neo4j Aura and its relationship to Cypher. == What is Aura? @@ -13,36 +13,30 @@ AuraDB is a graph database service for developers building intelligent applicati AuraDB is available on the following tiers: * AuraDB Free -* AuraDB Pro -* AuraDB Enterprise +* AuraDB Professional +* AuraDB Business Critical +* AuraDB Virtual Dedicated Cloud For more information, see link:{neo4j-docs-base-uri}/aura/auradb[Aura docs - Neo4j AuraDB overview]. AuraDS is available on the following tiers: -* AuraDS Pro +* Graph Data Science Community +* Graph Data Science Enterprise +* AuraDS Professional * AuraDS Enterprise For more information, see link:{neo4j-docs-base-uri}/aura/aurads[Aura docs - Neo4j AuraDS overview]. == Using Cypher on Aura -Most Cypher features are available on all tiers of Aura. -There are, however, some features which are not available to Aura instances. +Most Cypher features are available across all tiers of Aura. +However, certain features are not supported in Aura instances. For example, it is not possible to create, alter, or drop databases using Aura, nor is it possible to alter or drop servers. -There are also certain Cypher features which are only available on AuraDB Enterprise instances. -These can be categorized as the role-based access-control features of Cypher. -For example, it is not possible to create, alter, or drop roles using AuraDB Free, AuraDB Pro, AuraDS Pro, or AuraDS Enterprise, but it is possible using AuraDB Enterprise. - -The Cypher Manual uses two different labels to differentiate this distinction: - -[options="header,cols=""2a,2a"] -|=== -| Label | Description -| label:not-on-aura[Not Available on Aura] | Cypher feature not available on any tier of Aura. -| label:aura-db-enterprise[AuraDB Enterprise] | Cypher feature only available on AuraDB Enterprise. -|=== +Additionally, some Cypher features are exclusive to AuraDB Business Critical and AuraDB Virtual Dedicated Cloud tiers. +These primarily fall under database administration and role-based access control capabilities. +For more information, see the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/[Operations Manual -> Database administration] and the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/[Operations Manual -> Authentication and authorization]. == Aura and the Cypher Cheat Sheet @@ -50,4 +44,4 @@ Each different tier of Aura has a customized version of the Cypher Cheat Sheet w The Cypher Cheat Sheet can be accessed link:{neo4j-docs-base-uri}/cypher-cheat-sheet/{page-version}/auradb-enterprise/[here]. You can select your desired Aura tier and Neo4j version by using the dropdown menus provided. -Note that the default tier is AuraDB Enterprise. +Note that the default tier is AuraDB Virtual Dedicated Cloud. From d8bfe784bef76af1f90a59fdd37a92bc067ae040 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Tue, 22 Oct 2024 11:02:05 +0200 Subject: [PATCH 10/77] Fix remaining examples of CALL subqueries without variable scope clause (#1074) --- modules/ROOT/pages/clauses/union.adoc | 7 ++++++- modules/ROOT/pages/clauses/use.adoc | 5 +++-- modules/ROOT/pages/functions/graph.adoc | 14 ++++++++++++-- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/modules/ROOT/pages/clauses/union.adoc b/modules/ROOT/pages/clauses/union.adoc index 85b261d97..2df4687aa 100644 --- a/modules/ROOT/pages/clauses/union.adoc +++ b/modules/ROOT/pages/clauses/union.adoc @@ -131,10 +131,15 @@ The combined result is returned, without duplicates. The `UNION` clause can be used within a xref:subqueries/call-subquery.adoc[`CALL` subquery] to further process the combined results before a final output is returned. For example, the below query xref:functions/aggregating.adoc#functions-count[counts] the occurrences of each `name` property returned after the `UNION ALL` within the `CALL` subquery. +[NOTE] +The below query uses an empty xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause]: `CALL () { ... }` (introduced in Neo4j 5.23). +If you are using an older version of Neo4j, use `CALL { ... }` instead. +For more information, see xref:subqueries/call-subquery.adoc#import-variables[CALL subqueries -> Importing variables]. + .Query [source, cypher] ---- -CALL { +CALL () { MATCH (a:Actor) RETURN a.name AS name UNION ALL diff --git a/modules/ROOT/pages/clauses/use.adoc b/modules/ROOT/pages/clauses/use.adoc index 20df616ca..29c744c72 100644 --- a/modules/ROOT/pages/clauses/use.adoc +++ b/modules/ROOT/pages/clauses/use.adoc @@ -41,13 +41,14 @@ USE + [source, syntax, role="noheader"] ---- -CALL { +CALL () { USE } ---- + -In subqueries, a `USE` clause may appear as the second clause, if directly following an xref::subqueries/call-subquery.adoc#call-importing-variables[importing `WITH` clause]. +In subqueries, a `USE` clause may appear directly following the xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause]: `CALL () { ... }` (introduced in Neo4j 5.23). +Or, if you are using an older version of Neo4j, directly following an xref::subqueries/call-subquery.adoc#importing-with[importing `WITH` clause]. When executing queries against a composite database, the `USE` clause must only refer to graphs that are part of the current composite database. diff --git a/modules/ROOT/pages/functions/graph.adoc b/modules/ROOT/pages/functions/graph.adoc index 8ac1fcd0e..9404b48f5 100644 --- a/modules/ROOT/pages/functions/graph.adoc +++ b/modules/ROOT/pages/functions/graph.adoc @@ -117,7 +117,7 @@ Properties for all graphs on the current composite database are returned. UNWIND graph.names() AS name WITH name, graph.propertiesByName(name) AS props WHERE "A" IN props.tags -CALL { +CALL () { USE graph.byName(name) MATCH (n) RETURN n @@ -127,6 +127,11 @@ RETURN n Returns all nodes from a subset of graphs that have a `tags` property containing `"A"`. +[NOTE] +The above query uses an empty xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause]: `CALL () { ... }` (introduced in Neo4j 5.23). +If you are using an older version of Neo4j, use `CALL { ... }` instead. +For more information, see xref:subqueries/call-subquery.adoc#import-variables[CALL subqueries -> Importing variables]. + ====== [[functions-graph-byname]] @@ -148,7 +153,7 @@ Returns all nodes from a subset of graphs that have a `tags` property containing [source, cypher, indent=0] ---- UNWIND graph.names() AS graphName -CALL { +CALL () { USE graph.byName(graphName) MATCH (n) RETURN n @@ -158,6 +163,11 @@ RETURN n Returns all nodes from all graphs on the current composite database. +[NOTE] +The above query uses an empty xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause]: `CALL () { ... }` (introduced in Neo4j 5.23). +If you are using an older version of Neo4j, use `CALL { ... }` instead. +For more information, see xref:subqueries/call-subquery.adoc#import-variables[CALL subqueries -> Importing variables]. + ====== [role=label--new-5.13] From 4fa08145b39f2a6a6e040004fa2d43a99107d77a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Tue, 22 Oct 2024 11:04:50 +0200 Subject: [PATCH 11/77] remove introduced in information --- modules/ROOT/pages/clauses/union.adoc | 5 ----- modules/ROOT/pages/clauses/use.adoc | 3 +-- modules/ROOT/pages/functions/graph.adoc | 5 ----- 3 files changed, 1 insertion(+), 12 deletions(-) diff --git a/modules/ROOT/pages/clauses/union.adoc b/modules/ROOT/pages/clauses/union.adoc index 2df4687aa..2e4e41178 100644 --- a/modules/ROOT/pages/clauses/union.adoc +++ b/modules/ROOT/pages/clauses/union.adoc @@ -131,11 +131,6 @@ The combined result is returned, without duplicates. The `UNION` clause can be used within a xref:subqueries/call-subquery.adoc[`CALL` subquery] to further process the combined results before a final output is returned. For example, the below query xref:functions/aggregating.adoc#functions-count[counts] the occurrences of each `name` property returned after the `UNION ALL` within the `CALL` subquery. -[NOTE] -The below query uses an empty xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause]: `CALL () { ... }` (introduced in Neo4j 5.23). -If you are using an older version of Neo4j, use `CALL { ... }` instead. -For more information, see xref:subqueries/call-subquery.adoc#import-variables[CALL subqueries -> Importing variables]. - .Query [source, cypher] ---- diff --git a/modules/ROOT/pages/clauses/use.adoc b/modules/ROOT/pages/clauses/use.adoc index 29c744c72..7205b8389 100644 --- a/modules/ROOT/pages/clauses/use.adoc +++ b/modules/ROOT/pages/clauses/use.adoc @@ -47,8 +47,7 @@ CALL () { } ---- + -In subqueries, a `USE` clause may appear directly following the xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause]: `CALL () { ... }` (introduced in Neo4j 5.23). -Or, if you are using an older version of Neo4j, directly following an xref::subqueries/call-subquery.adoc#importing-with[importing `WITH` clause]. +In subqueries, a `USE` clause may appear directly following the xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause]: `CALL () { ... }`. When executing queries against a composite database, the `USE` clause must only refer to graphs that are part of the current composite database. diff --git a/modules/ROOT/pages/functions/graph.adoc b/modules/ROOT/pages/functions/graph.adoc index 9404b48f5..89ddf6a20 100644 --- a/modules/ROOT/pages/functions/graph.adoc +++ b/modules/ROOT/pages/functions/graph.adoc @@ -163,11 +163,6 @@ RETURN n Returns all nodes from all graphs on the current composite database. -[NOTE] -The above query uses an empty xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause]: `CALL () { ... }` (introduced in Neo4j 5.23). -If you are using an older version of Neo4j, use `CALL { ... }` instead. -For more information, see xref:subqueries/call-subquery.adoc#import-variables[CALL subqueries -> Importing variables]. - ====== [role=label--new-5.13] From aafc17e57a4a0df86c9c8c7cdb329b252f054c6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Tue, 22 Oct 2024 11:10:26 +0200 Subject: [PATCH 12/77] Cypher 25: Remove 5.x "Introduced in" labels and in-text notifications (#1056) --- .../tutorials/advanced-query-tuning.adoc | 2 +- modules/ROOT/pages/clauses/call.adoc | 2 +- .../pages/clauses/clause-composition.adoc | 3 +- modules/ROOT/pages/clauses/create.adoc | 4 +- modules/ROOT/pages/clauses/delete.adoc | 2 +- modules/ROOT/pages/clauses/finish.adoc | 1 - modules/ROOT/pages/clauses/index.adoc | 3 - modules/ROOT/pages/clauses/limit.adoc | 2 +- .../ROOT/pages/clauses/listing-functions.adoc | 4 +- .../pages/clauses/listing-procedures.adoc | 4 +- .../ROOT/pages/clauses/listing-settings.adoc | 4 +- modules/ROOT/pages/clauses/load-csv.adoc | 9 +- modules/ROOT/pages/clauses/merge.adoc | 2 +- modules/ROOT/pages/clauses/order-by.adoc | 3 +- modules/ROOT/pages/clauses/remove.adoc | 6 +- modules/ROOT/pages/clauses/set.adoc | 10 +- modules/ROOT/pages/clauses/skip.adoc | 4 +- .../pages/clauses/transaction-clauses.adoc | 20 +- modules/ROOT/pages/clauses/union.adoc | 2 +- modules/ROOT/pages/clauses/use.adoc | 2 +- modules/ROOT/pages/clauses/where.adoc | 2 +- modules/ROOT/pages/constraints/syntax.adoc | 2 +- modules/ROOT/pages/functions/aggregating.adoc | 2 +- modules/ROOT/pages/functions/database.adoc | 1 - modules/ROOT/pages/functions/graph.adoc | 2 +- modules/ROOT/pages/functions/index.adoc | 20 +- modules/ROOT/pages/functions/scalar.adoc | 10 +- modules/ROOT/pages/functions/string.adoc | 17 +- modules/ROOT/pages/functions/vector.adoc | 1 - modules/ROOT/pages/genai-integrations.adoc | 24 +-- .../managing-indexes.adoc | 41 ++-- .../using-indexes.adoc | 10 +- .../semantic-indexes/full-text-indexes.adoc | 7 +- .../semantic-indexes/vector-indexes.adoc | 175 ++---------------- modules/ROOT/pages/indexes/syntax.adoc | 18 +- modules/ROOT/pages/patterns/reference.adoc | 10 +- .../ROOT/pages/patterns/shortest-paths.adoc | 4 +- .../patterns/variable-length-patterns.adoc | 6 +- .../planning-and-tuning/operators/index.adoc | 56 +++--- .../operators/operators-detail.adoc | 114 ++++++------ .../planning-and-tuning/query-tuning.adoc | 2 +- .../runtimes/concepts.adoc | 2 +- .../runtimes/reference.adoc | 2 +- modules/ROOT/pages/queries/basic.adoc | 4 +- modules/ROOT/pages/queries/case.adoc | 2 +- .../ROOT/pages/subqueries/call-subquery.adoc | 4 +- modules/ROOT/pages/subqueries/collect.adoc | 1 - modules/ROOT/pages/subqueries/count.adoc | 6 +- .../ROOT/pages/subqueries/existential.adoc | 6 +- modules/ROOT/pages/subqueries/index.adoc | 2 +- .../subqueries-in-transactions.adoc | 11 +- modules/ROOT/pages/syntax/operators.adoc | 8 +- .../property-structural-constructed.adoc | 2 +- .../ROOT/pages/values-and-types/spatial.adoc | 1 - .../ROOT/pages/values-and-types/temporal.adoc | 13 -- .../values-and-types/type-predicate.adoc | 11 +- 56 files changed, 247 insertions(+), 441 deletions(-) diff --git a/modules/ROOT/pages/appendix/tutorials/advanced-query-tuning.adoc b/modules/ROOT/pages/appendix/tutorials/advanced-query-tuning.adoc index 910b35f78..115e7092c 100644 --- a/modules/ROOT/pages/appendix/tutorials/advanced-query-tuning.adoc +++ b/modules/ROOT/pages/appendix/tutorials/advanced-query-tuning.adoc @@ -939,7 +939,7 @@ Predicates that will not work: If there is an existence constraint on the property, no predicate is required to trigger the optimization. For example, `CREATE CONSTRAINT constraint_name FOR (p:Person) REQUIRE p.name IS NOT NULL` -As of Neo4j {neo4j-version-exact}, predicates with parameters, such as `WHERE n.prop > $param`, can trigger _index-backed ORDER BY_. +Predicates with parameters, such as `WHERE n.prop > $param`, can trigger _index-backed ORDER BY_. The only exception are queries with parameters of type `POINT`. ==== diff --git a/modules/ROOT/pages/clauses/call.adoc b/modules/ROOT/pages/clauses/call.adoc index d600d0bd4..30b0ed1b9 100644 --- a/modules/ROOT/pages/clauses/call.adoc +++ b/modules/ROOT/pages/clauses/call.adoc @@ -259,7 +259,7 @@ A `VOID` procedure is a procedure that does not declare any result fields and re `VOID` procedure only produces side-effects and does not allow for the use of `YIELD`. Calling a `VOID` procedure in the middle of a larger query will simply pass on each input record (i.e., it acts like xref:clauses/with.adoc[`WITH *`] in terms of the record stream). -[role=label--new-5.24] + [[optional-call]] == Optional procedure calls diff --git a/modules/ROOT/pages/clauses/clause-composition.adoc b/modules/ROOT/pages/clauses/clause-composition.adoc index fa560590f..416906fcf 100644 --- a/modules/ROOT/pages/clauses/clause-composition.adoc +++ b/modules/ROOT/pages/clauses/clause-composition.adoc @@ -573,8 +573,7 @@ Later invocations of the subquery can observe writes made by earlier invocations Using the same example graph as above, this example shows the table of intermediate results and the state of the graph after each clause for the following query: [NOTE] -The below query uses a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause] (introduced in Neo4j 5.23) to import variables into the `CALL` subquery. -If you are using an older version of Neo4j, use an xref:subqueries/call-subquery.adoc#importing-with[importing `WITH` clause] instead. +The below query uses a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause] to import variables into the `CALL` subquery. [source,cypher] ---- diff --git a/modules/ROOT/pages/clauses/create.adoc b/modules/ROOT/pages/clauses/create.adoc index 9749ac375..f27945c18 100644 --- a/modules/ROOT/pages/clauses/create.adoc +++ b/modules/ROOT/pages/clauses/create.adoc @@ -23,7 +23,7 @@ Multiple labels are separated by colons. CREATE (charlie:Person:Actor {name: 'Charlie Sheen'}), (oliver:Person:Director {name: 'Oliver Stone'}) ---- -As of Neo4j 5.18, multiple labels can also be separated by an ampersand `&`, in the same manner as it is used in xref:patterns/reference.adoc#label-expressions[label expressions]. +Multiple labels can also be separated by an ampersand `&`, in the same manner as it is used in xref:patterns/reference.adoc#label-expressions[label expressions]. Separation by colon `:` and ampersand `&` cannot be mixed in the same clause. .Query @@ -205,7 +205,7 @@ Nodes created: 2 + Properties set: 4 |=== -[role=label--new-5.18] + [[insert-as-synonym-of-create]] == `INSERT` as a synonym of `CREATE` diff --git a/modules/ROOT/pages/clauses/delete.adoc b/modules/ROOT/pages/clauses/delete.adoc index 0f6c13678..2d87d05f9 100644 --- a/modules/ROOT/pages/clauses/delete.adoc +++ b/modules/ROOT/pages/clauses/delete.adoc @@ -58,7 +58,7 @@ This query is only possible to run on nodes without any relationships connected Deleted 1 node ---- -[role=label--new-5.14] + [[delete-nodetach]] === NODETACH keyword diff --git a/modules/ROOT/pages/clauses/finish.adoc b/modules/ROOT/pages/clauses/finish.adoc index b233b4896..21413fc51 100644 --- a/modules/ROOT/pages/clauses/finish.adoc +++ b/modules/ROOT/pages/clauses/finish.adoc @@ -1,5 +1,4 @@ :description: The `FINISH` clause defines a query to have no result. -:page-role: new-5.19 [[query-finish]] = FINISH diff --git a/modules/ROOT/pages/clauses/index.adoc b/modules/ROOT/pages/clauses/index.adoc index d0e421713..77165c7d0 100644 --- a/modules/ROOT/pages/clauses/index.adoc +++ b/modules/ROOT/pages/clauses/index.adoc @@ -63,15 +63,12 @@ m| xref::clauses/where.adoc[WHERE] m| xref::clauses/order-by.adoc[ORDER BY [ASC[ENDING\] \| DESC[ENDING\]\]] | A sub-clause following `RETURN` or `WITH`, specifying that the output should be sorted in either ascending (the default) or descending order. -As of Neo4j 5.24, it can also be used as a standalone clause. m| xref::clauses/skip.adoc[SKIP] / xref::clauses/skip.adoc#offset-synonym[`OFFSET`] | Defines from which row to start including the rows in the output. -As of Neo4j 5.24, it can be used as a standalone clause. m| xref::clauses/limit.adoc[LIMIT] | Constrains the number of rows in the output. -As of Neo4j 5.24, it can be used as a standalone clause. |=== diff --git a/modules/ROOT/pages/clauses/limit.adoc b/modules/ROOT/pages/clauses/limit.adoc index cc29cf861..443012915 100644 --- a/modules/ROOT/pages/clauses/limit.adoc +++ b/modules/ROOT/pages/clauses/limit.adoc @@ -159,7 +159,7 @@ d|Rows: 1 + Properties set: 1 |=== -[role=label--new-5.24] + [[limit-standalone-clause]] == Using `LIMIT` as a standalone clause diff --git a/modules/ROOT/pages/clauses/listing-functions.adoc b/modules/ROOT/pages/clauses/listing-functions.adoc index 38d4ea035..325b72685 100644 --- a/modules/ROOT/pages/clauses/listing-functions.adoc +++ b/modules/ROOT/pages/clauses/listing-functions.adoc @@ -66,12 +66,12 @@ m| LIST m| isDeprecated a| Whether the function is deprecated. -label:new[Introduced in 5.9] + m| BOOLEAN m| deprecatedBy a| The replacement function to use in case of deprecation; otherwise `null`. -label:new[Introduced in 5.21] + m| STRING |=== diff --git a/modules/ROOT/pages/clauses/listing-procedures.adoc b/modules/ROOT/pages/clauses/listing-procedures.adoc index b79eba881..686113050 100644 --- a/modules/ROOT/pages/clauses/listing-procedures.adoc +++ b/modules/ROOT/pages/clauses/listing-procedures.adoc @@ -64,12 +64,12 @@ m| LIST m| isDeprecated a| Whether the procedure is deprecated. -label:new[Introduced in 5.9] + m| BOOLEAN m| deprecatedBy a| The replacement procedure to use in case of deprecation; otherwise `null`. -label:new[Introduced in 5.21] + m| STRING m| option diff --git a/modules/ROOT/pages/clauses/listing-settings.adoc b/modules/ROOT/pages/clauses/listing-settings.adoc index df859d1cb..ab6da6766 100644 --- a/modules/ROOT/pages/clauses/listing-settings.adoc +++ b/modules/ROOT/pages/clauses/listing-settings.adoc @@ -1,6 +1,6 @@ [[query-listing-settings]] = SHOW SETTINGS -:page-role: not-on-aura new-5.6 +:page-role: not-on-aura :description: This section explains the `SHOW SETTINGS` command. Listing the configuration settings on a server can be done with `SHOW SETTINGS`. @@ -63,7 +63,7 @@ m| STRING m| isDeprecated a| Whether the setting is deprecated. -label:new[Introduced in 5.9] + m| BOOLEAN |=== diff --git a/modules/ROOT/pages/clauses/load-csv.adoc b/modules/ROOT/pages/clauses/load-csv.adoc index 24050d9bb..3f17dc8cb 100644 --- a/modules/ROOT/pages/clauses/load-csv.adoc +++ b/modules/ROOT/pages/clauses/load-csv.adoc @@ -180,7 +180,7 @@ You can import data from a number of different cloud storages: See link:{neo4j-docs-base-uri}/operations-manual/current/backup-restore/restore-dump/#load-dump-cloud-storage[Operations Manual -> Load a dump from a cloud storage] on how to set up access to cloud storages. [[azure-cloud-storage]] -[role=label--new-5.24] + ==== Import from an Azure Cloud Storage URI You can import data from a CSV file hosted in an Azure Cloud Storage URI. @@ -220,7 +220,7 @@ Added 4 nodes, Set 8 properties, Added 4 labels ==== [[google-cloud-storage]] -[role=label--new-5.21] + ==== Import from a Google Cloud Storage URI You can import data from a CSV file hosted in a Google Cloud Storage URI. @@ -260,7 +260,7 @@ Added 4 nodes, Set 8 properties, Added 4 labels ==== [[aws-s3]] -[role=label--new-5.19] + ==== Import from an AWS S3 URI You can import data from a CSV file hosted in an AWS S3 URI. @@ -658,8 +658,7 @@ person_tmdbId,bio,born,bornIn,died,person_imdbId,name,person_poster,person_url ---- [NOTE] -The below query uses a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause] (introduced in Neo4j 5.23) to import variables into the `CALL` subquery. -If you are using an older version of Neo4j, use an xref:subqueries/call-subquery.adoc#importing-with[importing `WITH` clause] instead. +The below query uses a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause] to import variables into the `CALL` subquery. .Query [source, cypher] diff --git a/modules/ROOT/pages/clauses/merge.adoc b/modules/ROOT/pages/clauses/merge.adoc index 669409c6a..d21f8b65b 100644 --- a/modules/ROOT/pages/clauses/merge.adoc +++ b/modules/ROOT/pages/clauses/merge.adoc @@ -107,7 +107,7 @@ A new node is created because there are no nodes labeled both `Critic` and `View | ["Critic","Viewer"] |=== -As of Neo4j 5.18, multiple labels can also be separated by an ampersand `&`, in the same manner as it is used in xref:patterns/reference.adoc#label-expressions[label expressions]. +Multiple labels can also be separated by an ampersand `&`, in the same manner as it is used in xref:patterns/reference.adoc#label-expressions[label expressions]. Separation by colon `:` and ampersand `&` cannot be mixed in the same clause. .Query diff --git a/modules/ROOT/pages/clauses/order-by.adoc b/modules/ROOT/pages/clauses/order-by.adoc index feb5bb766..90ce90bb1 100644 --- a/modules/ROOT/pages/clauses/order-by.adoc +++ b/modules/ROOT/pages/clauses/order-by.adoc @@ -5,7 +5,6 @@ `ORDER BY` specifies how the output of a clause should be sorted. It be used as a sub-clause following `RETURN` or `WITH`. -As of Neo4j 5.24, it can also be used as a standalone clause, either on its own or in combination with `SKIP`/`OFFSET` or `LIMIT`. `ORDER BY` relies on comparisons to sort the output, see xref::syntax/operators.adoc#cypher-ordering[Ordering and comparison of values]. You can sort on many different values, e.g. node/relationship properties, the node/relationship ids, or on most expressions. @@ -238,7 +237,7 @@ The performance of Cypher queries using `ORDER BY` on node properties can be inf If the index can provide the nodes in the order requested in the query, Cypher can avoid the use of an expensive `Sort` operation. Read more about this capability in xref::indexes/search-performance-indexes/using-indexes.adoc#range-index-backed-order-by[Range index-backed ORDER BY]. -[role=label--new-5.24] + [[order-standalone-clause]] == Using `ORDER BY` as a standalone clause diff --git a/modules/ROOT/pages/clauses/remove.adoc b/modules/ROOT/pages/clauses/remove.adoc index 4203403af..717c6948a 100644 --- a/modules/ROOT/pages/clauses/remove.adoc +++ b/modules/ROOT/pages/clauses/remove.adoc @@ -68,7 +68,7 @@ Properties set: 1 `REMOVE` cannot be used to remove all existing properties from a node or relationship. Instead, using xref::clauses/set.adoc#set-remove-properties-using-empty-map[`SET` with `=` and an empty map as the right operand] will clear all properties from the node or relationship. -[role=label--new-5.24] + [[remove-remove-a-property-dynamically]] == Dynamically removing a property @@ -130,7 +130,7 @@ RETURN n.name, labels(n) Labels removed: 1 |=== -[role=label--new-5.24] + [[remove-remove-a-label-dynamically-from-a-node]] == Dynamically removing a label @@ -186,7 +186,7 @@ RETURN n.name, labels(n) Labels removed: 2 |=== -[role=label--new-5.24] + [[remove-remove-multiple-labels-dynamically]] == Remove multiple labels dynamically from a node diff --git a/modules/ROOT/pages/clauses/set.adoc b/modules/ROOT/pages/clauses/set.adoc index 6976c8abe..8f16fd210 100644 --- a/modules/ROOT/pages/clauses/set.adoc +++ b/modules/ROOT/pages/clauses/set.adoc @@ -161,7 +161,7 @@ Properties set: 1 |=== -[role=label--new-5.24] + [[set-dynamically-a-property]] == Dynamically setting or updating a property @@ -540,7 +540,7 @@ The newly-labeled node is returned by the query. Labels added: 1 |=== -[role=label--new-5.24] + [[set-set-a-dynamic-label-on-a-node]] == Dynamically setting a label @@ -571,7 +571,7 @@ The newly-labeled node is returned by the query. Labels added: 1 |=== -[role=label--new-5.24] + [[set-set-a-label-using-a-parameter]] == Set a label using a parameter @@ -628,7 +628,7 @@ The newly-labeled node is returned by the query. Labels added: 2 |=== -[role=label--new-5.24] + [[set-set-multiple-dynamic-labels-on-a-node]] == Set multiple labels dynamically on a node @@ -657,7 +657,7 @@ Labels added: 4 |=== -[role=label--new-5.24] + [[set-set-multiple-labels-using-a-parameter]] == Set multiple labels using parameters diff --git a/modules/ROOT/pages/clauses/skip.adoc b/modules/ROOT/pages/clauses/skip.adoc index 2f31a9f49..b4c4ecbee 100644 --- a/modules/ROOT/pages/clauses/skip.adoc +++ b/modules/ROOT/pages/clauses/skip.adoc @@ -119,7 +119,7 @@ d|Rows: 4 ==== -[role=label--new-5.24] + [[skip-standalone-clause]] == Using `SKIP` as a standalone clause @@ -162,7 +162,7 @@ RETURN collect(n.name) AS names |Rows: 1 |=== -[role=label--new-5.24] + [[offset-synonym]] == `OFFSET` as a synonym to `SKIP` diff --git a/modules/ROOT/pages/clauses/transaction-clauses.adoc b/modules/ROOT/pages/clauses/transaction-clauses.adoc index b1a099770..a6eebbdc5 100644 --- a/modules/ROOT/pages/clauses/transaction-clauses.adoc +++ b/modules/ROOT/pages/clauses/transaction-clauses.adoc @@ -93,7 +93,7 @@ m| indexes a| The indexes utilised by the query currently executing in this transaction, or an empty list if no query is currently executing. m| LIST -// New in 5.0 + m| currentQueryStartTime a| The time at which the query currently executing in this transaction was started, or an empty `STRING` if no query is currently executing. m| STRING @@ -109,7 +109,7 @@ m| requestUri a| The request URI used by the client connection issuing the transaction, or `null` if the URI is not available. m| STRING -// New in 5.0 + m| currentQueryStatus a| The current status of the query currently executing in this transaction (`parsing`, `planning`, `planned`, `running`, or `waiting`), or an empty `STRING` if no query is currently executing. m| STRING @@ -126,7 +126,7 @@ m| activeLockCount a| Count of active locks held by the transaction. m| INTEGER -// New in 5.0 + m| currentQueryActiveLockCount a| Count of active locks held by the query currently executing in this transaction. m| INTEGER @@ -143,27 +143,27 @@ m| idleTime a| Idle time for this transaction, or `null` if unavailable. m| DURATION -// New in 5.0 + m| currentQueryElapsedTime a| The time that has elapsed since the query currently executing in this transaction was started, or `null` if no query is currently executing. m| DURATION -// New in 5.0 + m| currentQueryCpuTime a| CPU time that has been actively spent executing the query currently executing in this transaction, or `null` if unavailable or no query is currently executing. m| DURATION -// New in 5.0 + m| currentQueryWaitTime a| Wait time that has been spent waiting to acquire locks for the query currently executing in this transaction, or `null` if no query is currently executing. m| DURATION -// New in 5.0 + m| currentQueryIdleTime a| Idle time for the query currently executing in this transaction, or `null` if unavailable or no query is currently executing. m| DURATION -// New in 5.0 + m| currentQueryAllocatedBytes a| The number of bytes allocated on the heap so far by the query currently executing in this transaction, or `null` if unavailable or no query is currently executing. m| INTEGER @@ -184,12 +184,12 @@ m| pageFaults a| The total number of page cache faults that the transaction performed. m| INTEGER -// New in 5.0 + m| currentQueryPageHits a| The total number of page cache hits that the query currently executing in this transaction performed. m| INTEGER -// New in 5.0 + m| currentQueryPageFaults a| The total number of page cache faults that the query currently executing in this transaction performed. m| INTEGER diff --git a/modules/ROOT/pages/clauses/union.adoc b/modules/ROOT/pages/clauses/union.adoc index 2e4e41178..b193a7786 100644 --- a/modules/ROOT/pages/clauses/union.adoc +++ b/modules/ROOT/pages/clauses/union.adoc @@ -95,7 +95,7 @@ The combined result is returned, without duplicates. |Rows: 3 |=== -[role=label--new-5.19] + [[union-distinct]] === UNION DISTINCT diff --git a/modules/ROOT/pages/clauses/use.adoc b/modules/ROOT/pages/clauses/use.adoc index 7205b8389..4f1811d20 100644 --- a/modules/ROOT/pages/clauses/use.adoc +++ b/modules/ROOT/pages/clauses/use.adoc @@ -116,7 +116,7 @@ MATCH (n) RETURN n [[query-use-examples-query-composite-database-by-element-id]] === Query a composite database constituent using elementId -The `graph.byElementId()` function (introduced in Neo4j 5.13), can be used in the `USE` clause to resolve a constituent graph to which a given element id belongs. +The `graph.byElementId()` function, can be used in the `USE` clause to resolve a constituent graph to which a given element id belongs. In the below example, it is assumed that the DBMS contains a composite database constituent, which contains the element id `4:c0a65d96-4993-4b0c-b036-e7ebd9174905:0`. If the constituent database is not a standard database in the DBMS an error will be thrown: .Query diff --git a/modules/ROOT/pages/clauses/where.adoc b/modules/ROOT/pages/clauses/where.adoc index 90334ffab..9d4546119 100644 --- a/modules/ROOT/pages/clauses/where.adoc +++ b/modules/ROOT/pages/clauses/where.adoc @@ -341,7 +341,7 @@ The `name` and `age` for `Peter` are are returned because his name contains "ete [[match-string-is-normalized]] === Checking if a `STRING` `IS NORMALIZED` -The `IS NORMALIZED` operator (introduced in Neo4j 5.17) is used to check whether the given `STRING` is in the `NFC` Unicode normalization form: +The `IS NORMALIZED` operator is used to check whether the given `STRING` is in the `NFC` Unicode normalization form: .Query [source, cypher] diff --git a/modules/ROOT/pages/constraints/syntax.adoc b/modules/ROOT/pages/constraints/syntax.adoc index 49dbe30db..e7762d7c3 100644 --- a/modules/ROOT/pages/constraints/syntax.adoc +++ b/modules/ROOT/pages/constraints/syntax.adoc @@ -334,4 +334,4 @@ This means its default behavior is to throw an error if an attempt is made to dr With the `IF EXISTS` flag, no error is thrown and nothing happens should the constraint not exist. Instead, an informational notification is returned detailing that the constraint does not exist. -For examples on how to drop constraints, see xref:constraints/managing-constraints.adoc#drop-constraint[Create, show, and drop constraints -> DROP CONSTRAINT]. +For examples on how to drop constraints, see xref:constraints/managing-constraints.adoc#drop-constraint[Create, show, and drop constraints -> DROP CONSTRAINT]. \ No newline at end of file diff --git a/modules/ROOT/pages/functions/aggregating.adoc b/modules/ROOT/pages/functions/aggregating.adoc index 2976c3666..f6b9836ac 100644 --- a/modules/ROOT/pages/functions/aggregating.adoc +++ b/modules/ROOT/pages/functions/aggregating.adoc @@ -275,7 +275,7 @@ The number of nodes with the label `Person` and a property `age` is returned: The default behavior of the `count` function is to count all matching results, including duplicates. To avoid counting duplicates, use the `DISTINCT` keyword. -As of Neo4j 5.15, it is also possible to use the `ALL` keyword with aggregating functions. +It is also possible to use the `ALL` keyword with aggregating functions. This will count all results, including duplicates, and is functionally the same as not using the `DISTINCT` keyword. The `ALL` keyword was introduced as part of Cypher's xref:appendix/gql-conformance/index.adoc[]. diff --git a/modules/ROOT/pages/functions/database.adoc b/modules/ROOT/pages/functions/database.adoc index 929d72d90..8ba36ae72 100644 --- a/modules/ROOT/pages/functions/database.adoc +++ b/modules/ROOT/pages/functions/database.adoc @@ -2,7 +2,6 @@ = Database functions :description: Database functions provide information about databases :test-skip: true -:page-role: new-5.12 :table-caption!: [[functions-database-nameFromElementId]] diff --git a/modules/ROOT/pages/functions/graph.adoc b/modules/ROOT/pages/functions/graph.adoc index 89ddf6a20..174910a8d 100644 --- a/modules/ROOT/pages/functions/graph.adoc +++ b/modules/ROOT/pages/functions/graph.adoc @@ -165,7 +165,7 @@ Returns all nodes from all graphs on the current composite database. ====== -[role=label--new-5.13] + [[functions-graph-by-elementid]] == graph.byElementId() diff --git a/modules/ROOT/pages/functions/index.adoc b/modules/ROOT/pages/functions/index.adoc index bb324d520..b077f3af1 100644 --- a/modules/ROOT/pages/functions/index.adoc +++ b/modules/ROOT/pages/functions/index.adoc @@ -73,7 +73,7 @@ These functions take multiple values as arguments, and calculate and return an a |=== -[role=label--new-5.12] + [[header-query-functions-database]] == Database functions @@ -88,7 +88,7 @@ Database functions provide information about databases. |=== -[role=label--new-5.12] + [[header-query-functions-genai]] == GenAI functions @@ -110,7 +110,7 @@ Graph functions provide information about the constituent graphs in composite da 1.1+| xref:functions/graph.adoc#functions-graph-by-elementid[`graph.byElementId()`] | `USE graph.byElementId(elementId :: STRING)` | Resolves the constituent graph to which a given element id belongs. -label:new[Introduced in 5.13] + 1.1+| xref:functions/graph.adoc#functions-graph-byname[`graph.byName()`] | `USE graph.byName(name :: STRING)` | Resolves a constituent graph by name. 1.1+| xref:functions/graph.adoc#functions-graph-names[`graph.names()`] | `graph.names() :: LIST` | Returns a list containing the names of all graphs in the current composite database. 1.1+| xref:functions/graph.adoc#functions-graph-names[`graph.propertiesByName()`] | `graph.propertiesByName(name :: STRING) :: MAP` | Returns a map containing the properties associated with the given graph. @@ -389,12 +389,12 @@ These functions return a single value. 1.1+| xref::functions/scalar.adoc#functions-char_length[`char_length()`] | `char_length(input :: STRING) :: INTEGER` | Returns the number of Unicode characters in a `STRING`. -label:new[Introduced in 5.13] + 1.1+| xref::functions/scalar.adoc#functions-character_length[`character_length()`] | `character_length(input :: STRING) :: INTEGER` | Returns the number of Unicode characters in a `STRING`. -label:new[Introduced in 5.13] + 1.1+| xref::functions/scalar.adoc#functions-coalesce[`coalesce()`] | `coalesce(input :: ANY) :: ANY` @@ -491,7 +491,7 @@ These functions are used to manipulate `STRING` values or to create a `STRING` r 1.1+| xref::functions/string.adoc#functions-btrim[`btrim()`] | `btrim(original :: STRING [, trimCharacterString :: STRING ]) :: STRING` -| Returns the given `STRING` with leading and trailing whitespace removed, optionally specifying a `trimCharacterString` value to remove. label:new[Introduced in 5.20] +| Returns the given `STRING` with leading and trailing whitespace removed, optionally specifying a `trimCharacterString` value to remove. 1.1+| xref::functions/string.adoc#functions-left[`left()`] | `left(original :: STRING, length :: INTEGER) :: STRING` @@ -499,7 +499,7 @@ These functions are used to manipulate `STRING` values or to create a `STRING` r 1.1+| xref::functions/string.adoc#functions-lower[`lower()`] | `lower(input :: STRING) :: STRING` -| Returns the given `STRING` in lowercase. This function is an alias to the xref:functions/string.adoc#functions-tolower[`toLower()`] function, and it was introduced as part of Cypher's xref:appendix/gql-conformance/index.adoc[]. label:new[Introduced in 5.21] +| Returns the given `STRING` in lowercase. This function is an alias to the xref:functions/string.adoc#functions-tolower[`toLower()`] function, and it was introduced as part of Cypher's xref:appendix/gql-conformance/index.adoc[]. 1.1+| xref::functions/string.adoc#functions-ltrim[`ltrim()`] | `ltrim(input :: STRING [, trimCharacterString :: STRING]) :: STRING` @@ -507,7 +507,7 @@ These functions are used to manipulate `STRING` values or to create a `STRING` r 1.1+| xref::functions/string.adoc#functions-normalize[`normalize()`] | `normalize(input :: STRING [,normalForm = NFC :: [NFC, NFD, NFKC, NFKD]]) :: STRING` -| Normalizes a `STRING`, optionally specifying a normalization form. label:new[Introduced in 5.17] +| Normalizes a `STRING`, optionally specifying a normalization form. 1.1+| xref::functions/string.adoc#functions-replace[`replace()`] | `replace(original :: STRING, search :: STRING, replace :: STRING) :: STRING` @@ -555,7 +555,7 @@ These functions are used to manipulate `STRING` values or to create a `STRING` r 1.1+| xref::functions/string.adoc#functions-upper[`upper()`] | `upper(input :: STRING) :: STRING` -| Returns the given `STRING` in uppercase. This function is an alias to the xref:functions/string.adoc#functions-toupper[`toUpper()`] function, and it was introduced as part of Cypher's xref:appendix/gql-conformance/index.adoc[]. label:new[Introduced in 5.21] +| Returns the given `STRING` in uppercase. This function is an alias to the xref:functions/string.adoc#functions-toupper[`toUpper()`] function, and it was introduced as part of Cypher's xref:appendix/gql-conformance/index.adoc[]. |=== [[header-query-functions-spatial]] @@ -757,7 +757,7 @@ There are two main types of functions that can be developed and used: |=== -[role=label--new-5.18] + [[header-query-functions-vector]] == Vector functions diff --git a/modules/ROOT/pages/functions/scalar.adoc b/modules/ROOT/pages/functions/scalar.adoc index 459102044..977732cc0 100644 --- a/modules/ROOT/pages/functions/scalar.adoc +++ b/modules/ROOT/pages/functions/scalar.adoc @@ -30,7 +30,7 @@ CREATE (bob)-[:MARRIED]->(eskil) ---- -[role=label--new-5.13] + [[functions-char_length]] == char_length() @@ -76,7 +76,7 @@ The number of Unicode characters in the `STRING` is returned. ====== -[role=label--new-5.13] + [[functions-character_length]] == character_length() @@ -1184,7 +1184,7 @@ The relationship type of `r` is returned. ====== -[role=label--new-5.13] + [[functions-valueType]] == valueType() @@ -1205,12 +1205,12 @@ Future releases of Cypher may include updates to the current type system. This can include the introduction of new types and subtypes of already supported types. If a new type is introduced, it will be returned by the `valueType()` function as soon as it is released. However, if a more precise subtype of a previously supported type is introduced, it would be considered a breaking change. -As a result, any new subtypes introduced after the release of Neo4j 5.13 will not be returned by the `valueType()` function until the following major release (Neo4j 6.0). + For example, the function currently returns `"FLOAT"`, but if a more specific `FLOAT` type was added, e.g. `FLOAT32`, this would be considered more specific and not be returned until Neo4j 6.0. As a result,`"FLOAT"` would continue to be returned for any `FLOAT32` values until the release of Neo4j 6.0. -With this in mind, the below list contains all supported types (as of Neo4j 5.13) displayed by the `valueType()` function until the release of Neo4j 6.0: +The below list contains all supported types displayed by the `valueType()` function: * Predefined types ** `NOTHING` diff --git a/modules/ROOT/pages/functions/string.adoc b/modules/ROOT/pages/functions/string.adoc index 68725bd94..3519af475 100644 --- a/modules/ROOT/pages/functions/string.adoc +++ b/modules/ROOT/pages/functions/string.adoc @@ -18,7 +18,7 @@ This `STRING` will therefore be formatted according to the https://en.wikipedia. See also xref::syntax/operators.adoc#query-operators-string[String operators]. -[role=label--new-5.20] + [[functions-btrim]] == btrim() @@ -111,7 +111,7 @@ RETURN left('hello', 3) ====== -[role=label--new-5.21] + [[functions-lower]] == lower() @@ -174,8 +174,7 @@ RETURN lower('HELLO') | `ltrim(null, null)` returns `null`. | `ltrim("hello", null)` returns `null`. | `ltrim(null, ' ')` returns `null`. -| As of Neo4j 5.20, a `trimCharacterString` can be specified. -If this is not specified all leading whitespace will be removed. +| If `trimCharacterString` is not specified all leading whitespace will be removed. |=== @@ -202,7 +201,7 @@ RETURN ltrim(' hello'), ltrim('xxyyhelloxyxy', 'xy') ====== -[role=label--new-5.17] + [[functions-normalize]] == normalize() @@ -466,8 +465,7 @@ RETURN right('hello', 3) | `rtrim(null, null)` returns `null`. | `rtrim("hello", null)` returns `null`. | `rtrim(null, ' ')` returns `null`. -| As of Neo4j 5.20, a `trimCharacterString` can be specified. -If this is not specified all trailing whitespace will be removed. +| If `trimCharacterString` is not specified all leading whitespace will be removed. |=== @@ -787,8 +785,7 @@ RETURN toUpper('hello') | `trim(null FROM "hello")` returns `null`. | `trim(" " FROM null)` returns `null`. | `trim(BOTH null FROM null)` returns `null`. -| As of Neo4j 5.20, a `trimSpecification` and a `trimCharacterString` can be specified. -If these are not specified all leading and/or trailing whitespace will be removed. +| If `trimSpecification` and a `trimCharacterString` are not specified all leading and/or trailing whitespace will be removed. |=== @@ -814,7 +811,7 @@ RETURN trim(' hello '), trim(BOTH 'x' FROM 'xxxhelloxxx') ====== -[role=label--new-5.21] + [[functions-upper]] == upper() diff --git a/modules/ROOT/pages/functions/vector.adoc b/modules/ROOT/pages/functions/vector.adoc index 3db5ecef0..467c4b80d 100644 --- a/modules/ROOT/pages/functions/vector.adoc +++ b/modules/ROOT/pages/functions/vector.adoc @@ -1,5 +1,4 @@ :description: Vector functions allow you to compute the similarity scores of vector pairs. -:page-role: new-5.18 :table-caption!: :link-vector-indexes: xref:indexes/semantic-indexes/vector-indexes.adoc diff --git a/modules/ROOT/pages/genai-integrations.adoc b/modules/ROOT/pages/genai-integrations.adoc index 5168f0d01..649de2644 100644 --- a/modules/ROOT/pages/genai-integrations.adoc +++ b/modules/ROOT/pages/genai-integrations.adoc @@ -1,5 +1,4 @@ :description: Information about Neo4j's GenAI integrations. -:page-role: new-5.17 :test-setup-dump: https://github.com/neo4j-graph-examples/recommendations/raw/main/data/recommendations-50.dump include::https://raw.githubusercontent.com/neo4j-graphacademy/courses/main/asciidoc/courses/llm-fundamentals/ad.adoc[] @@ -25,8 +24,6 @@ The plugin needs to be installed on self-managed instances. This is done by moving the `neo4j-genai.jar` file from `/products` to `/plugins` in the Neo4j home directory, or, if you are using Docker, by starting the Docker container with the extra parameter `--env NEO4J_PLUGINS='["genai"]'`. For more information, see link:{neo4j-docs-base-uri}/operations-manual/{page-version}/configuration/plugins/[Operations Manual -> Configure plugins]. -[NOTE] -Prior to Neo4j 5.23, the GenAI plugin was only available on Neo4j Enterprise Edition. [[example-graph]] == Example graph @@ -38,7 +35,7 @@ image::genai_graph.svg[width="600",role="middle"] The graph contains 28863 nodes and 332522 relationships. There are 9083 `Movie` nodes with a `plot` and `title` property. -To recreate the graph, download and import this link:https://github.com/neo4j-graph-examples/recommendations/blob/main/data/recommendations-embeddings-50.dump[dump file] to an empty Neo4j database (running version 5.17 or later). +To recreate the graph, download and import this link:https://github.com/neo4j-graph-examples/recommendations/blob/main/data/recommendations-embeddings-50.dump[dump file] to an empty Neo4j database. Dump files can be imported for both link:{neo4j-docs-base-uri}/aura/auradb/importing/import-database/[Aura] and link:{neo4j-docs-base-uri}/operations-manual/{page-version}/backup-restore/restore-dump/[on-prem] instances. [NOTE] @@ -79,7 +76,7 @@ db.create.setNodeVectorProperty(node :: NODE, key :: STRING, vector :: ANY) Use the `db.create.setRelationshipVectorProperty` procedure to store an embedding to a relationship property. -.Signature for `db.create.setRelationshipVectorProperty` label:procedure[] label:new[Introduced in 5.18] +.Signature for `db.create.setRelationshipVectorProperty` label:procedure[] [source,syntax] ---- db.create.setRelationshipVectorProperty(relationship :: RELATIONSHIP, key :: STRING, vector :: ANY) @@ -197,8 +194,7 @@ Because vector embeddings can be very large, a larger batch size may require sig Too large a batch size may also exceed the provider's threshold. <3> Process `Movie` nodes in increments of `batchSize`. <4> A xref:subqueries/subqueries-in-transactions.adoc[`CALL` subquery] executes a separate transaction for each batch. -Note that this `CALL` subquery uses a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause] (introduced in Neo4j 5.23) to import variables. -If you are using an older version of Neo4j, use an xref:subqueries/call-subquery.adoc#importing-with[importing `WITH` clause] instead. +Note that this `CALL` subquery uses a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause]. <5> `resources` is a list of strings, each being the concatenation of `title` and `plot` of one movie. <6> The procedure sets `vector` as value for the property named `embedding` for the node at position `batchStart + index` in the `moviesList`. <7> Set to `1` the amount of batches to be processed at once. @@ -246,10 +242,10 @@ Each provider has its own configuration map that can be passed to `genai.vector. Supported values: + + -* `"textembedding-gecko@001"` label:new[Introduced in 5.17] -* `"textembedding-gecko@002"` label:new[Introduced in 5.19] -* `"textembedding-gecko@003"` label:new[Introduced in 5.19] -* `"textembedding-gecko-multilingual@001"` label:new[Introduced in 5.19] +* `"textembedding-gecko@001"` +* `"textembedding-gecko@002"` +* `"textembedding-gecko@003"` +* `"textembedding-gecko-multilingual@001"` | `"textembedding-gecko@001"` @@ -298,12 +294,12 @@ Supported values: + | taskType | STRING -| The intended downstream application (see link:https://cloud.google.com/vertex-ai/generative-ai/docs/embeddings/get-text-embeddings#api_changes_to_models_released_on_or_after_august_2023[provider documentation]). The specified `taskType` will apply to all resources in a batch. label:new[Introduced in 5.19] +| The intended downstream application (see link:https://cloud.google.com/vertex-ai/generative-ai/docs/embeddings/get-text-embeddings#api_changes_to_models_released_on_or_after_august_2023[provider documentation]). The specified `taskType` will apply to all resources in a batch. | | title | STRING -| The title of the document that is being encoded (see link:https://cloud.google.com/vertex-ai/generative-ai/docs/embeddings/get-text-embeddings#api_changes_to_models_released_on_or_after_august_2023[provider documentation]). The specified `title` will apply to all resources in a batch. label:new[Introduced in 5.19] +| The title of the document that is being encoded (see link:https://cloud.google.com/vertex-ai/generative-ai/docs/embeddings/get-text-embeddings#api_changes_to_models_released_on_or_after_august_2023[provider documentation]). The specified `title` will apply to all resources in a batch. | |=== ==== @@ -340,7 +336,7 @@ Supported values: + ==== [[azure-openai]] -[role=label--new-5.18] + === Azure OpenAI * Identifier (`provider` argument): `"AzureOpenAI"` diff --git a/modules/ROOT/pages/indexes/search-performance-indexes/managing-indexes.adoc b/modules/ROOT/pages/indexes/search-performance-indexes/managing-indexes.adoc index 2487e32ad..d235707e9 100644 --- a/modules/ROOT/pages/indexes/search-performance-indexes/managing-indexes.adoc +++ b/modules/ROOT/pages/indexes/search-performance-indexes/managing-indexes.adoc @@ -31,7 +31,7 @@ The `CREATE INDEX` command is optionally idempotent. This mean that its default behavior is to throw an error if an attempt is made to create the same index twice. If `IF NOT EXISTS` is appended to the command, no error is thrown and nothing happens should an index with the same name or same schema and index type already exist. It may still throw an error if conflicting constraints exist, such as constraints with the same name or schema and backing index type. -As of Neo4j 5.17, an informational notification is instead returned showing the existing index which blocks the creation. +Instead, an informational notification is returned showing the existing index which blocks the creation. Index providers and configuration settings can be specified using the `OPTIONS` clause.footnote:[Index providers are essentially different implementations of the same index type. Different providers are only available for xref:indexes/search-performance-indexes/managing-indexes.adoc#create-a-text-index-specifying-the-index-provider[text indexes].] @@ -169,8 +169,6 @@ CREATE INDEX composite_range_rel_index_name FOR ()-[r:PURCHASED]-() ON (r.date, [[create-a-range-index-by-param]] ===== Create a range index using a parameter -_This feature was introduced in Neo4j 5.16._ - The following statement will create a named range index on all nodes with a `Person` label and a `firstname` property using a parameter for the index name. .Parameters @@ -201,7 +199,7 @@ FOR (n:Person) ON (n.surname) ---- The index will not be created if there already exists an index with the same schema and type, same name or both. -As of Neo4j 5.17, an informational notification is instead returned. +Instad an informational notification is returned. .Notification [source] @@ -216,7 +214,7 @@ As of Neo4j 5.17, an informational notification is instead returned. Creating a text index can be done with the `CREATE TEXT INDEX` command. Note that the index name must be unique. -Text indexes have no supported index configuration and, as of Neo4j 5.1, they have two index providers available, `text-2.0` (default) and `text-1.0` (deprecated). +Text indexes have no supported index configuration and they have two index providers available, `text-2.0` (default) and `text-1.0` (deprecated). [[text-indexes-supported-predicates]] [discrete] @@ -280,8 +278,8 @@ CONTAINS |=== -As of Neo4j 5.11, the above set of predicates can be extended with the use of property type constraints. -See the section about xref:indexes/search-performance-indexes/using-indexes.adoc#type-constraints[index compatibility and property type constraints] for more information. +The above set of predicates can be extended with the use of type constraints. +See the section about xref:indexes/search-performance-indexes/using-indexes.adoc#type-constraints[index compatibility and type constraints] for more information. [TIP] Text indexes are only used for exact query matches. To perform approximate matches (including, for example, variations and typos), and to compute a similarity score between `STRING` values, use semantic xref:indexes/semantic-indexes/full-text-indexes.adoc[full-text indexes] instead. @@ -324,8 +322,6 @@ CREATE TEXT INDEX rel_text_index_name FOR ()-[r:KNOWS]-() ON (r.interest) [[create-a-text-index-by-param]] ===== Create a text index using a parameter -_This feature was introduced in Neo4j 5.16._ - The following statement will create a named text index on all nodes with the `Person` label the `favoriteColor` `STRING` property using a parameter for the index name. .Parameters @@ -357,7 +353,7 @@ CREATE TEXT INDEX node_index_name IF NOT EXISTS FOR (n:Person) ON (n.nickname) ---- Note that the index will not be created if there already exists an index with the same schema and type, same name or both. -As of Neo4j 5.17, an informational notification is instead returned. +Instead, an informational notification is returned. .Notification [source] @@ -426,8 +422,8 @@ point.distance(n.prop, center) < = distance |=== -As of Neo4j 5.11, the above set of predicates can be extended with the use of property type constraints. -See xref:indexes/search-performance-indexes/using-indexes.adoc#index-compatibility-type-constraints[Index compatibility and property type constraints] for more information. +The above set of predicates can be extended with the use of type constraints. +See xref:indexes/search-performance-indexes/using-indexes.adoc#index-compatibility-type-constraints[Index compatibility and type constraints] for more information. [TIP] To learn more about the spatial data types supported by Cypher, see the page about xref:values-and-types/spatial.adoc[Spatial values]. @@ -470,8 +466,6 @@ CREATE POINT INDEX rel_point_index_name FOR ()-[r:STREET]-() ON (r.intersection) [[create-a-point-index-by-param]] ===== Create a point index using a parameter -_This feature was introduced in Neo4j 5.16._ - The following statement will create a named point index on all relationships with relationship type `STREET` and `POINT` property `coordinate` using a parameter for the index name. .Parameters @@ -502,7 +496,7 @@ FOR (n:Person) ON (n.sublocation) ---- Note that the index will not be created if there already exists an index with the same schema and type, same name or both. -As of Neo4j 5.17, an informational notification is instead returned. +Instead, an informational notification is returned. .Notification [source] @@ -656,7 +650,7 @@ CREATE LOOKUP INDEX node_label_lookup IF NOT EXISTS FOR (n) ON EACH labels(n) ---- The index will not be created if there already exists an index with the same schema and type, same name or both. -As of Neo4j 5.17, an informational notification is instead returned. +Instead, an informational notification is returned. .Notification [source] @@ -985,7 +979,7 @@ The below table contains the full information about all columns returned by the | The index provider for this index. label:default-output[] | `STRING` -// New in 5.0 + | `owningConstraint` | The name of the constraint the index is associated with or `null` if the index is not associated with any constraint. label:default-output[] | `STRING` @@ -994,17 +988,17 @@ The below table contains the full information about all columns returned by the | The last time the index was used for reading. Returns `null` if the index has not been read since `trackedSince`, or if the statistics are not tracked. label:default-output[] -label:new[Introduced in 5.8] + | `ZONED DATETIME` | `readCount` | The number of read queries that have been issued to this index since `trackedSince`, or `null` if the statistics are not tracked. label:default-output[] -label:new[Introduced in 5.8] + | `INTEGER` | `trackedSince` | The time when usage statistics tracking started for this index, or `null` if the statistics are not tracked. -label:new[Introduced in 5.8] + | `ZONED DATETIME` | `options` @@ -1038,7 +1032,7 @@ DROP INDEX index_name [IF EXISTS] The `DROP INDEX` command is optionally idempotent. This means that its default behavior is to throw an error if an attempt is made to drop the same index twice. With `IF EXISTS`, no error is thrown and nothing happens should the index not exist. -As of Neo4j 5.17, an informational notification is instead returned detailing that the index does not exist. +Instead, an informational notification is returned detailing that the index does not exist. [TIP] Dropping an index requires link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/authentication-authorization/database-administration/#access-control-database-administration-index[the `DROP INDEX` privilege]. @@ -1070,8 +1064,6 @@ If an index with that name exists it is removed, if not the command fails. [[drop-an-index-by-param]] ==== Drop an index using a parameter -_This feature was introduced in Neo4j 5.16._ - The following statement will attempt to drop the index named `range_index_param` using a parameter for the index name. .Parameters @@ -1125,8 +1117,7 @@ The following statement will attempt to drop the index named `missing_index_name DROP INDEX missing_index_name IF EXISTS ---- -If an index with that name exists it is removed, if not the command does nothing. -As of Neo4j 5.17, additionally, an informational notification is returned. +If an index with that name exists it is removed, if not the command does nothing and an informational notification is instead returned. .Notification [source] diff --git a/modules/ROOT/pages/indexes/search-performance-indexes/using-indexes.adoc b/modules/ROOT/pages/indexes/search-performance-indexes/using-indexes.adoc index 7a163a8f1..98f7ffb45 100644 --- a/modules/ROOT/pages/indexes/search-performance-indexes/using-indexes.adoc +++ b/modules/ROOT/pages/indexes/search-performance-indexes/using-indexes.adoc @@ -854,7 +854,7 @@ This plan shows that the previously created range index on the `name` property i Text indexes require that predicates only include `STRING` properties. -To use text indexes in situations where any of the queried properties may be either of an incompatible type or `null` rather than a `STRING` value, add the type predicate expression `IS {two-colons} STRING NOT NULL` (or its alias, introduced in Neo4j 5.14, `IS {two-colons} STRING!`) to the query. +To use text indexes in situations where any of the queried properties may be either of an incompatible type or `null` rather than a `STRING` value, add the type predicate expression `IS {two-colons} STRING NOT NULL` (or its alias, `IS {two-colons} STRING!`) to the query. This will enforce both the existence of a property and its `STRING` type, discarding any rows where the property is missing or not of type `STRING`, and thereby enable the use of text indexes. For example, if the `WHERE` predicate in the previous query is altered to instead append `IS {two-colons} STRING NOT NULL`, then the text index rather than the range index is used (range indexes do not support type predicate expressions): @@ -884,13 +884,9 @@ RETURN count(n) AS nodes Total database accesses: 186, total allocated memory: 472 ---- -[TIP] -While type predicate expressions were introduced in Neo4j 5.9, the `IS {two-colons} STRING NOT NULL` syntax only became an index-compatible predicate in Neo4j 5.15. -For more information, see the page about xref:values-and-types/type-predicate.adoc[type predicate expressions]. - The xref:functions/string.adoc#functions-tostring[`toString`] function can also be used to convert an expression to `STRING` values, and thereby help the planner to select a text index. -[role=label--new-5.11] + [[type-constraints]] === Property type constraints @@ -1007,7 +1003,7 @@ As a result of these two points, deciding what to index (and what not to index) Unused indexes take up unnecessary storage space and it may be beneficial to remove them. Knowing which indexes are most frequently used by the queries against a database can, however, be difficult. -As of Neo4j 5.8, there are three relevant columns returned by the xref:indexes/search-performance-indexes/managing-indexes.adoc#list-indexes[`SHOW INDEX`] command which can help identify redundant indexes: +There are three relevant columns returned by the xref:indexes/search-performance-indexes/managing-indexes.adoc#list-indexes[`SHOW INDEX`] command which can help identify redundant indexes: * *`lastRead`*: returns the last time the index was used for reading. * *`readCount`*: returns the number of read queries issued to the index. diff --git a/modules/ROOT/pages/indexes/semantic-indexes/full-text-indexes.adoc b/modules/ROOT/pages/indexes/semantic-indexes/full-text-indexes.adoc index 647bb9a65..0dca5ae71 100644 --- a/modules/ROOT/pages/indexes/semantic-indexes/full-text-indexes.adoc +++ b/modules/ROOT/pages/indexes/semantic-indexes/full-text-indexes.adoc @@ -38,8 +38,8 @@ If no name is given when created, a random name will be assigned to the full-tex The `CREATE FULLTEXT INDEX` command is optionally idempotent. This mean that its default behavior is to throw an error if an attempt is made to create the same index twice. If `IF NOT EXISTS` is appended to the command, no error is thrown and nothing happens should an index with the same name or a full-text index on the same schema already exist. -As of Neo4j 5.17, an informational notification is instead returned showing the existing index which blocks the creation. -As of Neo4j 5.16, the index name can also be given as a parameter, `CREATE FULLTEXT INDEX $name FOR ...`. +Instead, an informational notification is returned showing the existing index which blocks the creation. +The index name can also be given as a parameter, `CREATE FULLTEXT INDEX $name FOR ...`. [TIP] Creating a full-text index requires the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/database-administration/#access-control-database-administration-index[`CREATE INDEX` privilege]. @@ -101,7 +101,6 @@ For more information, see the link:{neo4j-docs-base-uri}/java-reference/{page-ve The `CREATE FULLTEXT INDEX` command takes an optional `OPTIONS` clause, where the `indexConfig` can be specified. The following statement creates a full-text index using a parameter for nodes with the label `Employee` or `Manager`. -Creating and dropping indexes using parameters was introduced in Neo4j 5.16. .Parameters [source, parameters] @@ -352,7 +351,7 @@ In the following example, the previously created `communications` full-text inde DROP INDEX communications ---- -As of Neo4j 5.16, the index name can also be given as a parameter when dropping an index: `DROP INDEX $name`. +The index name can also be given as a parameter when dropping an index: `DROP INDEX $name`. [[full--text-index-procedures]] == List of full-text index procedures diff --git a/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc b/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc index 13c8334b2..9ca635bbd 100644 --- a/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc +++ b/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc @@ -1,13 +1,10 @@ :description: Information about creating, querying, and deleting vector indexes with Cypher. -:page-role: new-5.13 :test-setup-dump: https://github.com/neo4j-graph-examples/recommendations/raw/main/data/recommendations-embeddings-50.dump :l2-norm: image:l2.svg["l2"]-norm include::https://raw.githubusercontent.com/neo4j-graphacademy/courses/main/asciidoc/courses/llm-vectors-unstructured/ad.adoc[] = Vector indexes -_Node vector indexes were released as a public beta in Neo4j 5.11 and general availability in Neo4j 5.13._ - Vector indexes enable similarity searches and complex analytical queries by representing nodes or properties as vectors in a multidimensional space. The following resources provide hands-on tutorials for working with LLMs and vector indexes in Neo4j: @@ -29,7 +26,7 @@ image::vector_index_graph.svg[width="600",role="middle"] The graph contains 28863 nodes and 332522 relationships. -To recreate the graph, download and import this link:https://github.com/neo4j-graph-examples/recommendations/blob/main/data/recommendations-embeddings-50.dump[dump file] to an empty Neo4j database (running version 5.13 or later). +To recreate the graph, download and import this link:https://github.com/neo4j-graph-examples/recommendations/blob/main/data/recommendations-embeddings-50.dump[dump file] to an empty Neo4j database. Dump files can be imported for both link:{neo4j-docs-base-uri}/aura/auradb/importing/import-database/[Aura] and link:{neo4j-docs-base-uri}/operations-manual/{page-version}/backup-restore/restore-dump/[on-prem] instances. [NOTE] @@ -77,7 +74,7 @@ For more information, see xref:indexes/semantic-indexes/vector-indexes.adoc#vect A vector index is created by using the `CREATE VECTOR INDEX` command. It is recommended to give the index a name when it is created. If no name is given when created, a random name will be assigned. -As of Neo4j 5.16, the index name can also be given as a parameter: `CREATE VECTOR INDEX $name ...`. +The index name can also be given as a parameter: `CREATE VECTOR INDEX $name ...`. [NOTE] The index name must be unique among both indexes and constraints. + @@ -86,7 +83,7 @@ A newly created index is not immediately available but is created in the backgro [TIP] Creating indexes requires link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/database-administration/#access-control-database-administration-index[the `CREATE INDEX` privilege]. -.Create vector index for `Movie` nodes on the `embedding` property label:new[Introduced in 5.15] +.Create vector index for `Movie` nodes on the `embedding` property [source, cypher] ---- CREATE VECTOR INDEX moviePlots IF NOT EXISTS // <1> @@ -102,19 +99,14 @@ OPTIONS { indexConfig: { This means that its default behavior is to throw an error if an attempt is made to create the same index twice. With `IF NOT EXISTS`, no error is thrown and nothing happens should an index with the same name, schema or both already exist. It may still throw an error should a constraint with the same name exist. -As of Neo4j 5.17, an informational notification is returned when nothing happens, showing the existing index which blocks the creation. -<2> Prior to Neo4j 5.23, the `OPTIONS` map was mandatory since a vector index could not be created without setting the vector dimensions and similarity function. -Since Neo4j 5.23, both can be omitted. -To read more about the available configuration settings, see xref:indexes/semantic-indexes/vector-indexes.adoc#configuration-settings[]. +An informational notification is returned when nothing happens, showing the existing index which blocks the creation. +<2> To read more about the available configuration settings, see xref:indexes/semantic-indexes/vector-indexes.adoc#configuration-settings[]. In this example, the vector dimension is explicitly set to `1536` and the vector similarity function to `'cosine'`, which is generally the preferred similarity function for text embeddings. To read more about the available similarity functions, see xref:indexes/semantic-indexes/vector-indexes.adoc#similarity-functions[]. -[NOTE] -Prior to Neo4j 5.15, node vector indexes were created using the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_index_vector_createnodeindex[`db.index.vector.createNodeIndex`] procedure. - You can also create a vector index for relationships with a particular type on a given property using the following syntax: -.Create a vector index for a relationship type on a single property label:new[Introduced in 5.18] +.Create a vector index for a relationship type on a single property [source, cypher, role=test-skip] ---- CREATE VECTOR INDEX name IF NOT EXISTS @@ -142,7 +134,6 @@ It is recommended to provide dimensions when creating a vector index. Accepted values::: `INTEGER` between `1` and `4096` inclusively. Default value::: None. -The setting was mandatory prior to Neo4j 5.23. [[config-vector.similarity_function]] ==== `vector.similarity_function` @@ -151,16 +142,15 @@ The name of the similarity function used to assess the similarity of two vectors To read more about the available similarity functions, see xref:indexes/semantic-indexes/vector-indexes.adoc#similarity-functions[]. Accepted values::: `STRING`: `'cosine'`, `'euclidean'`. -Default value::: `'cosine'`. The setting was mandatory prior to Neo4j 5.23. +Default value::: `'cosine'`. + -[role=label--new-5.23] [[config-vector.quantization.enabled]] ==== `vector.quantization.enabled` Quantization is a technique to reduce the size of vector representations. Enabling quantization can accelerate search performance but can slightly decrease accuracy. It is recommended to enable quantization on machines with limited memory. -Vector indexes created prior to Neo4j 5.23 have this setting effectively set to `false`. Accepted values::: `BOOLEAN`: `true`, `false`. Default value::: `true` @@ -169,24 +159,22 @@ Default value::: `true` [[config-advanced]] === Advanced configuration settings -[role=label--new-5.23] + [[config-vector.hsnw.m]] ==== `vector.hnsw.m` The `M` parameter controls the maximum number of connections each node has in the HNSW (Hierarchical Navigable Small Worlds) graph. Increasing this value may lead to greater accuracy at the expense of increased index population and update times, especially for vectors with high dimensionality. -Vector indexes created prior to Neo4j 5.23 have this setting effectively set to `16`. Accepted values::: `INTEGER` between `1` and `512` inclusively. Default value::: `16` -[role=label--new-5.23] + [[config-vector.hsnw.ef_construction]] ==== `vector.hnsw.ef_construction` The number of nearest neighbors tracked during the insertion of vectors into the HNSW graph. Increasing this value increases the quality of the index, and may lead to greater accuracy (with diminishing returns) at the expense of increased index population and update times. -Vector indexes created prior to Neo4j 5.23 have this setting effectively set to `100`. Accepted values::: `INTEGER` between `1` and `3200` inclusively. Default value::: `100` @@ -238,7 +226,7 @@ If the query vector itself is not wanted, adding the predicate `WHERE score < 1` To query a relationship vector index, use the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_index_vector_queryRelationships[`db.index.vector.queryRelationships`] procedure. -.Signature for `db.index.vector.queryRelationships` label:new[Introduced in 5.18] +.Signature for `db.index.vector.queryRelationships` [source,syntax] ---- db.index.vector.queryRelationships(indexName :: STRING, numberOfNearestNeighbours :: INTEGER, query :: ANY) :: (relationship :: RELATIONSHIP, score :: FLOAT) @@ -336,7 +324,7 @@ SHOW VECTOR INDEXES YIELD name, type, entityType, labelsOrTypes, properties == Drop vector indexes A vector index is dropped by using the xref:indexes/search-performance-indexes/managing-indexes.adoc#drop-an-index[same command as for other indexes], `DROP INDEX`. -As of Neo4j 5.16, the index name can also be given as a parameter when dropping an index: `DROP INDEX $name`. +The index name can also be given as a parameter when dropping an index: `DROP INDEX $name`. [TIP] Dropping indexes requires link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/authentication-authorization/database-administration/#access-control-database-administration-index[the `DROP INDEX` privilege]. @@ -350,7 +338,7 @@ DROP INDEX moviePlots [[vector-index-providers]] == Vector index providers for compatibility -As of Neo4j 5.18, the default and preferred vector index provider is `vector-2.0`. +The default and preferred vector index provider is `vector-2.0`. Previously created `vector-1.0` indexes will continue to function. New indexes can still be created with the `vector-1.0` provider if it is specified in the `OPTIONS` map. @@ -484,11 +472,11 @@ Returns the requested number of approximate nearest neighbor nodes and their sim | Use relationship vector index. | link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_index_vector_queryRelationships[`db.index.vector.queryRelationships`] | Query the given relationship vector index. -Returns the requested number of approximate nearest neighbor relationships and their similarity score, ordered by score. label:new[Introduced in 5.18] +Returns the requested number of approximate nearest neighbor relationships and their similarity score, ordered by score. | Set node vector property. | link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_create_setNodeVectorProperty[`db.create.setNodeVectorProperty`] -| Update a given node property with the given vector in a more space-efficient way than directly using xref:clauses/set.adoc#set-set-a-property[`SET`]. Replaces link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_create_setVectorProperty[`db.create.setVectorProperty`]. label:beta[] label:new[Introduced in 5.13] +| Update a given node property with the given vector in a more space-efficient way than directly using xref:clauses/set.adoc#set-set-a-property[`SET`]. Replaces link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_create_setVectorProperty[`db.create.setVectorProperty`]. label:beta[] | Set node vector property. | link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_create_setVectorProperty[`db.create.setVectorProperty`] @@ -496,14 +484,14 @@ Returns the requested number of approximate nearest neighbor relationships and t | Set relationship vector property. | link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_create_setRelationshipVectorProperty[`db.create.setRelationshipVectorProperty`] -| Update a given relationship property with the given vector in a more space-efficient way than directly using xref:clauses/set.adoc#set-set-a-property[`SET`]. label:beta[] label:new[Introduced in 5.18] +| Update a given relationship property with the given vector in a more space-efficient way than directly using xref:clauses/set.adoc#set-set-a-property[`SET`]. label:beta[] |=== [[limitations-and-issues]] == Limitations and known issues -As of Neo4j 5.13, the vector index is no longer a beta feature. +The vector index is no longer a beta feature. It does, however, still contain some limitations and known issues. .*Limitations* @@ -545,135 +533,6 @@ The types are still enforced as `LIST`. -- | -| No provided settings or options for tuning the index. -| Neo4j 5.23 - -| Only node vector indexes are supported. -| Neo4j 5.18 - -| Vector indexes cannot be assigned autogenerated names. -| Neo4j 5.15 - -| There is no Cypher syntax for creating a vector index. - -[TIP] --- -Use the procedure `db.index.vector.createNodeIndex` to create the a vector index. -Procedure signature: -[source,syntax,role="noheader"] ----- -db.index.vector.createNodeIndex(indexName :: STRING, label :: STRING, propertyKey :: STRING, vectorDimension :: INTEGER, vectorSimilarityFunction :: STRING) ----- --- -| Neo4j 5.15 - -| The standard index type filtering for xref:indexes/search-performance-indexes/managing-indexes.adoc#list-indexes[`SHOW INDEXES`] command is missing. - -[TIP] --- -Filtering on vector indexes can be done with the `WHERE` clause as well: -[source,cypher] ----- -SHOW INDEXES -WHERE type = 'VECTOR' ----- --- - -| Neo4j 5.15 - -| Vector indexes may incorrectly reject valid queries in a cluster setting. -This is caused by an issue in the handling of index capabilities on followers. - -[TIP] --- -Because index capabilities will be correctly configured on a restart, this issue can be worked around by rolling the cluster after vector index creation. - -For more information about clustering in Neo4j, see the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/clustering[Operations Manual -> Clustering]. --- -| Neo4j 5.14 - -| Querying for a _single_ approximate nearest neighbor from an index would fail a validation check. Passing a `null` value would also provide an unhelpful exception. -| Neo4j 5.13 - -| Vector index queries throw an exception if the transaction state contains changes. This means that writes may only take place *after* the last vector index query in a transaction. - -[TIP] --- -To work around this issue if you need to run multiple vector index queries and make changes based on the results, you can run the queries in a `+CALL { ... } IN TRANSACTIONS+` clause to isolate them from the outer transaction's state. --- -| Neo4j 5.13 - -| xref:clauses/listing-procedures.adoc[`SHOW PROCEDURES`] does not show the vector index procedures: - -* link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_create_setVectorProperty[`db.create.setVectorProperty`] -* link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_index_vector_createNodeIndex[`db.index.vector.createNodeIndex`] -* link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_index_vector_queryNodes[`db.index.vector.queryNodes`] - -[NOTE] --- -The procedures are still usable, just not visible. --- -| Neo4j 5.12 - -| Passing `null` as an argument to some of the procedure parameters can generate a confusing exception. -| Neo4j 5.12 - -| The creation of the vector index skipped the check to limit the dimension to `2048`. - -[NOTE] --- -Vector indexes configured with a dimension greater than `2048` in Neo4j 5.11 should continue to work after the limitation is applied. --- -| Neo4j 5.12 - -d| The validation for xref:indexes/semantic-indexes/vector-indexes.adoc#similarity-functions[cosine similarity] verifies that the vector's {l2-norm} can be represented finitely in IEEE 754 *double* precision, rather than in _single_ precision. -This can lead to certain large component vectors being incorrectly indexed, and return a similarity score of `±0.0`. -| Neo4j 5.12 - -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/#procedure_db_index_vector_queryNodes[`db.index.vector.queryNodes`] query vector validation is incorrect with a xref:indexes/semantic-indexes/vector-indexes.adoc#similarity-functions[cosine] vector index. The {l2-norm} validation only considers the last component of the vector. If that component is `±0.0`, an otherwise valid query vector will be thrown as invalid. This can also result in some invalid vectors being used to query, and return a similarity score of `±0.0`. - -[TIP] --- -For {l2-norm}alized vectors (unit vectors), thus having unit length image:l2norm_is_1.svg["The l2-norm of vector v equals 1"], Euclidean and cosine similarity functions produce the same similarity ordering. -It is _recommended_ to normalize your vectors (if needed), and use a xref:indexes/semantic-indexes/vector-indexes.adoc#similarity-functions[Euclidean] vector index. --- -| Neo4j 5.12 - -| The vector index `createStatement` field from xref:indexes/search-performance-indexes/managing-indexes.adoc#list-indexes[`SHOW INDEXES`] does not correctly escape single quotes in index names, labels, and property keys. -| Neo4j 5.12 - -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/backup-restore/copy-database/[Copying a database store] with a vector index does not log the recreation command, and instead logs an error: ----- -ERROR: [StoreCopy] Unable to format statement for index 'index-name' ----- -Due to an: ----- -java.lang.IllegalArgumentException: Did not recognize index type VECTOR ----- - -[TIP] --- -If a store copy is required, make a note of the information in the `createStatement` column returned from the `SHOW INDEX` command. -For example: -[source,cypher] ----- -SHOW INDEXES YIELD type, createStatement -WHERE type = 'VECTOR' -RETURN createStatement ----- --- -| Neo4j 5.12 - -| Some of the protections preventing the use of new features during a database rolling upgrade are missing. -This can result in a transaction to create a vector index on a cluster member running Neo4j 5.11 and distributing it to other cluster members running an older Neo4j version. -The older Neo4j versions will fail to understand the transaction. - -[TIP] --- -Ensure that all cluster members have been updated to use Neo4j 5.11 (or a newer version) before calling `dbms.upgrade()` on the `system` database. Once committed, vector indexes can be safely created on the cluster. --- - -| Neo4j 5.12 |=== ==== diff --git a/modules/ROOT/pages/indexes/syntax.adoc b/modules/ROOT/pages/indexes/syntax.adoc index baede5cba..9c8342c7f 100644 --- a/modules/ROOT/pages/indexes/syntax.adoc +++ b/modules/ROOT/pages/indexes/syntax.adoc @@ -22,7 +22,7 @@ ON property_or_token_lookup_pattern The `CREATE … INDEX …` command is optionally idempotent. This means that its default behavior is to throw an error if an attempt is made to create an index with the same name twice. With `IF NOT EXISTS`, no error is thrown and nothing happens should an index with the same name or same schema and index type already exist (it may still throw an error if conflicting constraints exist, such as constraints with the same name or with the same schema and backing index). -As of Neo4j 5.17, an informational notification is instead returned showing the existing index which blocks the creation. +Instead, an informational notification is returned showing the existing index which blocks the creation. The index name must be unique among both indexes and constraints. A random name will be assigned if no name is explicitly given when an index is created. @@ -85,7 +85,7 @@ ON (r.propertyName_1) [OPTIONS “{“ option: value[, …] “}”] ---- -Text indexes have no supported index configuration and, as of Neo4j 5.1, they have two index providers available, `text-2.0` (default) and `text-1.0` (deprecated). +Text indexes have no supported index configuration and they have two index providers available, `text-2.0` (default) and `text-1.0` (deprecated). [NOTE] It is not possible to create composite text indexes on multiple properties. @@ -189,7 +189,7 @@ For more information, see xref:indexes/semantic-indexes/full-text-indexes.adoc#c [[create-vector-index]] === Vector indexes -.Create a vector index for a node label on a single property label:new[Introduced in 5.15] +.Create a vector index for a node label on a single property [source,syntax] ---- CREATE VECTOR INDEX [index_name] [IF NOT EXISTS] @@ -199,7 +199,7 @@ ON (n.propertyName) ---- [source, syntax] -.Create a vector index for a relationship type on a single property label:new[Introduced in 5.18] +.Create a vector index for a relationship type on a single property ---- CREATE VECTOR INDEX [index_name] [IF NOT EXISTS] FOR ()-”[“r:TYPE_NAME”]”-() @@ -207,11 +207,11 @@ ON (r.propertyName) [OPTIONS “{“ option: value[, …] “}”] ---- -As of Neo4j 5.18, vector indexes have two vector index providers available, `vector-2.0` (default) and `vector-1.0`. +Vector indexes have two vector index providers available, `vector-2.0` (default) and `vector-1.0`. For more information, see xref:indexes/semantic-indexes/vector-indexes.adoc#vector-index-providers[Vector index providers for compatibility]. For a full list of all vector index settings, see xref:indexes/semantic-indexes/vector-indexes.adoc#configuration-settings[Vector index configuration settings]. -Note that the `OPTIONS` clause was mandatory prior to Neo4j 5.23 because it was necessary to configure the `vector.dimensions` and `vector.similarity_function` settings when creating a vector index. + [source,syntax] ---- @@ -281,13 +281,13 @@ For more information, see xref:indexes/semantic-indexes/full-text-indexes.adoc#q [[query-vector-index]] === Vector indexes -.Query vector-text index on nodes: db.index.vector.queryNodes label:new[Introduced 5.11] +.Query vector-text index on nodes: db.index.vector.queryNodes [source,syntax] ---- CALL db.index.vector.queryNodes(indexName :: STRING, numberOfNearestNeighbours :: INTEGER, query :: LIST) ---- -.Query vector-text index on relationships: db.index.vector.queryRelationships label:new[Introduced 5.18] +.Query vector-text index on relationships: db.index.vector.queryRelationships [source,syntax] ---- CALL db.index.vector.queryRelationships(indexName :: STRING, numberOfNearestNeighbours :: INTEGER, query :: LIST) @@ -307,7 +307,7 @@ The name of the index can be found using the `SHOW INDEXES` command, given in th The `DROP INDEX` command is optionally idempotent. This means that its default behavior is to throw an error if an attempt is made to drop the same index twice. With `IF EXISTS`, no error is thrown and nothing happens should the index not exist. -As of Neo4j 5.17, an informational notification is instead returned detailing that the index does not exist. +Instead, an informational notification is returned detailing that the index does not exist. [TIP] Dropping indexes requires link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/database-administration/#access-control-database-administration-index[the `DROP INDEX` privilege]. diff --git a/modules/ROOT/pages/patterns/reference.adoc b/modules/ROOT/pages/patterns/reference.adoc index d9da89346..4ea43aaab 100644 --- a/modules/ROOT/pages/patterns/reference.adoc +++ b/modules/ROOT/pages/patterns/reference.adoc @@ -538,7 +538,7 @@ Paths matched by the path pattern can be assigned to a variable: MATCH p = ()-[r WHERE r.q = n.q]-() ---- -[role=label--new-5.9] + [[quantified-path-patterns]] == Quantified path patterns @@ -733,7 +733,7 @@ Compared to the fixed length quantifier `\{2}`, this also matches paths of lengt |=== -[role=label--new-5.9] + [[quantified-relationships]] == Quantified relationships @@ -854,8 +854,8 @@ Although the resulting quantified path pattern will match on the same paths the [[variable-length-relationships]] == Variable-length relationships -Prior to the introduction of the syntax for quantified path patterns and quantified relationships in Neo4j 5.9, the only way in Cypher to match paths of variable length was with a variable-length relationship. - This syntax is still available, but it is not xref:appendix/gql-conformance/index.adoc[GQL conformant]. +Prior to the introduction of the syntax for quantified path patterns and quantified relationships, the only way in Cypher to match paths of variable length was with a variable-length relationship. +This syntax is still available, but it is not xref:appendix/gql-conformance/index.adoc[GQL conformant]. It is equivalent to the syntax for quantified relationships, with the following differences: * Position and syntax of quantifier. @@ -1366,7 +1366,7 @@ WHERE length(p) % 2 = 0 [[shortest-functions]] == The `shortestPath()` and `allShortestPaths()` functions -Prior to the introduction of keyword-based specification of shortest path selection in Neo4j 5.21, the only available syntax for shortest paths were the functions `shortestPath()` and `allShortestPaths()`. +Prior to the introduction of keyword-based specification of shortest path selection, the only available syntax for shortest paths were the functions `shortestPath()` and `allShortestPaths()`. They are similar to `SHORTEST 1` and `ALL SHORTEST`, but with several differences: * The path pattern is passed as an argument to the functions. diff --git a/modules/ROOT/pages/patterns/shortest-paths.adoc b/modules/ROOT/pages/patterns/shortest-paths.adoc index b6f540e91..a177ffce3 100644 --- a/modules/ROOT/pages/patterns/shortest-paths.adoc +++ b/modules/ROOT/pages/patterns/shortest-paths.adoc @@ -1,5 +1,4 @@ :description: Information about finding the `SHORTEST` path patterns. -:page-role: new-5.21 = Shortest paths The Cypher keyword `SHORTEST` is used to find variations of the shortest paths between nodes. @@ -553,8 +552,7 @@ To have the planner choose the `StatefulShortestPath(Into)` instead, rewrite the For example, in the below query, using a `CALL` subquery ensures that the planner binds `a` and `b` to exactly one `Station` node respectively for each executed row, and this forces it to use `StatefulShortestPath(Into)` for each invocation of the `CALL` subquery, since a precondition of using this operator is that both boundary nodes match exactly one node each. [NOTE] -The below query uses a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause] (introduced in Neo4j 5.23) to import variables into the `CALL` subquery. -If you are using an older version of Neo4j, use an xref:subqueries/call-subquery.adoc#importing-with[importing `WITH` clause] instead. +The below query uses a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause] to import variables into the `CALL` subquery. .Query rewritten to use `StatefulShortestPath(Into)` [source,cypher] diff --git a/modules/ROOT/pages/patterns/variable-length-patterns.adoc b/modules/ROOT/pages/patterns/variable-length-patterns.adoc index 89041e57a..8274c3f56 100644 --- a/modules/ROOT/pages/patterns/variable-length-patterns.adoc +++ b/modules/ROOT/pages/patterns/variable-length-patterns.adoc @@ -5,7 +5,7 @@ Cypher can be used to match patterns of a variable or an unknown length. Such patterns can be found using quantified path patterns and quantified relationships. This page also discusses how variables work when declared in quantified path patterns (group variables), and how to use predicates in quantified path patterns. -[role=label--new-5.9] + [[quantified-path-patterns]] == Quantified path patterns @@ -193,7 +193,7 @@ RETURN d.departs AS departureTime, a.arrives AS arrivalTime |=== -[role=label--new-5.9] + [[quantified-relationships]] == Quantified relationships @@ -253,7 +253,7 @@ then it can be re-written as follows: [NOTE] ==== -Prior to the introduction of quantified path patterns and quantified relationships in Neo4j 5.9, the only method in Cypher to match paths of a variable length was through variable-length relationships. +Prior to the introduction of quantified path patterns and quantified relationships, the only method in Cypher to match paths of a variable length was through variable-length relationships. This syntax is still available but it is not xref:appendix/gql-conformance/index.adoc[GQL conformant]. It is very similar to the syntax for quantified relationships, with the following differences: diff --git a/modules/ROOT/pages/planning-and-tuning/operators/index.adoc b/modules/ROOT/pages/planning-and-tuning/operators/index.adoc index f20bacc35..3fabf028b 100644 --- a/modules/ROOT/pages/planning-and-tuning/operators/index.adoc +++ b/modules/ROOT/pages/planning-and-tuning/operators/index.adoc @@ -72,7 +72,7 @@ Restricts the xref:planning-and-tuning/runtimes/index.adoc[Cypher runtime] to no | Ensures that no relationship property uniqueness constraints are violated. | | -| label:new[Introduced in 5.8] +| | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-asserting-multi-node-index-seek[AssertingMultiNodeIndexSeek] | Used to ensure that no property uniqueness constraints are violated. @@ -274,7 +274,7 @@ Yields rows from the left-hand operator and discards rows from the right-hand op | Fetches all nodes that have all of the provided labels from the node label index. | label:yes[] | -| label:new[Introduced in 5.5] +| | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-let-anti-semi-apply[LetAntiSemiApply] a| @@ -342,7 +342,7 @@ Tests for the presence of a pattern predicate in queries containing multiple pat | Reads one or more nodes by id from the node store, specified via the function xref::functions/scalar.adoc#functions-elementid[elementId()]. | label:yes[] | -| label:new[Introduced in 5.3] +| | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-node-by-id-seek[NodeByIdSeek] | Reads one or more nodes by id from the node store, specified via the function xref::functions/scalar.adoc#functions-id[id()]. @@ -427,7 +427,7 @@ Tests for the presence of a pattern predicate in queries containing multiple pat It is only planned directly after `Repeat(Trail)`. | | -| label:new[Introduced in 5.9] +| | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-optional[Optional] | Yields a single row with all columns set to `null` if no data is returned by its source. @@ -476,13 +476,13 @@ It is not eager. | Used by the parallel runtime to read all nodes from the node store. | label:yes[] | -| label:new[Introduced in 5.17] +| | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-partitioned-directed-all-relationships-scan[PartitionedDirectedAllRelationshipsScan] | Used by the parallel runtime to fetch all relationships and their start and end nodes from the database. | label:yes[] | -| label:new[Introduced in 5.17] +| | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-partitioned-directed-relationship-index-scan[PartitionedDirectedRelationshipIndexScan] @@ -490,70 +490,70 @@ It is not eager. It returns all relationships with a particular type and a specified property, along with their start and end nodes. | label:yes[] | -| label:new[Introduced in 5.17] +| | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-partitioned-directed-relationship-index-seek[PartitionedDirectedRelationshipIndexSeek] | Finds relationships and their start and end nodes using a parallel index seek. | label:yes[] | -| label:new[Introduced in 5.17] +| | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-partitioned-directed-relationship-index-seek-by-range[PartitionedDirectedRelationshipIndexSeekByRange] | Finds relationships using a parallel index seek where the value of the of the specified relationship type property is within a given range. It also finds the start and end nodes of those relationships. | label:yes[] | -| label:new[Introduced in 5.17] +| | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-partitioned-directed-relationship-types-scan[PartitionedDirectedRelationshipTypesScan] | Fetches all relationships with a specific type from the relationship type index using a parallel scan. It also fetches the start and end nodes of those relationships. | label:yes[] | -| label:new[Introduced in 5.17] +| | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-partitioned-directed-union-relationship-types-scan[PartitionedDirectedUnionRelationshipTypesScan] | Fetches all relationships with at least one of the provided types from the relationship type index using a parallel scan. It also fetches the start and end nodes of those relationships. | | -| label:new[Introduced in 5.17] +| | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-partitioned-node-by-label-scan[PartitionedNodeByLabelScan] | Used by the parallel runtime to fetch all nodes with a specific label from the node label index. | label:yes[] | -| label:new[Introduced in 5.17] +| | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-partitioned-node-index-scan[PartitionedNodeIndexScan] | Used by the parallel runtime to examine all values stored in an index, returning all nodes with a particular label and a specified property. | label:yes[] | -| label:new[Introduced in 5.17] +| | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-partitioned-node-index-seek[PartitionedNodeIndexSeek] | Used by the parallel runtime to find nodes using an index seek. | label:yes[] | -| label:new[Introduced in 5.17] +| | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-partitioned-node-index-seek-by-range[PartitionedNodeIndexSeekByRange] | Finds nodes using a parallel index seek where the value of the specified property is within a given range. | label:yes[] | -| label:new[Introduced in 5.17] +| | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-partitioned-subtraction-node-by-labels-scan[PartitionedSubtractionNodeByLabelsScan] | Used by the parallel runtime to fetch all nodes that have all of the first set of provided labels and none of the second provided set of labels from the node label index. | label:yes[] | -| label:new[Introduced in 5.21] +| | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-partitioned-undirected-all-relationships-scan[PartitionedUndirectedAllRelationshipsScan] | Used by the parallel runtime to fetch all relationships and their start and end nodes from the database. | label:yes[] | -| label:new[Introduced in 5.17] +| | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-partitioned-undirected-relationship-index-scan[PartitionedUndirectedRelationshipIndexScan] @@ -561,46 +561,46 @@ It also fetches the start and end nodes of those relationships. It also returns the start and end nodes of those relationships. | label:yes[] | -| label:new[Introduced in 5.17] +| | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-partitioned-undirected-relationship-index-seek[PartitionedUndirectedRelationshipIndexSeek] | Finds relationships and their start and end nodes using a parallel index seek. | label:yes[] | -| label:new[Introduced in 5.17] +| | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-partitioned-undirected-relationship-index-seek-by-range[PartitionedUndirectedRelationshipIndexSeekByRange] | Finds relationships using a parallel index seek where the value of the specified relationship property type is within a given range. It also finds the start and end nodes of those relationships. | label:yes[] | -| label:new[Introduced in 5.17] +| | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-partitioned-undirected-relationship-type-scan[PartitionedUndirectedRelationshipTypeScan] | Used by the parallel runtime to fetch all relationships with a specific type from the relationship type index. It also fetches the start and end nodes of those relationships. | label:yes[] | -| label:new[Introduced in 5.17] +| | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-partitioned-undirected-union-relationship-types-scan[PartitionedUndirectedUnionRelationshipTypesScan] | Used by the parallel runtime to fetch all relationships with at least one of the provided types from the relationship type index. It also fetches the start and end nodes of those relationships. | label:yes[] | -| label:new[Introduced in 5.17] +| | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-partitioned-union-node-by-labels-scan[PartitionedUnionNodeByLabelsScan] | Used by the parallel runtime to fetch all nodes that have at least one of the provided labels from the node label index. | label:yes[] | -| label:new[Introduced in 5.17] +| | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-partitioned-unwind[PartitionedUnwind] | Used by the parallel runtime to return one row per item in a list. | | -| label:new[Introduced in 5.17] +| | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-procedure-call[ProcedureCall] | Calls a procedure. @@ -636,7 +636,7 @@ It also fetches the start and end nodes of those relationships. | Solves quantified path patterns. | | -| label:new[Introduced in 5.9] +| | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-remove-labels[RemoveLabels] | Deletes labels from a node. @@ -758,14 +758,14 @@ Tests for the absence of a pattern predicate if an expression predicate evaluate | Finds shortest paths from a previously matched node variable to an endpoint that was not previously matched. | | -| label:new[Introduced in 5.21] +| | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-stateful-shortest-path-into[StatefulShortestPath(Into)] | Finds shortest paths between two previously matched node variables. It uses a bidirectional breadth-first search (BFS) algorithm, which performs two BFS invocations at the same time, one from the left boundary node and one from the right boundary node. | | -| label:new[Introduced in 5.21] +| | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-subquery-foreach[SubqueryForeach] | Works like the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-foreach[`Foreach`]operator but it is only used for executing subqueries. @@ -777,7 +777,7 @@ It uses a bidirectional breadth-first search (BFS) algorithm, which performs two | Fetches all nodes that have all of the first set of provided labels and none of the second provided set of labels from the node label index. | label:yes[] | -| label:new[Introduced in 5.21] +| | xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-terminate-transactions[TerminateTransactions] diff --git a/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc b/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc index 4f9d332ed..0a9cccc30 100644 --- a/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc +++ b/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc @@ -125,11 +125,11 @@ Total database accesses: 36, total allocated memory: 184 ====== -[role=label--new-5.17] + [[query-plan-partitioned-all-nodes-scan]] == Partitioned All Nodes Scan // PartitionedAllNodesScan -// New in 5.17 + The `PartitionedAllNodesScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-all-nodes-scan[`AllNodesScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. It allows the store to be partitioned into different segments where each segment can be scanned independently in parallel. @@ -221,11 +221,11 @@ Total database accesses: 16, total allocated memory: 184 ====== -[role=label--new-5.17] + [[query-plan-partitioned-directed-relationship-index-scan]] == Partitioned Directed Relationship Index Scan // PartitionedDirectedRelationshipIndexScan -// New in 5.17 + The `PartitionedDirectedRelationshipIndexScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-directed-relationship-index-scan[`DirectedRelationshipIndexScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. @@ -310,11 +310,11 @@ Total database accesses: 16, total allocated memory: 184 ====== -[role=label--new-5.17] + [[query-plan-partitioned-undirected-relationship-index-scan]] == Partitioned Undirected Relationship Index Scan // PartitionedUndirectedRelationshipIndexScan -// New in 5.17 + The `PartitionedUndirectedRelationshipIndexScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-undirected-relationship-index-scan[`UndirectedRelationshipIndexScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. @@ -401,11 +401,11 @@ Total database accesses: 2, total allocated memory: 184 ====== -[role=label--new-5.17] + [[query-plan-partitioned-directed-relationship-index-seek]] == Partitioned Directed Relationship Index Seek // PartitionedDirectedRelationshipIndexSeek -// New in 5.17 + The `PartitionedDirectedRelationshipIndexSeek` is a variant of the the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-directed-relationship-index-seek[`DirectedRelationshipIndexSeek`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. @@ -953,11 +953,11 @@ Total database accesses: 46, total allocated memory: 184 ====== -[role=label--new-5.17] + [[query-plan-partitioned-directed-relationship-index-seek-by-range]] == Partitioned Directed Relationship Index Seek By Range // PartitionedDirectedRelationshipIndexSeekByRange -// New in 5.17 + The `PartitionedDirectedRelationshipIndexSeekByRange` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-directed-relationship-index-seek-by-range[`DirectedRelationshipIndexSeekByRange`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. @@ -1048,11 +1048,11 @@ Total database accesses: 76, total allocated memory: 184 ====== -[role=label--new-5.17] + [[query-plan-partitioned-undirected-relationship-index-seek-by-range]] == Partitioned Undirected Relationship Index Seek By Range // PartitionedUndirectedRelationshipIndexSeekByRange -// New in 5.17 + The `PartitionedUndirectedRelationshipIndexSeekByRange` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-undirected-relationship-index-seek-by-range[`UndirectedRelationshipIndexSeekByRange`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. It allows the store to be partitioned into different segments where each segment can be scanned independently in parallel. @@ -1100,7 +1100,7 @@ Total database accesses: 106 [[query-plan-union-node-by-labels-scan]] == Union Node By Labels Scan // UnionNodeByLabelsScan -// New in 5.0 + The `UnionNodeByLabelsScan` operator fetches all nodes that have at least one of the provided labels from the node label index. ====== @@ -1137,11 +1137,11 @@ Total database accesses: 13, total allocated memory: 184 ====== -[role=label--new-5.17] + [[query-plan-partitioned-union-node-by-labels-scan]] == Partitioned Union Node By Labels Scan // PartitionedUnionNodeByLabelsScan -// New in 5.17 + The `PartitionedUnionNodeByLabelsScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-union-node-by-labels-scan[`UnionNodeByLabelsScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. @@ -1181,7 +1181,7 @@ Total database accesses: 35 ====== -[role=label--new-5.5] + [[query-plan-intersection-node-by-labels-scan]] == Intersection Node By Labels Scan // IntersectionNodeByLabelsScan @@ -1222,11 +1222,11 @@ Total database accesses: 13, total allocated memory: 184 ====== -[role=label--new-5.17] + [[query-plan-partitioned-intersection-node-by-labels-scan]] == Partitioned Intersection Node By Labels Scan // PartitionedIntersectionNodeByLabelsScan -// New in 5.17 + The `PartitionedIntersectionNodeByLabelsScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-intersection-node-by-labels-scan[`IntersectionNodeByLabelsScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. @@ -1266,11 +1266,11 @@ Total database accesses: 13 ====== -[role=label--new-5.21] + [[query-plan-subtraction-node-by-labels-scan]] == Subtraction Node By Labels Scan // SubtractionNodeByLabelsScan -// New in 5.21 + The `SubtractionNodeByLabelsScan` operator fetches all nodes that have all of the first set of provided labels and none of the second provided set of labels from the node label index. In the example below, `SubtractionNodeByLabelsScan` retrieves all nodes that have the `Location` label but do not have the `Country` label. @@ -1308,11 +1308,11 @@ Total database accesses: 13, total allocated memory: 312 ====== -[role=label--new-5.21] + [[query-plan-partitioned-subtraction-node-by-labels-scan]] == Partitioned Subtraction Node By Labels Scan // PartitionedSubtractionNodeByLabelsScan -// New in 5.21 + The `PartitionedSubtractionNodeByLabelsScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-subtraction-node-by-labels-scan[`SubtractionNodeByLabelsScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. @@ -1390,10 +1390,10 @@ Total database accesses: 28, total allocated memory: 184 ---- ====== -[role=label--new-5.17] + [[query-plan-partitioned-directed-all-relationships-scan]] == Partitioned Directed All Relationships Scan -// New in 5.17 + The `PartitionedDirectedAllRelationshipsScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-directed-all-relationships-scan[`DirectedAllRelationshipsScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. It allows the store to be partitioned into different segments where each segment can be scanned independently in parallel. @@ -1468,10 +1468,10 @@ Total database accesses: 28, total allocated memory: 184 ---- ====== -[role=label--new-5.17] + [[query-plan-partitioned-undirected-all-relationships-scan]] == Partitioned Undirected All Relationships Scan -// New in 5.17 + The `PartitionedUndirectedAllRelationshipsScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-undirected-all-relationships-scan[`UndirectedAllRelationshipsScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. It allows the store to be partitioned into different segments where each segment can be scanned independently in parallel. @@ -1551,11 +1551,11 @@ Total database accesses: 13, total allocated memory: 184 ====== -[role=label--new-5.17] + [[query-plan-partitioned-directed-relationship-types-scan]] == Partitioned Directed Relationship Type Scan // PartitionedDirectedRelationshipTypeScan -// New in 5.17 + The `PartitionedDirectedRelationshipTypeScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-directed-relationship-type-scan[`DirectedRelationshipTypeScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. @@ -1637,11 +1637,11 @@ Total database accesses: 13, total allocated memory: 184 ====== -[role=label--new-5.17] + [[query-plan-partitioned-undirected-relationship-type-scan]] == Partitioned Undirected Relationship Type Scan // PartitionedUndirectedRelationshipTypeScan -// New in 5.17 + The `PartitionedUndirectedRelationshipTypeScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-undirected-relationship-type-scan[`UndirectedRelationshipTypeScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. @@ -1726,11 +1726,11 @@ Total database accesses: 14, total allocated memory: 184 ====== -[role=label--new-5.17] + [[query-plan-partitioned-directed-union-relationship-types-scan]] == Partitioned Directed Union Relationship Types Scan // PartitionedDirectedUnionRelationshipTypesScan -// New in 5.17 + The `PartitionedDirectedUnionRelationshipTypeScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-directed-union-relationship-types-scan[`DirectedUnionRelationshipTypesScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. @@ -1819,11 +1819,11 @@ Total database accesses: 14, total allocated memory: 184 ====== -[role=label--new-5.17] + [[query-plan-partitioned-undirected-union-relationship-types-scan]] == Partitioned Undirected Union Relationship Types Scan // PartitionedUndirectedUnionRelationshipTypesScan -// New in 5.17 + The `PartitionedUndirectedUnionRelationshipTypeScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-undirected-union-relationship-types-scan[`UndirectedUnionRelationshipTypesScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. @@ -1866,7 +1866,7 @@ Total database accesses: 37 ---- ====== -[role=label--new-5.3] + [[query-plan-node-by-elementid-seek]] == Node By ElementId Seek // NodeByElementIdSeek @@ -1997,11 +1997,11 @@ Total database accesses: 15, total allocated memory: 184 ====== -[role=label--new-5.17] + [[query-plan-partitioned-node-by-label-scan]] == Partitioned Node By Label Scan // PartitionedNodeByLabelScan -// New in 5.17 + The `PartitionedNodeByLabelScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-node-by-label-scan[`NodeByLabelScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. @@ -2095,11 +2095,11 @@ Total database accesses: 2, total allocated memory: 184 ====== -[role=label--new-5.17] + [[query-plan-partitioned-node-index-seek]] == Partitioned Node Index Seek // PartitionedNodeIndexSeek -// New in 5.17 + The `PartitionedNodeIndexSeek` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-node-index-seek[`NodeIndexSeek`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. @@ -2356,11 +2356,11 @@ Total database accesses: 2, total allocated memory: 184 ====== -[role=label--new-5.17] + [[query-plan-partitioned-node-index-seek-by-range]] == Partitioned Node Index Seek By Range // PartitionedNodeIndexSeekByRange -// New in 5.17 + The `PartitionedNodeIndexSeekByRange` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-node-index-seek-by-range[`NodeIndexSeekByRange`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. @@ -2590,11 +2590,11 @@ Total database accesses: 11, total allocated memory: 184 ====== -[role=label--new-5.17] + [[query-plan-partitioned-node-index-scan]] == Partitioned Node Index Scan // PartitionedNodeIndexScan -// New in 5.17 + The `PartitionedNodeIndexScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-node-index-scan[`NodeIndexScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. @@ -2812,8 +2812,7 @@ Total database accesses: 166, total allocated memory: 976 ====== [NOTE] -The below query uses a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause] (introduced in Neo4j 5.23) to import variables into the `CALL` subquery. -If you are using an older version of Neo4j, use an xref:subqueries/call-subquery.adoc#importing-with[importing `WITH` clause] instead. +The below query uses a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause] to import variables into the `CALL` subquery. .Query [source, cypher] @@ -3516,8 +3515,7 @@ This restricts the xref:planning-and-tuning/runtimes/index.adoc[Cypher runtime] ====== [NOTE] -The below query uses a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause] (introduced in Neo4j 5.23) to import variables into the `CALL` subquery. -If you are using an older version of Neo4j, use an xref:subqueries/call-subquery.adoc#importing-with[importing `WITH` clause] instead. +The below query uses a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause] to import variables into the `CALL` subquery. .Query [source, cypher] @@ -3915,7 +3913,7 @@ Total database accesses: 30, total allocated memory: 480 [[query-plan-breadth-first-varlength-expand-pruning-bfs-all]] == Breadth First VarLength Expand Pruning // VarLengthExpand(Pruning,BFS) -// New in 5.0 + Given a start node, the `VarLengthExpand(Pruning,BFS,All)` operator traverses variable-length and quantified relationships much like the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-varlength-expand-all[`VarLengthExpand(All)`] operator. However, as an optimization, it instead performs a breadth-first search (BFS) and while expanding, some paths are not explored if they are guaranteed to produce an end node that has already been found (by means of a previous path traversal). @@ -3964,7 +3962,7 @@ Batch size 128 Total database accesses: 49, total allocated memory: 1200 ---- -[role=label--new-5.9] + [[query-plan-repeat]] == Repeat (Trail) // Repeat(Trail) @@ -4026,7 +4024,7 @@ Total database accesses: 747, total allocated memory: 45832 ====== -[role=label--new-5.9] + [[query-plan-nullify-metadata]] == Nullify Metadata // NullifyMetadata @@ -4137,7 +4135,7 @@ Total database accesses: 2, total allocated memory: 64 ====== -[role=label--new-5.8] + [[query-plan-assert-same-relationship]] == Assert Same Relationship // AssertSameRelationship @@ -4804,8 +4802,7 @@ Total database accesses: 9, total allocated memory: 64 ====== [NOTE] -The below query uses a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause] (introduced in Neo4j 5.23) to import variables into the `CALL` subquery. -If you are using an older version of Neo4j, use an xref:subqueries/call-subquery.adoc#importing-with[importing `WITH` clause] instead. +The below query uses a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause] to import variables into the `CALL` subquery. .Query [source, cypher] @@ -4859,8 +4856,7 @@ Batch size 128 ====== [NOTE] -The below query uses a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause] (introduced in Neo4j 5.23) to import variables into the `CALL` subquery. -If you are using an older version of Neo4j, use an xref:subqueries/call-subquery.adoc#importing-with[importing `WITH` clause] instead. +The below query uses a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause] to import variables into the `CALL` subquery. .Query [source, cypher] @@ -5711,11 +5707,11 @@ Total database accesses: 0, total allocated memory: 184 ====== -[role=label--new-5.17] + [[query-plan-partitioned-unwind]] == Partitioned Unwind // PartitionedUnwind -// New in 5.17 + The `PartitionedUnwind` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-unwind[`Unwind`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. @@ -6005,7 +6001,7 @@ Total database accesses: 5, total allocated memory: 1488 ====== -[role=label--new-5.21] + [[query-plan-stateful-shortest-path-into]] == StatefulShortestPath(Into) // StatefulShortestPath(Into) @@ -6065,7 +6061,7 @@ Total database accesses: 43, total allocated memory: 22557 ====== -[role=label--new-5.21] + [[query-plan-stateful-shortest-path-all]] == StatefulShortestPath(All) // StatefulShortestPath(All) diff --git a/modules/ROOT/pages/planning-and-tuning/query-tuning.adoc b/modules/ROOT/pages/planning-and-tuning/query-tuning.adoc index b8ba76a7e..9c7130e0c 100644 --- a/modules/ROOT/pages/planning-and-tuning/query-tuning.adoc +++ b/modules/ROOT/pages/planning-and-tuning/query-tuning.adoc @@ -303,7 +303,7 @@ CYPHER replan=force EXPLAIN MATCH ... During times of known high load, `replan=skip` can be useful to not introduce unwanted latency spikes. -[role=label--new-5.21] + [[cypher-infer-schema-parts]] === Cypher infer schema parts diff --git a/modules/ROOT/pages/planning-and-tuning/runtimes/concepts.adoc b/modules/ROOT/pages/planning-and-tuning/runtimes/concepts.adoc index 060c5646f..456de836f 100644 --- a/modules/ROOT/pages/planning-and-tuning/runtimes/concepts.adoc +++ b/modules/ROOT/pages/planning-and-tuning/runtimes/concepts.adoc @@ -234,7 +234,7 @@ Unlike interpreted runtimes, compiled runtimes have a code generation phase foll As stated xref::planning-and-tuning/runtimes/concepts.adoc#runtimes-slotted-runtime-considerations[above], there are rare scenarios in which users of Neo4j Enterprise Edition may benefit from not using the pipelined runtime for their queries. However, for most queries, the pipelined runtime is a more efficient runtime capable of handling all operators and queries. -[role=label--enterprise-edition label--new-5.13] +[role=label--enterprise-edition label] [[runtimes-parallel-runtime]] == Parallel runtime diff --git a/modules/ROOT/pages/planning-and-tuning/runtimes/reference.adoc b/modules/ROOT/pages/planning-and-tuning/runtimes/reference.adoc index 24d12435b..43f43f0f2 100644 --- a/modules/ROOT/pages/planning-and-tuning/runtimes/reference.adoc +++ b/modules/ROOT/pages/planning-and-tuning/runtimes/reference.adoc @@ -1,6 +1,6 @@ :description: reference material for the parallel runtime. = Parallel runtime: reference -:page-role: enterprise-edition new-5.13 +:page-role: enterprise-edition The parallel runtime behaves differently compared to the slotted and pipelined runtimes in several regards. This page explains the relevant configuration settings for the parallel runtime and the scenarios in which it is either not supported or considered thread-safe. diff --git a/modules/ROOT/pages/queries/basic.adoc b/modules/ROOT/pages/queries/basic.adoc index 530e50616..f9e9f1933 100644 --- a/modules/ROOT/pages/queries/basic.adoc +++ b/modules/ROOT/pages/queries/basic.adoc @@ -795,7 +795,7 @@ LIMIT 5 |=== [NOTE] -The quantifier used in the above two examples was introduced with the release of xref::patterns/variable-length-patterns.adoc#quantified-path-patterns[quantified path patterns] in Neo4j 5.9. +The quantifier used in the above two examples was introduced with the release of xref::patterns/variable-length-patterns.adoc#quantified-path-patterns[quantified path patterns]. Before that, the only way in Cypher to match paths of a variable length was with a variable-length relationship. This syntax is still available in Cypher, but it is not xref:appendix/gql-conformance/index.adoc[GQL conformant]. For more information, see xref::patterns/reference.adoc#variable-length-relationships[Patterns -> Syntax and semantics -> Variable length relationships]. @@ -827,7 +827,7 @@ The results show that 2 different paths are tied for the shortest length. |=== [NOTE] -The `SHORTEST` keyword was introduced in Neo4j 5.21, and functionally replaces and extendes the `shortestPath()` and `allShortestPaths()` functions. +The `SHORTEST` keyword functionally replaces and extendes the `shortestPath()` and `allShortestPaths()` functions. Both functions can still be used, but they are not xref:appendix/gql-conformance/index.adoc[GQL conformant]. For more information, see xref:patterns/reference.adoc#shortest-functions[Patterns -> Syntax and semantics -> The `shortestPath()` and `allShortestPaths()` functions]. diff --git a/modules/ROOT/pages/queries/case.adoc b/modules/ROOT/pages/queries/case.adoc index 1dae13b99..be2a3420d 100644 --- a/modules/ROOT/pages/queries/case.adoc +++ b/modules/ROOT/pages/queries/case.adoc @@ -97,7 +97,7 @@ END AS result, n.eyes 2+d|Rows: 5 |=== -[role=label--new-5.18] + [[case-extended-simple]] == Extended Simple `CASE` diff --git a/modules/ROOT/pages/subqueries/call-subquery.adoc b/modules/ROOT/pages/subqueries/call-subquery.adoc index 44d2001c9..6f8a4905a 100644 --- a/modules/ROOT/pages/subqueries/call-subquery.adoc +++ b/modules/ROOT/pages/subqueries/call-subquery.adoc @@ -160,7 +160,7 @@ Using a `CALL` subquery can therefore reduce the amount of heap memory required Variables from the outer scope must be explicitly imported into the inner scope of the `CALL` subquery, either by using a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause] or an xref:subqueries/call-subquery.adoc#importing-with[importing `WITH` clause] (deprecated). As the subquery is evaluated for each incoming input row, the imported variables are assigned the corresponding values from that row. -[role=label--new-5.23] + [[variable-scope-clause]] === The variable scope clause @@ -422,7 +422,7 @@ RETURN largeLists ==== -[role=label--new-5.24] + [[optional-call]] == Optional subquery calls diff --git a/modules/ROOT/pages/subqueries/collect.adoc b/modules/ROOT/pages/subqueries/collect.adoc index 5c65f3752..cd9825c1b 100644 --- a/modules/ROOT/pages/subqueries/collect.adoc +++ b/modules/ROOT/pages/subqueries/collect.adoc @@ -1,6 +1,5 @@ = COLLECT subqueries :description: This page describes how to use the COLLECT subquery with Cypher. -:page-role: new-5.6 A `COLLECT` subquery expression can be used to create a list with the rows returned by a given subquery. diff --git a/modules/ROOT/pages/subqueries/count.adoc b/modules/ROOT/pages/subqueries/count.adoc index 44d9f0aa5..18ef3fe6a 100644 --- a/modules/ROOT/pages/subqueries/count.adoc +++ b/modules/ROOT/pages/subqueries/count.adoc @@ -71,7 +71,7 @@ RETURN person.name AS name 1+d|Rows: 1 |=== -[role=label--new-5.3] + [[count-union]] == `COUNT` subquery with a `UNION` @@ -102,7 +102,7 @@ RETURN 2+d|Rows: 3 |=== -[role=label--new-5.3] + [[count-with]] == `COUNT` subquery with `WITH` @@ -249,7 +249,7 @@ RETURN COUNT { (person)-[:HAS_DOG]->(:Dog) } AS numDogs, 2+d|Rows: 3 |=== -[role=label--new-5.3] + [[count-return]] === `COUNT` subquery with `RETURN` diff --git a/modules/ROOT/pages/subqueries/existential.adoc b/modules/ROOT/pages/subqueries/existential.adoc index 99a8cca9c..e2b3399c1 100644 --- a/modules/ROOT/pages/subqueries/existential.adoc +++ b/modules/ROOT/pages/subqueries/existential.adoc @@ -126,7 +126,7 @@ RETURN person.name AS name, EXISTS { 2+d|Rows: 3 |=== -[role=label--new-5.3] + [[existential-union]] == `EXISTS` subquery with a `UNION` @@ -155,7 +155,7 @@ RETURN 2+d|Rows: 3 |=== -[role=label--new-5.3] + [[existential-with]] == `EXISTS` subquery with `WITH` @@ -204,7 +204,7 @@ RETURN person.name AS name 1+d|Rows: 1 |=== -[role=label--new-5.3] + [[existential-return]] == `EXISTS` subquery with `RETURN` diff --git a/modules/ROOT/pages/subqueries/index.adoc b/modules/ROOT/pages/subqueries/index.adoc index 56ae5ccb1..7bc8adac5 100644 --- a/modules/ROOT/pages/subqueries/index.adoc +++ b/modules/ROOT/pages/subqueries/index.adoc @@ -9,4 +9,4 @@ For more information, see the following sections: * xref:subqueries/subqueries-in-transactions.adoc[] * xref:subqueries/existential.adoc[] * xref:subqueries/count.adoc[] -* xref:subqueries/collect.adoc[] label:new[Introduced in 5.6] +* xref:subqueries/collect.adoc[] diff --git a/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc b/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc index c72457853..1a6664bb5 100644 --- a/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc +++ b/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc @@ -16,8 +16,7 @@ Cancelling the outer transaction will cancel the inner ones as well. If you are using link:https://neo4j.com/docs/browser-manual/current/[Neo4j Browser], you must prepend any queries using `CALL { ... } IN TRANSACTIONS` with `:auto`. [NOTE] -The examples on this page use a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause] (introduced in Neo4j 5.23) to import variables into the `CALL` subquery. -If you are using an older version of Neo4j, use an xref:subqueries/call-subquery.adoc#importing-with[importing `WITH` clause] instead. +The examples on this page use a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause] to import variables into the `CALL` subquery. == Syntax @@ -212,11 +211,11 @@ The batch size of `2 ROWS` is an example given the small data set used here. For larger data sets, you might want to use larger batch sizes, such as `10000 ROWS`. ==== -[role=label--new-5.18] + [[composite-databases]] == Composite databases -As of Neo4j 5.18, `CALL { ... } IN TRANSACTIONS` can be used with link:{neo4j-docs-base-uri}/operations-manual/{page-version}/composite-databases[composite databases]. +`CALL { ... } IN TRANSACTIONS` can be used with link:{neo4j-docs-base-uri}/operations-manual/{page-version}/composite-databases[composite databases]. Even though composite databases allow accessing multiple graphs in a single query, only one graph can be modified in a single transaction. `CALL { ... } IN TRANSACTIONS` offers a way of constructing queries which modify multiple graphs. @@ -310,7 +309,7 @@ CALL (g) { ---- ==== -[role=label--new-5.7] + [[error-behavior]] == Error behavior @@ -590,7 +589,7 @@ RETURN n.num, s.errorMessage; REPORT STATUS can only be used when specifying ON ERROR CONTINUE or ON ERROR BREAK ---- -[role=label--new-5.21] + [[concurrent-transactions]] == Concurrent transactions diff --git a/modules/ROOT/pages/syntax/operators.adoc b/modules/ROOT/pages/syntax/operators.adoc index b6ce384ab..e1b523052 100644 --- a/modules/ROOT/pages/syntax/operators.adoc +++ b/modules/ROOT/pages/syntax/operators.adoc @@ -563,7 +563,7 @@ RETURN 'neo' + '4j' AS result 1+d|Rows: 1 |=== -[role=label--new-5.19] + [[syntax-concatenating-two-strings-doublebar]] === Concatenating two `STRING` values with `||` @@ -582,7 +582,7 @@ RETURN 'neo' || '4j' AS result 1+d|Rows: 1 |=== -[role=label--new-5.17] + [[match-string-is-normalized]] === Checking if a `STRING` `IS NORMALIZED` @@ -615,7 +615,7 @@ To normalize a `STRING`, use the xref:functions/string.adoc#functions-normalize[ Note that the `IS NORMALIZED` operator returns `null` when used on a non-`STRING` value. For example, `RETURN 1 IS NORMALIZED` returns `null`. -[role=label--new-5.17] + [[match-string-is-not-normalized]] === Checking if a `STRING` `IS NOT NORMALIZED` @@ -933,7 +933,7 @@ RETURN [1,2,3,4,5] + [6,7] AS myList 1+d|Rows: 1 |=== -[role=label--new-5.19] + [[syntax-concatenating-two-lists-with-doublebar]] === Concatenating two lists using `||` diff --git a/modules/ROOT/pages/values-and-types/property-structural-constructed.adoc b/modules/ROOT/pages/values-and-types/property-structural-constructed.adoc index a08608f9e..10756b55d 100644 --- a/modules/ROOT/pages/values-and-types/property-structural-constructed.adoc +++ b/modules/ROOT/pages/values-and-types/property-structural-constructed.adoc @@ -106,7 +106,7 @@ However, not all types can be used in all places. |=== All Cypher types contain the `null` value. To make them not nullable, `NOT NULL` can be appended to the end of the type (e.g. `BOOLEAN NOT NULL`, `LIST`). -A shorthand syntax equivalent, introduced in Neo4j 5.14, for `NOT NULL` is to use an exclamation mark `!` (e.g. `INTEGER!`, `LIST`). +A shorthand syntax equivalent for `NOT NULL` is to use an exclamation mark `!` (e.g. `INTEGER!`, `LIST`). Note that closed dynamic types (`INNER_TYPE_1 | INNER_TYPE_2...`) cannot be appended with `NOT NULL`: all inner types must be nullable, or all appended with `NOT NULL`. [[type-normalization]] diff --git a/modules/ROOT/pages/values-and-types/spatial.adoc b/modules/ROOT/pages/values-and-types/spatial.adoc index dce319fb1..f1b89a2e0 100644 --- a/modules/ROOT/pages/values-and-types/spatial.adoc +++ b/modules/ROOT/pages/values-and-types/spatial.adoc @@ -251,7 +251,6 @@ RETURN [[spatial-values-point-index]] == Spatial values and indexes -// POINT INDEX new in Neo4j 5.0 If there is a range or point index on a particular node or relationship property, and a spatial point is assigned to that property on a node or relationship, the node or relationship will be indexed. diff --git a/modules/ROOT/pages/values-and-types/temporal.adoc b/modules/ROOT/pages/values-and-types/temporal.adoc index bba317da5..1c514ccad 100644 --- a/modules/ROOT/pages/values-and-types/temporal.adoc +++ b/modules/ROOT/pages/values-and-types/temporal.adoc @@ -36,19 +36,6 @@ By contrast, `DURATION` is not a temporal instant type. A `DURATION` represents a temporal amount, capturing the difference in time between two instants, and can be negative. `DURATION` captures the amount of time between two instants, it does not capture a start time and end time. -Starting from Neo4j 5.9, some temporal types have been renamed. -The table below shows the current as well as the old names of the temporal types. - -[options="header", cols="2a,2a"] -|=== -| Type | Old type name -| `DATE` | `Date` -| `LOCAL TIME` | `LocalTime` -| `ZONED TIME` | `Time` -| `LOCAL DATETIME` | `LocalDateTime` -| `ZONED DATETIME` | `DateTime` -| `DURATION` | `Duration` -|=== [[cypher-temporal-timezones]] == Time zones diff --git a/modules/ROOT/pages/values-and-types/type-predicate.adoc b/modules/ROOT/pages/values-and-types/type-predicate.adoc index 688529f2b..de79a17f5 100644 --- a/modules/ROOT/pages/values-and-types/type-predicate.adoc +++ b/modules/ROOT/pages/values-and-types/type-predicate.adoc @@ -1,6 +1,5 @@ = Type predicate expressions :description: This page describes how to use type predicate expressions with Cypher. -:page-role: new-5.9 A type predicate expression can be used to verify the type of a variable, literal, property or other Cypher expression. @@ -55,12 +54,12 @@ RETURN val, val IS NOT :: STRING AS notString 2+d|Rows: 4 |=== -[role=label--new-5.10] + [[type-predicate-null]] == Type predicate expressions for null All Cypher types includes the `null` value. -Since Neo4j 5.10, type predicate expressions can be appended with `NOT NULL`. +Type predicate expressions can be appended with `NOT NULL`. This means that `IS ::` returns `true` for all expressions evaluating to `null`, unless `NOT NULL` is appended. [source, cypher] @@ -205,7 +204,7 @@ For verifying that an expression is not of a certain type, the following alterna IS NOT TYPED ---- -[role=label--new-5.10] + [[type-predicate-any-and-nothing]] == Use of `ANY` and `NOTHING` types @@ -225,7 +224,7 @@ RETURN 42 IS :: ANY AS isOfTypeAny, 42 IS :: NOTHING AS isOfTypeNothing 2+d|Rows: 1 |=== -[role=label--new-5.11] + [[type-predicate-closed-dynamic-unions]] == Closed Dynamic Unions @@ -246,7 +245,7 @@ RETURN val, val IS :: INTEGER | FLOAT AS isNumber 2+d|Rows: 3 |=== -[role=label--new-5.10] + [[type-predicate-lists]] == List Types From 565593bc3d4bd45ad31b57c4d1de4f93a0773af8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Tue, 22 Oct 2024 11:28:14 +0200 Subject: [PATCH 13/77] Fix SHOW CONSTRAINTS table (#1075) --- modules/ROOT/pages/constraints/managing-constraints.adoc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/ROOT/pages/constraints/managing-constraints.adoc b/modules/ROOT/pages/constraints/managing-constraints.adoc index 76d08beac..3fce10b6b 100644 --- a/modules/ROOT/pages/constraints/managing-constraints.adoc +++ b/modules/ROOT/pages/constraints/managing-constraints.adoc @@ -1528,6 +1528,8 @@ SHOW CONSTRAINTS YIELD * [source, queryresult] ---- +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| id | name | type | entityType | labelsOrTypes | properties | ownedIndex | propertyType | options | createStatement | ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | 21 | "actor_fullname" | "NODE_KEY" | "NODE" | ["Actor"] | ["firstname", "surname"] | "actor_fullname" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `actor_fullname` FOR (n:`Actor`) REQUIRE (n.`firstname`, n.`surname`) IS NODE KEY" | | 10 | "author_name" | "NODE_PROPERTY_EXISTENCE" | "NODE" | ["Author"] | ["name"] | NULL | NULL | NULL | "CREATE CONSTRAINT `author_name` FOR (n:`Author`) REQUIRE (n.`name`) IS NOT NULL" | | 3 | "book_isbn" | "NODE_PROPERTY_UNIQUENESS" | "NODE" | ["Book"] | ["isbn"] | "book_isbn" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `book_isbn` FOR (n:`Book`) REQUIRE (n.`isbn`) IS UNIQUE" | From e4abb899c64626f0589ad0f3f99bc7bf82e64a1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Thu, 24 Oct 2024 10:01:13 +0200 Subject: [PATCH 14/77] Aura update for parallel runtime (#1076) --- .../pages/planning-and-tuning/runtimes/reference.adoc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/ROOT/pages/planning-and-tuning/runtimes/reference.adoc b/modules/ROOT/pages/planning-and-tuning/runtimes/reference.adoc index 43f43f0f2..0b8033ca1 100644 --- a/modules/ROOT/pages/planning-and-tuning/runtimes/reference.adoc +++ b/modules/ROOT/pages/planning-and-tuning/runtimes/reference.adoc @@ -78,11 +78,11 @@ For more information about configuration settings in Neo4j, see the link:{neo4j- [[aura]] == Aura -The parallel runtime can only be run on Aura instances with 3 or more CPUs. -This means that the parallel runtime is not available to users of AuraDB Free. -Nor is it available on instances of AuraDB Professional, AuraDB Business Critical, and AuraDB Virtual Dedicated Cloud with 2 or fewer CPUs. +The parallel runtime is available on all non-free AuraDB instances, regardless of their size or CPU count. +Additionally, when a query is run with parallel runtime on an Aura instance, it can utilize up to the total number of available CPUs. -Attempting to run a query with the parallel runtime on instances with 2 or fewer CPUs will generate the following error message: +The parallel runtime is disabled on AuraDB Free instances. +Attempting to run a query with parallel runtime on AuraDB Free will throw the following error message: .Error message [source,error] @@ -92,7 +92,7 @@ Parallel runtime has been disabled, please enable it or upgrade to a bigger Aura [TIP] ==== -Users of AuraDB Professional, AuraDB Business Critical, and AuraDB Virtual Dedicated Cloud select the number of available CPUs when creating an instance. +Users of AuraDB Professional, AuraDB Business Critical, and AuraDB Virtual Dedicated Cloud select the the size and the number of available CPUs when creating an instance. More information about the various tiers of AuraDB can be found on the link:https://neo4j.com/pricing/[Neo4j Pricing page]. ==== From 8b08e29e9fdfa8eb066f6353a1af5b8e9d20cbac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Thu, 24 Oct 2024 11:11:09 +0200 Subject: [PATCH 15/77] Document identfier max length (#1078) --- .../pages/appendix/gql-conformance/index.adoc | 4 ++-- .../gql-conformance/supported-optional.adoc | 5 +++++ ...ions-additions-removals-compatibility.adoc | 22 ++++++++++++++++++- modules/ROOT/pages/syntax/naming.adoc | 7 ++++++ 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/modules/ROOT/pages/appendix/gql-conformance/index.adoc b/modules/ROOT/pages/appendix/gql-conformance/index.adoc index 2aafc9772..438f89042 100644 --- a/modules/ROOT/pages/appendix/gql-conformance/index.adoc +++ b/modules/ROOT/pages/appendix/gql-conformance/index.adoc @@ -1,8 +1,8 @@ :description: Overview of Cypher's conformance to GQL. = GQL conformance -*Last updated*: 13 September 2024 + -*Neo4j version*: 5.24 +*Last updated*: 24 October 2024 + +*Neo4j version*: 5.25 GQL is the new link:https://www.iso.org/home.html[ISO] International Standard query language for graph databases. diff --git a/modules/ROOT/pages/appendix/gql-conformance/supported-optional.adoc b/modules/ROOT/pages/appendix/gql-conformance/supported-optional.adoc index b71364b84..77defa1ec 100644 --- a/modules/ROOT/pages/appendix/gql-conformance/supported-optional.adoc +++ b/modules/ROOT/pages/appendix/gql-conformance/supported-optional.adoc @@ -93,6 +93,11 @@ These codes order the features in the table below. | xref:patterns/reference.adoc#graph-patterns-rules-variable-references[Graph patterns -> Rules] | +| GB01 +| Long identifiers +| xref:syntax/naming.adoc#identifier-length-limit[Naming rules and recommendations -> Identifier length limit] +| + | GF01 | Enhanced numeric functions | xref:functions/mathematical-numeric.adoc#functions-abs[`abs()`], xref:functions/mathematical-numeric.adoc#functions-floor[`floor()`], xref:functions/mathematical-logarithmic.adoc#functions-sqrt[`sqrt()`]. diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index 7b74ef3ac..5e8b66a28 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -108,6 +108,27 @@ CREATE DATABASE db OPTIONS { existingDataSeedInstance: ... } | The `CREATE DATABASE` option `existingDataSeedInstance` has been deprecated and replaced with the option link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/standard-databases/create-database/#manage-databases-create-database-options[`existingDataSeedServer`]. The functionality is unchanged. |=== +=== Updated features + +[cols="2", options="header"] +|=== +| Feature +| Details + +a| +label:functionality[] +label:updated[] +[source, cypher, role="noheader"] +---- +CREATE (n:Label {property: 'name'}), +()-[r:REL_TYPE]->() +---- +| Neo4j's link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-internals/store-formats/#store-format-overview[block format] now implements xref:appendix/gql-conformance/index.adoc[GQL's] limit on the maximum length of identifiers. + +The maximum limit is set to 16,383 characters in an identifier. +This means that node labels, relationship types, and property keys cannot include more than 16,383 characters. +|=== + === New features [cols="2", options="header"] @@ -125,7 +146,6 @@ CREATE DATABASE db OPTIONS { existingDataSeedServer: ... } | The option link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/standard-databases/create-database/#manage-databases-create-database-options[`existingDataSeedServer`] has been added to `CREATE DATABASE`. The functionality is the same as the deprecated option `existingDataSeedServer`, which this replaces. |=== - [[cypher-deprecations-additions-removals-5.24]] == Neo4j 5.24 diff --git a/modules/ROOT/pages/syntax/naming.adoc b/modules/ROOT/pages/syntax/naming.adoc index 91c927682..d49190034 100644 --- a/modules/ROOT/pages/syntax/naming.adoc +++ b/modules/ROOT/pages/syntax/naming.adoc @@ -71,3 +71,10 @@ Here are the recommended naming conventions: | Relationship types | Upper-case, using underscore to separate words | `:OWNS_VEHICLE` rather than `:ownsVehicle` etc. |=== +[[identifier-length-limit]] +== Length limit of identifiers + +Neo4j's link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-internals/store-formats/#store-format-overview[block format] implements xref:appendix/gql-conformance/index.adoc[GQL's] limit on the maximum length of identifiers. + +The maximum limit is set to 16,383 characters in an identifier. +This means that node labels, relationship types, and property keys cannot include more than 16,383 characters. From 0d75a0e6eb5c3e3d5488f25df091f8e4dd6f2a2f Mon Sep 17 00:00:00 2001 From: Gem Lamont <106068376+gem-neo4j@users.noreply.github.com> Date: Thu, 24 Oct 2024 13:04:05 +0200 Subject: [PATCH 16/77] =?UTF-8?q?Document=20removal=20of=20allowing=20node?= =?UTF-8?q?s=20and=20rels=20on=20RHS=20of=20SET=20properties=20=E2=80=A6?= =?UTF-8?q?=20(#1069)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …clause. --------- Co-authored-by: Jens Pryce-Åklundh <112686610+JPryce-Aklundh@users.noreply.github.com> --- ...ions-additions-removals-compatibility.adoc | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index 5e8b66a28..d627e9f8e 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -64,6 +64,26 @@ The following Unicode Characters are removed in identifiers: '\u202D', '\u202E', '\u2060', '\u2061', '\u2062', '\u2063', '\u2064', '\u2066', '\u2067', '\u2068', '\u2069', '\u206A', '\u206B', '\u206C', '\u206D', '\u206E', '\u206F', '\u2E2F', '\uFEFF', '\uFFF9', '\uFFFA', '\uFFFB' + +a| +label:functionality[] +label:removed[] +[source, cypher, role="noheader"] +---- +MATCH (n)-[r:REL]->(m) SET n = r; +MATCH (n)-[r:REL]->(m) SET n += r; +MATCH (n)-[r:REL]->(m) SET r = n; +MATCH (n)-[r:REL]->(m) SET r += n; +---- +a| +Using a `NODE` or `RELATIONSHIP` instead of a `MAP` on the RHS of a xref:clauses/set.adoc[`SET`] properties clause is no longer supported. +Instead, use the xref:functions/scalar.adoc#functions-properties[`properties()`] function to get the map of properties from nodes or relationships, which can then be used in the `SET` clause. + +[source, cypher, role="noheader"] +---- +MATCH (n)-[r:REL]->(m) SET n = properties(r) +---- + |=== From ba96a72f739cdb062d9a1c0bc0208571c8f53fb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Fri, 25 Oct 2024 14:22:45 +0200 Subject: [PATCH 17/77] Update MATCH page (#1080) --- modules/ROOT/images/graph_match_clause.svg | 2 +- modules/ROOT/pages/clauses/match.adoc | 515 ++++++++++++--------- 2 files changed, 299 insertions(+), 218 deletions(-) diff --git a/modules/ROOT/images/graph_match_clause.svg b/modules/ROOT/images/graph_match_clause.svg index 9426d8918..d2481798f 100644 --- a/modules/ROOT/images/graph_match_clause.svg +++ b/modules/ROOT/images/graph_match_clause.svg @@ -1 +1 @@ -DIRECTEDACTED_INrole:'Gordon Gekko'ACTED_INrole:'Carl Fox'ACTED_INrole:'President Andrew Shepherd'ACTED_INrole:'A.J. MacInerney'ACTED_INrole:'Bud Fox'DIRECTEDFATHER_OFPersonname:'Oliver Stone'Movietitle:'Wall Street'Personname:'Michael Douglas'Personname:'Martin Sheen'Movietitle:'The American President'Personname:'Charlie Sheen'Personname:'Rob Reiner' \ No newline at end of file +DIRECTEDACTED_INrole:'Gordon Gekko'ACTED_INrole:'Carl Fox'ACTED_INrole:'President Andrew Shepherd'ACTED_INrole:'A.J. MacInerney'ACTED_INrole:'Bud Fox'DIRECTEDPersonname:'Oliver Stone'Movietitle:'Wall Street'Personname:'Michael Douglas'Personname:'Martin Sheen'Movietitle:'The American President'Personname:'Charlie Sheen'Personname:'Rob Reiner' diff --git a/modules/ROOT/pages/clauses/match.adoc b/modules/ROOT/pages/clauses/match.adoc index a26f46c2b..f04bf857d 100644 --- a/modules/ROOT/pages/clauses/match.adoc +++ b/modules/ROOT/pages/clauses/match.adoc @@ -1,80 +1,56 @@ :description: The `MATCH` clause is used to search for the pattern described in it. include::https://raw.githubusercontent.com/neo4j-graphacademy/courses/main/asciidoc/ads/data-analysis.adoc[] -[[query-match]] = MATCH -[[match-introduction]] -== Introduction - -The `MATCH` clause allows you to specify the patterns Neo4j will search for in the database. -This is the primary way of getting data into the current set of bindings. -For more information about how `MATCH` is used to find patterns (including xref:patterns/variable-length-patterns.adoc#quantified-path-patterns[quantified path patterns], xref:patterns/variable-length-patterns.adoc#quantified-relationships[quantified relationships], and xref:patterns/shortest-paths.adoc[shortest paths]), see the section on xref::patterns/index.adoc[Patterns]. - -`MATCH` is often coupled to a `WHERE` part which adds restrictions, or predicates, to the `MATCH` patterns, making them more specific. -The predicates are part of the pattern description, and should not be considered a filter applied only after the matching is done. -_This means that `WHERE` should always be put together with the `MATCH` clause it belongs to._ - -`MATCH` can occur at the beginning of the query or later, possibly after a `WITH`. -If it is the first clause, nothing will have been bound yet, and Neo4j will design a search to find the results matching the clause and any associated predicates specified in any `WHERE` part. -This could involve a scan of the database, a search for nodes having a certain label, or a search of an index to find starting points for the pattern matching. -Nodes and relationships found by this search are available as _bound pattern elements,_ and can be used for pattern matching of paths. -They can also be used in any further `MATCH` clauses, where Neo4j will use the known elements, and from there find further unknown elements. - -Cypher is declarative, and so usually the query itself does not specify the algorithm to use to perform the search. -Neo4j will automatically work out the best approach to finding start nodes and matching patterns. -Predicates in `WHERE` parts can be evaluated before pattern matching, during pattern matching, or after finding matches. -However, there are cases where you can influence the decisions taken by the query compiler. -Read more about indexes in xref:indexes/search-performance-indexes/managing-indexes.adoc[], and more about specifying hints to force Neo4j to solve a query in a specific way in xref::indexes/search-performance-indexes/index-hints.adoc[Planner hints and the USING keyword]. - +The `MATCH` clause enables you to define specific patterns that the database will search for within its graph structure. +The `MATCH` clause can specify the nodes, relationships, and properties in a pattern, allowing for queries that traverse the graph to retrieve relevant data. [[match-example-graph]] == Example graph The following graph is used for the examples below: -image::graph_match_clause.svg[width="600",role="middle"] +image::graph_match_clause.svg[width="500",role="middle"] To recreate the graph, run the following query against an empty Neo4j database: [source, cypher, role=test-setup] ---- -CREATE - (charlie:Person {name: 'Charlie Sheen'}), - (martin:Person {name: 'Martin Sheen'}), - (michael:Person {name: 'Michael Douglas'}), - (oliver:Person {name: 'Oliver Stone'}), - (rob:Person {name: 'Rob Reiner'}), - (wallStreet:Movie {title: 'Wall Street'}), - (charlie)-[:ACTED_IN {role: 'Bud Fox'}]->(wallStreet), - (martin)-[:ACTED_IN {role: 'Carl Fox'}]->(wallStreet), - (michael)-[:ACTED_IN {role: 'Gordon Gekko'}]->(wallStreet), - (oliver)-[:DIRECTED]->(wallStreet), - (thePresident:Movie {title: 'The American President'}), - (martin)-[:ACTED_IN {role: 'A.J. MacInerney'}]->(thePresident), - (michael)-[:ACTED_IN {role: 'President Andrew Shepherd'}]->(thePresident), - (rob)-[:DIRECTED]->(thePresident), - (martin)-[:FATHER_OF]->(charlie) +CREATE (charlie:Person {name: 'Charlie Sheen'}), + (martin:Person {name: 'Martin Sheen'}), + (michael:Person {name: 'Michael Douglas'}), + (oliver:Person {name: 'Oliver Stone'}), + (rob:Person {name: 'Rob Reiner'}), + (wallStreet:Movie {title: 'Wall Street'}), + (charlie)-[:ACTED_IN {role: 'Bud Fox'}]->(wallStreet), + (martin)-[:ACTED_IN {role: 'Carl Fox'}]->(wallStreet), + (michael)-[:ACTED_IN {role: 'Gordon Gekko'}]->(wallStreet), + (oliver)-[:DIRECTED]->(wallStreet), + (thePresident:Movie {title: 'The American President'}), + (martin)-[:ACTED_IN {role: 'A.J. MacInerney'}]->(thePresident), + (michael)-[:ACTED_IN {role: 'President Andrew Shepherd'}]->(thePresident), + (rob)-[:DIRECTED]->(thePresident) ---- +[[find-nodes]] +== Find nodes -[[basic-node-finding]] -== Basic node finding +The `MATCH` clause allows you to specify node patterns of varying complexity to retrieve from a graph. +For more information about finding node patterns, see xref:patterns/fixed-length-patterns#node-patterns[Patterns -> Node patterns]. -[[get-all-nodes]] -=== Get all nodes +[[find-all-nodes]] +=== Find all nodes By specifying a pattern with a single node and no labels, all nodes in the graph will be returned. -.Query -[source, cypher, indent=0] +.Find all nodes in a graph +[source, cypher] ---- MATCH (n) RETURN n ---- -Returns all the nodes in the database. - .Result [role="queryresult",options="header,footer",cols="1* +| "Martin Sheen" | +| "Michael Douglas" | +| "Oliver Stone" | +| "Rob Reiner" | +| | "Wall Street" +| | "The American President" +2+d| Rows: 7 |=== - -[[match-with-labels]] -=== Match with labels - -To constrain a pattern with labels on nodes, add the labels to the nodes in the pattern. - -.Query -[source, cypher, indent=0] +.Node pattern using negation (`!`) label expression +[source, cypher] ---- -MATCH (:Person {name: 'Oliver Stone'})--(movie:Movie) -RETURN movie.title +MATCH (n:!Movie) +RETURN labels(n) AS label, count(n) AS labelCount ---- -Returns any nodes with the `Movie` label connected to `Oliver Stone`. +[NOTE] +The above query uses the xref:functions/list.adoc#functions-labels[`labels()`] and xref:functions/aggregating.adoc#functions-count[`count()`] functions. .Result -[role="queryresult",options="header,footer",cols="1* Label expressions]. + +[[find-relationships]] +== Find relationships -[[label-expression-match-or-expression]] -=== Match with a label expression for the node labels +The `MATCH` clause allows you to specify relationship patterns of varying complexity to retrieve from a graph. +Unlike a node pattern, a relationship pattern cannot be used in a `MATCH` clause without node patterns at both ends. +For more information about relationship patterns, see xref:patterns/fixed-length-patterns#relationship patterns[Patterns -> Relationship patterns]. -A match with an `OR` expression for the node label returns the nodes that contains both the specified labels. +[NOTE] +Relationships will only be matched once inside a single pattern. +Read more about this behavior in the section on xref::patterns/reference.adoc#graph-patterns-rules-relationship-uniqueness[relationship uniqueness]. -.Query +[[empty-relationship-patterns]] +=== Empty relationship patterns + +By applying `--`, a pattern will be matched for a relationship with any direction and without any filtering on relationship types or properties. + +.Find connected nodes using an empty relationship pattern [source, cypher] ---- -MATCH (n:Movie|Person) -RETURN n.name AS name, n.title AS title +MATCH (:Person {name: 'Oliver Stone'})--(n) +RETURN n AS connectedNodes ---- .Result -[role="queryresult",options="header,footer",cols="2* -| "Martin Sheen" | -| "Michael Douglas" | -| "Oliver Stone" | -| "Rob Reiner" | -| | "Wall Street" -| | "The American President" -2+|Rows: 7 -|=== - +| connectedNodes +| (:Movie {title: "Wall Street"}) -[[relationship-basics]] -== Relationship basics +1+d| Rows: 1 +|=== -[[outgoing-relationships]] -=== Outgoing relationships +[[directed-relationship-patterns]] +=== Directed relationship patterns -When the direction of a relationship is of interest, it is shown by using `-->` or `<--`. -For example: +The direction of a relationship in a pattern is indicated by arrows: `-->` or `<--`. -.Query -[source, cypher, indent=0] +.Find all nodes connected to `Oliver Stone` by an outgoing relationship. +[source, cypher] ---- -MATCH (:Person {name: 'Oliver Stone'})-->(movie) -RETURN movie.title +MATCH (:Person {name: 'Oliver Stone'})-->(movie:Movie) +RETURN movie.title AS movieTitle ---- -Returns any nodes connected by an outgoing relationship to the `Person` node with the `name` property set to `Oliver Stone`. - .Result -[role="queryresult",options="header,footer",cols="1*(movie) -RETURN type(r) +MATCH (:Person {name: 'Oliver Stone'})-[r]->() +RETURN type(r) AS relType ---- -Returns the type of each outgoing relationship from `Oliver Stone`. +[NOTE] +The above query uses the xref:functions/scalar.adoc#functions-type[`type()` function]. .Result -[role="queryresult",options="header,footer",cols="1*()` will never match a relationship. + +For a list of all relationship type expressions supported by Cypher, see xref:patterns/reference.adoc#label-expressions[Patterns -> Label expressions]. + +[[multiple-relationships]] +=== Find multiple relationships + +A graph pattern can contain several relationship patterns. + +.Graph pattern including several relationship patterns +[source, cypher] +---- +MATCH (:Person {name: 'Charlie Sheen'})-[:ACTED_IN]->(movie:Movie)<-[:DIRECTED]-(director:Person) +RETURN movie.title AS movieTitle, director.name AS director +---- + +.Result +[role="queryresult",options="header,footer",cols="2*(movie:Movie) +WHERE charlie.name = 'Charlie Sheen' +RETURN movie.title AS movieTitle +---- -Variables and specific relationship types can be included in the same pattern. -For example: +.Result +[role="queryresult",options="header,footer",cols="1*(movie:Movie) +WHERE martin.name = 'Martin Sheen' AND NOT EXISTS { + MATCH (movie)<-[:DIRECTED]-(director:Person {name: 'Oliver Stone'}) +} +RETURN movie.title AS movieTitle ---- -Returns the `ACTED_IN` roles for the movie `Wall Street`. +[NOTE] +The above query uses an xref:subqueries/existential.adoc[`EXISTS` subquery]. .Result [role="queryresult",options="header,footer",cols="1* Parameters]. -Databases occasionally contain relationship types including non-alphanumerical characters, or with spaces in them. -These are created using backticks (```). +[[find-paths]] +== Find paths -For example, the following query creates a relationship which contains a space (`OLD FRIENDS`) between `Martin Sheen` and `Rob Reiner`. +The `MATCH` clause can also be used to bind whole paths to variables. -.Query -[source, cypher, indent=0] +.Find all paths matching a pattern +[source, cypher] ---- -MATCH - (martin:Person {name: 'Martin Sheen'}), - (rob:Person {name: 'Rob Reiner'}) -CREATE (rob)-[:`OLD FRIENDS`]->(martin) +MATCH path = ()-[:ACTED_IN]->(movie:Movie) +RETURN path ---- -This leads to the following graph: +.Result +[role="queryresult",options="header,footer",cols="1*(:Movie {title: "Wall Street"}) +| (:Person {name: "Martin Sheen"})-[:ACTED_IN {role: "Carl Fox"}]->(:Movie {title: "Wall Street"}) +| (:Person {name: "Martin Sheen"})-[:ACTED_IN {role: "A.J. MacInerney"}]->(:Movie {title: "The American President"}) +| (:Person {name: "Michael Douglas"})-[:ACTED_IN {role: "Gordon Gekko"}]->(:Movie {title: "Wall Street"}) +| (:Person {name: "Michael Douglas"})-[:ACTED_IN {role: "President Andrew Shepherd"}]->(:Movie {title: "The American President"}) +1+d| Rows: 5 +|=== -image::graph_match_clause_backtick.svg[width="600", role="middle"] -.Query -[source, cypher, indent=0] +.Find paths matching a pattern including a `WHERE` predicate +[source, cypher] ---- -MATCH (n {name: 'Rob Reiner'})-[r:`OLD FRIENDS`]->() -RETURN type(r) +MATCH path = (:Person)-[:ACTED_IN]->(movie:Movie)<-[:DIRECTED]-(:Person) +WHERE movie.title = 'Wall Street' +RETURN path ---- .Result [role="queryresult",options="header,footer",cols="1*(:Movie {title: "Wall Street"})<-[:DIRECTED]-(:Person {name: "Oliver Stone"}) +| (:Person {name: "Martin Sheen"})-[:ACTED_IN {role: "Carl Fox"}]->(:Movie {title: "Wall Street"})<-[:DIRECTED]-(:Person {name: "Oliver Stone"}) +| (:Person {name: "Michael Douglas"})-[:ACTED_IN {role: "Gordon Gekko"}]->(:Movie {title: "Wall Street"})<-[:DIRECTED]-(:Person {name: "Oliver Stone"}) +1+d| Rows: 3 |=== +For more information about how `MATCH` is used to find patterns of varying complexity (including xref:patterns/variable-length-patterns.adoc#quantified-path-patterns[quantified path patterns], xref:patterns/variable-length-patterns.adoc#quantified-relationships[quantified relationships], and the xref:patterns/shortest-paths.adoc[shortest paths] between nodes), see the section on xref::patterns/index.adoc[Patterns]. -[[multiple-rels]] -=== Multiple relationships +== Multiple MATCH clauses, the WITH clause, and clause composition -Relationships can be expressed by using multiple statements in the form of `()--()`, or they can be strung together. -For example: +In Cypher, the behavior of a query is defined by its clauses. +Each clause takes the current graph state and a table of intermediate results, processes them, and passes the updated graph state and results to the next clause. +The first clause starts with the graph's initial state and an empty table, while the final clause produces the query result. -.Query -[source, cypher, indent=0] +.Chaining consecutive `MATCH` clauses +[source, cypher] ---- -MATCH (charlie {name: 'Charlie Sheen'})-[:ACTED_IN]->(movie)<-[:DIRECTED]-(director) -RETURN movie.title, director.name +MATCH (:Person {name: 'Martin Sheen'})-[:ACTED_IN]->(movie:Movie) // <1> +MATCH (director:Person)-[:DIRECTED]->(movie) // <2> +RETURN director.name AS director, movie.title AS movieTitle ---- - -Returns the movie in which `Charlie Sheen` acted and its director. +<1> The result of the first `MATCH` clause is the variable `movie` which holds all the `Movies` that `Martin Sheen` has `ACTED_IN`. +<2> The second `MATCH` clause uses the `movie` variable to find any `Person` node with a `DIRECTED` relationship to those `Movie` nodes that `Martin Sheen` has `ACTED_IN`. .Result [role="queryresult",options="header,footer",cols="2*(movies:Movie) // <1> +WITH actors, count(movies) AS movieCount // <2> +ORDER BY movieCount DESC +LIMIT 1 // <3> +MATCH (actors)-[:ACTED_IN]->(movies) // <4> +RETURN actors.name AS actor, movieCount, collect(movies.title) AS movies +---- +<1> The `Person` and `Movie` nodes matched in this step are stored in variables, which are then passed on to the second row of the query. +<2> The `movies` variable is implicitly imported by its occurrence in the `count()` function. +The `WITH` clause explicitly imports the `actors` variable. +<3> An xref:clauses/order-by.adoc[`ORDER BY`] clause orders the results by `movieCount` in descending order, ensuring that the `Person` with the highest number of movies appears at the top, and xref:clauses/limit.adoc[`LIMIT] 1` ensures that all other `Person` nodes are discarded. +<4> The second `MATCH` clause finds all `Movie` nodes associated with the `Person` nodes currently bound to the `actors` variable. + +[NOTE] +The above query uses the xref:functions/aggregating.adoc#functions-collect[`collect()` function]. + +.Result +[role="queryresult",options="header,footer",cols="3* Date: Wed, 30 Oct 2024 10:11:37 +0100 Subject: [PATCH 18/77] Small fix to MATCH (#1085) --- modules/ROOT/pages/clauses/match.adoc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/ROOT/pages/clauses/match.adoc b/modules/ROOT/pages/clauses/match.adoc index f04bf857d..35f568d88 100644 --- a/modules/ROOT/pages/clauses/match.adoc +++ b/modules/ROOT/pages/clauses/match.adoc @@ -158,14 +158,13 @@ RETURN n AS connectedNodes |=== | connectedNodes | (:Movie {title: "Wall Street"}) - 1+d| Rows: 1 |=== [[directed-relationship-patterns]] === Directed relationship patterns -The direction of a relationship in a pattern is indicated by arrows: `-->` or `<--`. +The direction of a relationship in a pattern is indicated by arrows: `+-->+` or `+<--+`. .Find all nodes connected to `Oliver Stone` by an outgoing relationship. [source, cypher] From 10c4be3ae8f0975d1c43902e6e73db649c7ebdc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Wed, 30 Oct 2024 15:28:17 +0100 Subject: [PATCH 19/77] Fix cos() table (#1087) --- modules/ROOT/pages/functions/mathematical-trigonometric.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/ROOT/pages/functions/mathematical-trigonometric.adoc b/modules/ROOT/pages/functions/mathematical-trigonometric.adoc index 9382de300..dfdbfba26 100644 --- a/modules/ROOT/pages/functions/mathematical-trigonometric.adoc +++ b/modules/ROOT/pages/functions/mathematical-trigonometric.adoc @@ -186,8 +186,8 @@ The arctangent2 of `0.5` and `0.6` is returned. .Details |=== -| *Syntax* 3+| `acos(input)` -| *Description* 3+| Returns the arccosine of a `FLOAT` in radians. +| *Syntax* 3+| `cos(input)` +| *Description* 3+| Returns the cosine of a `FLOAT` in radians. .2+| *Arguments* | *Name* | *Type* | *Description* | `input` | `FLOAT` | An angle in radians. | *Returns* 3+| `FLOAT` From 5b237a66e4ae54cf6ec623241a00c2a9457f63b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Wed, 30 Oct 2024 15:34:38 +0100 Subject: [PATCH 20/77] Remove mentions of Neo4j 6.0 (#1088) --- modules/ROOT/pages/functions/scalar.adoc | 7 +++---- modules/ROOT/pages/syntax/naming.adoc | 5 ----- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/modules/ROOT/pages/functions/scalar.adoc b/modules/ROOT/pages/functions/scalar.adoc index 977732cc0..a20c65c73 100644 --- a/modules/ROOT/pages/functions/scalar.adoc +++ b/modules/ROOT/pages/functions/scalar.adoc @@ -1206,11 +1206,10 @@ This can include the introduction of new types and subtypes of already supported If a new type is introduced, it will be returned by the `valueType()` function as soon as it is released. However, if a more precise subtype of a previously supported type is introduced, it would be considered a breaking change. +For example, the function currently returns `"FLOAT"`, but if a more specific `FLOAT` type was added, e.g. `FLOAT32`, this would be considered more specific and not be returned until the next major release of Neo4j. +As a result,`"FLOAT"` would continue to be returned for any `FLOAT32` values until the next major release. -For example, the function currently returns `"FLOAT"`, but if a more specific `FLOAT` type was added, e.g. `FLOAT32`, this would be considered more specific and not be returned until Neo4j 6.0. -As a result,`"FLOAT"` would continue to be returned for any `FLOAT32` values until the release of Neo4j 6.0. - -The below list contains all supported types displayed by the `valueType()` function: +The below list contains all currently supported types displayed by the `valueType()` function: * Predefined types ** `NOTHING` diff --git a/modules/ROOT/pages/syntax/naming.adoc b/modules/ROOT/pages/syntax/naming.adoc index d49190034..7f812d2b0 100644 --- a/modules/ROOT/pages/syntax/naming.adoc +++ b/modules/ROOT/pages/syntax/naming.adoc @@ -49,11 +49,6 @@ Some techniques to mitigate this are: ==== -[NOTE] -==== -Several special characters have been deprecated and will require escaping in Neo4j 6.0, see xref::deprecations-additions-removals-compatibility.adoc#cypher-deprecations-additions-removals-5.15[here] for the comprehensive list of deprecated characters. -==== - == Scoping and namespace rules * Node labels, relationship types and property names may re-use names. From 2ea16aa44298352ba6710112910de36563ff3cf6 Mon Sep 17 00:00:00 2001 From: Richard Sill <156673635+rsill-neo4j@users.noreply.github.com> Date: Thu, 31 Oct 2024 12:04:37 +0100 Subject: [PATCH 21/77] Include statements for functions section (#1004) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Various queries in the Cypher Quick Reference are formatted differently. I wasn't sure which way is preferable, so i did not change anything, but it's something to keep in mind during a review --------- Co-authored-by: Jens Pryce-Åklundh <112686610+JPryce-Aklundh@users.noreply.github.com> --- modules/ROOT/pages/functions/aggregating.adoc | 26 +++++++++++ modules/ROOT/pages/functions/database.adoc | 2 + modules/ROOT/pages/functions/graph.adoc | 10 +++- modules/ROOT/pages/functions/list.adoc | 24 ++++++++++ .../functions/mathematical-logarithmic.adoc | 10 ++++ .../pages/functions/mathematical-numeric.adoc | 18 ++++++++ .../functions/mathematical-trigonometric.adoc | 24 ++++++++++ modules/ROOT/pages/functions/predicate.adoc | 12 +++++ modules/ROOT/pages/functions/scalar.adoc | 46 +++++++++++++++++++ modules/ROOT/pages/functions/spatial.adoc | 12 +++++ modules/ROOT/pages/functions/string.adoc | 41 +++++++++++++++-- .../pages/functions/temporal/duration.adoc | 12 +++++ .../ROOT/pages/functions/temporal/index.adoc | 39 ++++++++++++++++ 13 files changed, 272 insertions(+), 4 deletions(-) diff --git a/modules/ROOT/pages/functions/aggregating.adoc b/modules/ROOT/pages/functions/aggregating.adoc index f6b9836ac..c4d07085b 100644 --- a/modules/ROOT/pages/functions/aggregating.adoc +++ b/modules/ROOT/pages/functions/aggregating.adoc @@ -63,11 +63,13 @@ CREATE ====== .Query +// tag::functions_aggregating_avg[] [source, cypher] ---- MATCH (p:Person) RETURN avg(p.age) ---- +// end::functions_aggregating_avg[] The average of all the values in the property `age` is returned: @@ -87,11 +89,13 @@ The average of all the values in the property `age` is returned: ====== .Query +// tag::functions_aggregating_duration_avg[] [source, cypher] ---- UNWIND [duration('P2DT3H'), duration('PT1H45S')] AS dur RETURN avg(dur) ---- +// end::functions_aggregating_duration_avg[] The average of the two supplied `DURATION` values is returned: @@ -133,11 +137,13 @@ The average of the two supplied `DURATION` values is returned: ====== .Query +// tag::functions_aggregating_collect[] [source, cypher] ---- MATCH (p:Person) RETURN collect(p.age) ---- +// end::functions_aggregating_collect[] All the values are collected and returned in a single list: @@ -189,11 +195,13 @@ The function `count(*)` can be used to return the number of nodes; for example, ====== .Query +// tag::functions_aggregating_count[] [source, cypher] ---- MATCH (p:Person {name: 'Keanu Reeves'})-->(x) RETURN labels(p), p.age, count(*) ---- +// end::functions_aggregating_count[] The labels and `age` property of the start node `Keanu Reeves` and the number of nodes related to it are returned: @@ -248,11 +256,13 @@ Instead of simply returning the number of rows with `count(*)`, the function `co ====== .Query +// tag::functions_aggregating_count_as_expression[] [source, cypher] ---- MATCH (p:Person) RETURN count(p.age) ---- +// end::functions_aggregating_count_as_expression[] The number of nodes with the label `Person` and a property `age` is returned: (To calculate the sum, use `sum(n.age)`) @@ -389,11 +399,13 @@ The highest of all the lists in the set -- in this case, the list `[1, 2]` -- is ====== .Query +// tag::functions_aggregating_max[] [source, cypher] ---- MATCH (p:Person) RETURN max(p.age) ---- +// end::functions_aggregating_max[] The highest of all the values in the property `age` is returned: @@ -486,11 +498,13 @@ The lowest of all the values in the set -- in this case, the list `['a', 'c', 23 ====== .Query +// tag::functions_aggregating_min[] [source, cypher] ---- MATCH (p:Person) RETURN min(p.age) ---- +// end::functions_aggregating_min[] The lowest of all the values in the property `age` is returned: @@ -532,11 +546,13 @@ The lowest of all the values in the property `age` is returned: ====== .Query +// tag::functions_aggregating_percentile_cont[] [source, cypher] ---- MATCH (p:Person) RETURN percentileCont(p.age, 0.4) ---- +// end::functions_aggregating_percentile_cont[] The 40th percentile of the values in the property `age` is returned, calculated with a weighted average: @@ -579,11 +595,13 @@ The 40th percentile of the values in the property `age` is returned, calculated ====== .Query +// tag::functions_aggregating_percentile_disc[] [source, cypher] ---- MATCH (p:Person) RETURN percentileDisc(p.age, 0.5) ---- +// end::functions_aggregating_percentile_disc[] The 50th percentile of the values in the property `age` is returned: @@ -625,12 +643,14 @@ The 50th percentile of the values in the property `age` is returned: ====== .Query +// tag::functions_aggregating_stdev[] [source, cypher] ---- MATCH (p:Person) WHERE p.name IN ['Keanu Reeves', 'Liam Neeson', 'Carrie Anne Moss'] RETURN stDev(p.age) ---- +// end::functions_aggregating_stdev[] The standard deviation of the values in the property `age` is returned: @@ -672,12 +692,14 @@ The standard deviation of the values in the property `age` is returned: ====== .Query +// tag::functions_aggregating_stdevp[] [source, cypher] ---- MATCH (p:Person) WHERE p.name IN ['Keanu Reeves', 'Liam Neeson', 'Carrie Anne Moss'] RETURN stDevP(p.age) ---- +// end::functions_aggregating_stdevp[] The population standard deviation of the values in the property `age` is returned: @@ -719,11 +741,13 @@ The population standard deviation of the values in the property `age` is returne ====== .Query +// tag::functions_aggregating_sum[] [source, cypher] ---- MATCH (p:Person) RETURN sum(p.age) ---- +// end::functions_aggregating_sum[] The sum of all the values in the property `age` is returned: @@ -744,11 +768,13 @@ The sum of all the values in the property `age` is returned: ====== .Query +// tag::functions_aggregating_sum_duration[] [source, cypher] ---- UNWIND [duration('P2DT3H'), duration('PT1H45S')] AS dur RETURN sum(dur) ---- +// end::functions_aggregating_sum_duration[] The sum of the two supplied durations is returned: diff --git a/modules/ROOT/pages/functions/database.adoc b/modules/ROOT/pages/functions/database.adoc index 8ba36ae72..32a191747 100644 --- a/modules/ROOT/pages/functions/database.adoc +++ b/modules/ROOT/pages/functions/database.adoc @@ -25,11 +25,13 @@ ====== .Query +// tag::functions_database_name_from_element_id[] [source, cypher, indent=0] ---- WITH "2:efc7577d-022a-107c-a736-dbcdfc189c03:0" AS eid RETURN db.nameFromElementId(eid) AS name ---- +// end::functions_database_name_from_element_id[] Returns the name of the database which the element id belongs to. diff --git a/modules/ROOT/pages/functions/graph.adoc b/modules/ROOT/pages/functions/graph.adoc index 174910a8d..3d7b7028d 100644 --- a/modules/ROOT/pages/functions/graph.adoc +++ b/modules/ROOT/pages/functions/graph.adoc @@ -34,10 +34,12 @@ CREATE ALIAS composite.third FOR DATABASE dbc; ---- .Query +// tag::functions_graph_names[] [source, cypher, indent=0] ---- RETURN graph.names() AS name ---- +// end::functions_graph_names[] The names of all graphs on the current composite database are returned. @@ -91,11 +93,13 @@ CREATE ALIAS composite.third FOR DATABASE dbc ---- .Query +// tag::functions_graph_properties_by_name[] [source, cypher, indent=0] ---- UNWIND graph.names() AS name RETURN name, graph.propertiesByName(name) AS props ---- +// end::functions_graph_properties_by_name[] Properties for all graphs on the current composite database are returned. @@ -150,7 +154,8 @@ For more information, see xref:subqueries/call-subquery.adoc#import-variables[CA ====== .Query -[source, cypher, indent=0] +// tag::functions_graph_by_name[] +[source, cypher, role=noplay] ---- UNWIND graph.names() AS graphName CALL () { @@ -160,6 +165,7 @@ CALL () { } RETURN n ---- +// end::functions_graph_by_name[] Returns all nodes from all graphs on the current composite database. @@ -189,10 +195,12 @@ Returns all nodes from all graphs on the current composite database. In this example, it is assumed that the DBMS contains a composite database constituent, which contains the element id `4:c0a65d96-4993-4b0c-b036-e7ebd9174905:0`. .Query +// tag::functions_graph_by_element_id[] [source, cypher, role=test-skip] ---- USE graph.byElementId("4:c0a65d96-4993-4b0c-b036-e7ebd9174905:0") MATCH (n) RETURN n ---- +// end::functions_graph_by_element_id[] ====== diff --git a/modules/ROOT/pages/functions/list.adoc b/modules/ROOT/pages/functions/list.adoc index 1ff0cd547..7dc9e3fd7 100644 --- a/modules/ROOT/pages/functions/list.adoc +++ b/modules/ROOT/pages/functions/list.adoc @@ -56,11 +56,13 @@ CREATE ====== .Query +// tag::functions_list_keys[] [source, cypher] ---- MATCH (a) WHERE a.name = 'Alice' RETURN keys(a) ---- +// end::functions_list_keys[] A `LIST` containing the names of all the properties on the node bound to `a` is returned. @@ -103,11 +105,13 @@ A `LIST` containing the names of all the properties on the node bound to ====== .Query +// tag::functions_list_labels[] [source, cypher] ---- MATCH (a) WHERE a.name = 'Alice' RETURN labels(a) ---- +// end::functions_list_labels[] A `LIST` containing all the labels of the node bound to `a` is returned. @@ -148,12 +152,14 @@ A `LIST` containing all the labels of the node bound to `a` is returned. ====== .Query +// tag::functions_list_nodes[] [source, cypher] ---- MATCH p = (a)-->(b)-->(c) WHERE a.name = 'Alice' AND c.name = 'Eskil' RETURN nodes(p) ---- +// end::functions_list_nodes[] A `LIST` containing all the nodes in the path `p` is returned. @@ -197,10 +203,12 @@ The only exception where the range does not contain `start` are empty ranges. ====== .Query +// tag::functions_list_range[] [source, cypher] ---- RETURN range(0, 10), range(2, 18, 3), range(0, 5, -1) ---- +// end::functions_list_range[] Three lists of numbers in the given ranges are returned. @@ -237,12 +245,14 @@ This function is analogous to the `fold` or `reduce` method in functional langua ====== .Query +// tag::functions_list_reduce[] [source, cypher] ---- MATCH p = (a)-->(b)-->(c) WHERE a.name = 'Alice' AND b.name = 'Bob' AND c.name = 'Daniel' RETURN reduce(totalAge = 0, n IN nodes(p) | totalAge + n.age) AS reduction ---- +// end::functions_list_reduce[] The `age` property of all `NODE` values in the `PATH` are summed and returned as a single value. @@ -283,12 +293,14 @@ The `age` property of all `NODE` values in the `PATH` are summed and returned as ====== .Query +// tag::functions_list_relationships[] [source, cypher] ---- MATCH p = (a)-->(b)-->(c) WHERE a.name = 'Alice' AND c.name = 'Eskil' RETURN relationships(p) ---- +// end::functions_list_relationships[] A `LIST` containing all the `RELATIONSHIP` values in the `PATH` `p` is returned. @@ -330,11 +342,13 @@ A `LIST` containing all the `RELATIONSHIP` values in the `PATH` `p ====== .Query +// tag::functions_list_reverse[] [source, cypher] ---- WITH [4923,'abc',521, null, 487] AS ids RETURN reverse(ids) ---- +// end::functions_list_reverse[] .Result [role="queryresult",options="header,footer",cols="1*` comprising all but the first element of the `likedColors` property are returned. @@ -414,12 +430,14 @@ The property named `likedColors` and a `LIST` comprising all but the first ====== .Query +// tag::functions_list_to_boolean_list[] [source, cypher, indent=0] ---- RETURN toBooleanList(null) as noList, toBooleanList([null, null]) as nullsInList, toBooleanList(['a string', true, 'false', null, ['A','B']]) as mixedList ---- +// end::functions_list_to_boolean_list[] .Result [role="queryresult",options="header,footer",cols="3*(b) @@ -69,6 +70,7 @@ WHERE AND all(x IN nodes(p) WHERE x.age < 60) RETURN p ---- +// end::functions_predicate_all[] All nodes in the returned paths will have a property `age` with a value lower than `60`: @@ -110,12 +112,14 @@ image::predicate_function_example.svg[width="300",role="middle"] ====== .Query +// tag::functions_predicate_any[] [source, cypher, indent=0] ---- MATCH (p:Person) WHERE any(nationality IN p.nationality WHERE nationality = 'American') RETURN p ---- +// end::functions_predicate_any[] The query returns the `Person` nodes with the `nationality` property value `American`: @@ -160,6 +164,7 @@ To check if a property is not `null` use the xref::syntax/operators.adoc#cypher- ====== .Query +// tag::functions_predicate_exists[] [source, cypher, indent=0] ---- MATCH (p:Person) @@ -167,6 +172,7 @@ RETURN p.name AS name, exists((p)-[:ACTED_IN]->()) AS has_acted_in_rel ---- +// end::functions_predicate_exists[] This query returns the `name` property of every `Person` node, along with a boolean (`true` or `false`) indicating if those nodes have an `ACTED_IN` relationship in the graph. @@ -209,12 +215,14 @@ For information about the `EXISTS` subquery, which is more versatile than the `e ====== .Query +// tag::functions_predicate_is_empty[] [source, cypher] ---- MATCH (p:Person) WHERE NOT isEmpty(p.nationality) RETURN p.name, p.nationality ---- +// end::functions_predicate_is_empty[] This query returns every `Person` node in the graph with a set `nationality` property value (i.e., all `Person` nodes except for `Jessica Chastain`): @@ -310,6 +318,7 @@ xref:syntax/operators.adoc#cypher-comparison[`IS NULL` or `IS NOT NULL`] should ====== .Query +// tag::functions_predicate_none[] [source, cypher, indent=0] ---- MATCH p = (n)-[*]->(b) @@ -318,6 +327,7 @@ WHERE AND none(x IN nodes(p) WHERE x.age > 60) RETURN p ---- +// end::functions_predicate_none[] No node in the returned path has an `age` property with a greater value than `60`: @@ -361,6 +371,7 @@ image::predicate_function_example.svg[width="300",role="middle"] ====== .Query +// tag::functions_predicate_single[] [source, cypher, indent=0] ---- MATCH p = (n)-->(b) @@ -369,6 +380,7 @@ WHERE AND single(x IN nodes(p) WHERE x.nationality = 'Northern Irish') RETURN p ---- +// end::functions_predicate_single[] In every returned path there is exactly one node which has the `nationality` property value `Northern Irish`: diff --git a/modules/ROOT/pages/functions/scalar.adoc b/modules/ROOT/pages/functions/scalar.adoc index a20c65c73..66774ae1c 100644 --- a/modules/ROOT/pages/functions/scalar.adoc +++ b/modules/ROOT/pages/functions/scalar.adoc @@ -57,10 +57,12 @@ This function is an alias of the xref::functions/scalar.adoc#functions-size[`siz ====== .Query +// tag::functions_scalar_char_length[] [source, cypher, indent=0] ---- RETURN char_length('Alice') ---- +// end::functions_scalar_char_length[] .Result [role="queryresult",options="header,footer",cols="1*(b)-->(c) WHERE a.name = 'Alice' RETURN length(p) ---- +// end::functions_scalar_length[] The length of the path `p` is returned. @@ -553,10 +571,12 @@ The null value is returned as the two parameters are equivalent. ====== .Query +// tag::functions_scalar_null_if[] [source, cypher, indent=0] ---- RETURN nullIf("abc", "def") ---- +// end::functions_scalar_null_if[] The first parameter, "abc", is returned, as the two parameters are not equivalent. @@ -627,11 +647,13 @@ RETURN a.name AS name, coalesce(nullIf(a.eyes, "Brown"), "Hazel") AS eyeColor ====== .Query +// tag::functions_scalar_properties[] [source, cypher, indent=0] ---- CREATE (p:Person {name: 'Stefan', city: 'Berlin'}) RETURN properties(p) ---- +// end::functions_scalar_properties[] .Result [role="queryresult",options="header,footer",cols="1*() WHERE n.name = 'Alice' RETURN type(r) ---- +// end::functions_scalar_type[] The relationship type of `r` is returned. @@ -1244,11 +1288,13 @@ See the xref::values-and-types/type-predicate.adoc[type predicate expression] fo ====== .Query +// tag::functions_scalar_value_type[] [source, cypher, indent=0] ---- UNWIND ["abc", 1, 2.0, true, [date()]] AS value RETURN valueType(value) AS result ---- +// end::functions_scalar_value_type[] .Result [role="queryresult",options="header,footer",cols="1*(o:Office) @@ -345,6 +350,7 @@ WITH point({longitude: o.longitude, latitude: o.latitude}) AS officePoint RETURN round(point.distance(trainPoint, officePoint)) AS travelDistance ---- +// end::functions_spatial_point_wgs_84_2d[] The distance between the train station in Copenhagen and the Neo4j office in Malmo is returned. @@ -415,6 +421,7 @@ If `null` is provided as one or both of the arguments, `null` is returned. ====== .Query +// tag::functions_spatial_point_wgs_84_3d[] [source, cypher] ---- WITH @@ -422,6 +429,7 @@ WITH point({x: 10, y: 10, crs: 'cartesian'}) AS upperRight RETURN point.withinBBox(point({x: 5, y: 5, crs: 'cartesian'}), lowerLeft, upperRight) AS result ---- +// end::functions_spatial_point_wgs_84_3d[] Checking if a point in _Cartesian_ CRS is contained in the bounding box. @@ -442,6 +450,7 @@ Checking if a point in _Cartesian_ CRS is contained in the bounding box. ====== .Query +// tag::functions_spatial_point_cartesian_2d[] [source, cypher] ---- WITH @@ -451,6 +460,7 @@ MATCH (t:TrainStation) WHERE point.withinBBox(point({longitude: t.longitude, latitude: t.latitude}), lowerLeft, upperRight) RETURN count(t) ---- +// end::functions_spatial_point_cartesian_2d[] Finds all train stations contained in a bounding box around Copenhagen. @@ -498,6 +508,7 @@ A bounding box that crosses the 180th meridian. ====== .Query +// tag::functions_spatial_point_cartesian_3d[] [source, cypher] ---- RETURN @@ -507,6 +518,7 @@ RETURN point({longitude: 57.0, latitude: 13.0}) ) AS in ---- +// end::functions_spatial_point_cartesian_3d[] If `null` is provided as any of the arguments, `null` is returned. diff --git a/modules/ROOT/pages/functions/string.adoc b/modules/ROOT/pages/functions/string.adoc index 3519af475..21e882134 100644 --- a/modules/ROOT/pages/functions/string.adoc +++ b/modules/ROOT/pages/functions/string.adoc @@ -48,10 +48,12 @@ See also xref::syntax/operators.adoc#query-operators-string[String operators]. ====== .Query +// tag::functions_string_btrim[] [source, cypher, indent=0] ---- RETURN btrim(' hello '), btrim('xxyyhelloxyxy', 'xy') ---- +// end::functions_string_btrim[] .Result [role="queryresult",options="header,footer",cols="2* Date: Thu, 31 Oct 2024 14:14:36 +0100 Subject: [PATCH 22/77] Cherry pick 1063 (#1092) Co-authored-by: Gem Lamont <106068376+gem-neo4j@users.noreply.github.com> --- ...ions-additions-removals-compatibility.adoc | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index d627e9f8e..4c514512d 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -20,7 +20,6 @@ Replacement syntax for deprecated and removed features are also indicated. == Neo4j 2025.01 === Removed features - [cols="2", options="header"] |=== | Feature @@ -108,6 +107,30 @@ It now returns a list of strings representing the possible Cypher Types the give For all available Cypher types, see the section on xref::values-and-types/property-structural-constructed.adoc#types-synonyms[types and their synonyms]. |=== +[[cypher-deprecations-additions-removals-5.26]] +== Neo4j 5.26 + +=== Deprecated features + +[cols="2", options="header"] +|=== +| Feature +| Details + +a| +label:functionality[] +label:deprecated[] +[source, cypher, role="noheader"] +---- +CALL db.schema.nodeTypeProperties() YIELD propertyTypes RETURN propertyTypes; +CALL db.schema.relTypeProperties() YIELD propertyTypes RETURN propertyTypes; +---- +a| +The column `propertyTypes` currently returned by the procedures link:{neo4j-docs-base-uri}/operations-manual/{page-version}/procedures/#procedure_db_schema_nodetypeproperties[`db.schema.nodeTypeProperties()`] and link:{neo4j-docs-base-uri}/operations-manual/{page-version}/procedures/#procedure_db_schema_reltypeproperties[`db.schema.relTypeProperties()`] produces a list of strings representing the potential Java types for a given property. +In an upcoming major release of Neo4j, this will be updated to represent the possible Cypher types for that property instead. +For all available Cypher types, see the section on xref::values-and-types/property-structural-constructed.adoc#types-synonyms[types and their synonyms]. +|=== + [[cypher-deprecations-additions-removals-5.25]] == Neo4j 5.25 From 5b84bf5d3f35941c1eb9a97bf25106c410c6b681 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Thu, 31 Oct 2024 14:19:13 +0100 Subject: [PATCH 23/77] Cherry pick 1070 (#1093) Co-authored-by: Hannes Sandberg --- ...ions-additions-removals-compatibility.adoc | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index 4c514512d..9bc6a074c 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -132,6 +132,25 @@ For all available Cypher types, see the section on xref::values-and-types/proper |=== +=== Updated features + +[cols="2", options="header"] +|=== +| Feature +| Details + +a| +label:functionality[] +label:updated[] +[source, cypher, role="noheader"] +---- +GRANT READ {*} ON GRAPH * FOR (n) WHERE n.createdAt > date('2024-10-25') TO regularUsers +---- +| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/property-based-access-control/[Property-based access control] now supports xref:values-and-types/spatial.adoc[spatial] and xref:values-and-types/temporal.adoc[temporal] values. + +|=== + + [[cypher-deprecations-additions-removals-5.25]] == Neo4j 5.25 From 5b1ec296d7e7efe00178e4b1a507ffb13811a530 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Thu, 31 Oct 2024 14:51:29 +0100 Subject: [PATCH 24/77] cherry pick 1082 (#1094) Co-authored-by: Lasse Heemann <7661319+l-heemann@users.noreply.github.com> --- ...precations-additions-removals-compatibility.adoc | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index 9bc6a074c..9dfec472b 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -139,6 +139,19 @@ For all available Cypher types, see the section on xref::values-and-types/proper | Feature | Details +a| +label:functionality[] +label:updated[] +[source, cypher, role="noheader"] +---- +CREATE DATABASE foo TOPOLOGY $p PRIMARIES $s SECONDARIES +---- +[source, cypher, role="noheader"] +---- +ALTER DATABASE foo SET TOPOLOGY $p PRIMARIES $s SECONDARIES +---- +| The link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/standard-databases/create-databases/[`CREATE DATABASE`] and link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/standard-databases/alter-databases/[`ALTER DATABASE`] commands now accept parameters for `TOPOLOGY` configuration. + a| label:functionality[] label:updated[] From eeb8ba4507b1067796fdaca52e82ae5f8a0a5789 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Thu, 31 Oct 2024 15:29:08 +0100 Subject: [PATCH 25/77] Fix version exact roles (#1095) --- .../ROOT/pages/appendix/tutorials/advanced-query-tuning.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/ROOT/pages/appendix/tutorials/advanced-query-tuning.adoc b/modules/ROOT/pages/appendix/tutorials/advanced-query-tuning.adoc index 115e7092c..2546d7b8a 100644 --- a/modules/ROOT/pages/appendix/tutorials/advanced-query-tuning.adoc +++ b/modules/ROOT/pages/appendix/tutorials/advanced-query-tuning.adoc @@ -15,7 +15,7 @@ Let's explain how to use these features with a more advanced query tuning exampl [NOTE] ==== -If you are upgrading an existing store to {neo4j-version-exact}, it may be necessary to drop and re-create existing indexes. +If you are upgrading an existing store, it may be necessary to drop and re-create existing indexes. For information on native index support and upgrade considerations regarding indexes, see link:{neo4j-docs-base-uri}/operations-manual/{page-version}/performance/index-configuration[Operations Manual -> Performance -> Index configuration]. ==== @@ -936,7 +936,7 @@ Predicates that will not work: [NOTE] ==== -If there is an existence constraint on the property, no predicate is required to trigger the optimization. +If there is a xref:constraints/managing-constraints.adoc#create-property-existence-constraints[property existence constraint] on the property, no predicate is required to trigger the optimization. For example, `CREATE CONSTRAINT constraint_name FOR (p:Person) REQUIRE p.name IS NOT NULL` Predicates with parameters, such as `WHERE n.prop > $param`, can trigger _index-backed ORDER BY_. From 3b8732a4f5d3e43ab7bbaa02cd2763d7930960d2 Mon Sep 17 00:00:00 2001 From: Hannes Voigt <30618026+hvub@users.noreply.github.com> Date: Tue, 5 Nov 2024 08:46:08 +0100 Subject: [PATCH 26/77] cip-190 deprecations (#1084) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Deprecation message related to - https://github.com/neo-technology/neo4j/pull/27564 - https://github.com/neo4j/docs-status-codes/pull/202 - cf. [CIP-190](https://docs.google.com/document/d/1AONjI-SpSEla-bHPJ6ghXBfF9alN5mGiOHOTEyfBtRc/edit) --------- Co-authored-by: Jens Pryce-Åklundh <112686610+JPryce-Aklundh@users.noreply.github.com> --- ...ions-additions-removals-compatibility.adoc | 76 ++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index 9dfec472b..0c4380ae1 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -117,6 +117,81 @@ For all available Cypher types, see the section on xref::values-and-types/proper | Feature | Details +a| +label:functionality[] +label:deprecated[] +[source, cypher, role="noheader"] +---- +MATCH (where {...}) +---- +---- +MATCH (...)-[where {...}]->() +---- +a| The unescaped variable named `where` (or any casing variant, like `WHERE`) used in a node or relationship pattern followed directly by a property key-value expression is deprecated. +To continue using variables with this name, use backticks to escape the variable name: + +* Node patterns: `MATCH (++`where`++ { ... })` +* Relationship patterns: `MATCH (...)-[++`where`++ { ... }]->()` + +a| +label:functionality[] +label:deprecated[] +[source, cypher, role="noheader"] +---- +... + n:A +---- +---- +... + n:A&B +---- +---- +... + n:A&B\|C +---- +a| Using an unparenthesized label expression predicate as the right-hand side operand of `+` is deprecated. +Parenthesize the label expression predicate on the right-hand side of `+`: `... + (n:A)`. + +a| +label:functionality[] +label:deprecated[] +[source, cypher, role="noheader"] +---- +CASE x ... WHEN is :: STRING THEN ... END +---- +a| Using an unescaped variable named `is` (or any casing variant, like `IS`) as a `WHEN` operand in a xref:queries/case.adoc#case-simple[simple `CASE`] expression is deprecated. +To continue using variables with this name in simple `CASE` expressions, use backticks to escape the variable name: `CASE x ... WHEN ++`is`++ :: STRING THEN ... END` + +a| +label:functionality[] +label:deprecated[] +[source, cypher, role="noheader"] +---- +CASE x ... WHEN contains + 1 THEN ... END +---- +---- +CASE x ... WHEN contains - 1 THEN ... END +---- +a| Using an unescaped variable named `contains` (or any casing variant, like `CONTAINS`) in addition or subtraction operations within a `WHEN` operand of a xref:queries/case.adoc#case-simple[simple `CASE`] expression is deprecated. +To continue using variables with this name, use backticks to escape the variable name: + +* Additions: `CASE x ... WHEN ++`contains`++ + 1 THEN ... END` +* Subtractions: `CASE x ... WHEN ++`contains`++ - 1 THEN ... END` + +a| +label:functionality[] +label:deprecated[] +[source, cypher, role="noheader"] +---- +CASE x ... WHEN in[1] THEN ... END +---- +---- +CASE x ... WHEN in["abc"] THEN ... END +---- +a| Using the `[]` operator on an unescaped variable named `in` (or any casing variant, like `IN`) within a `WHEN` operand of a xref:queries/case.adoc#case-simple[simple `CASE`] expression is deprecated. +To continue using variables with this name, use backticks to escape the variable name: + +* `CASE x ... WHEN ++`in`++[1] THEN ... END` +* `CASE x ... WHEN ++`in`++["abc"] THEN ... END` + + a| label:functionality[] label:deprecated[] @@ -160,7 +235,6 @@ label:updated[] GRANT READ {*} ON GRAPH * FOR (n) WHERE n.createdAt > date('2024-10-25') TO regularUsers ---- | link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/property-based-access-control/[Property-based access control] now supports xref:values-and-types/spatial.adoc[spatial] and xref:values-and-types/temporal.adoc[temporal] values. - |=== From 765759906aee064324ae214c41b529e57a580e7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Tue, 5 Nov 2024 09:25:44 +0100 Subject: [PATCH 27/77] Update Readme and yml files for Cypher 25 (#1057) --- .github/workflows/docs-pr-checks.yml | 1 + .github/workflows/docs-teardown.yml | 1 + README.adoc | 11 ++++++----- antora.yml | 7 +++---- preview.yml | 4 ++-- publish.yml | 15 ++++----------- 6 files changed, 17 insertions(+), 22 deletions(-) diff --git a/.github/workflows/docs-pr-checks.yml b/.github/workflows/docs-pr-checks.yml index 07965cd90..0776f03d1 100644 --- a/.github/workflows/docs-pr-checks.yml +++ b/.github/workflows/docs-pr-checks.yml @@ -5,6 +5,7 @@ on: pull_request: branches: - "dev" + - "cypher-25" - "5.x" - "4.[0-9]" - "3.5" diff --git a/.github/workflows/docs-teardown.yml b/.github/workflows/docs-teardown.yml index e2dcc782c..3434992ef 100644 --- a/.github/workflows/docs-teardown.yml +++ b/.github/workflows/docs-teardown.yml @@ -5,6 +5,7 @@ on: pull_request_target: branches: - "dev" + - "cypher-25" - "5.x" - "4.[0-9]" - "3.5" diff --git a/README.adoc b/README.adoc index 71281a24f..a3dfe1c43 100644 --- a/README.adoc +++ b/README.adoc @@ -48,7 +48,8 @@ If a change to an asciidoc file is detected, the site is automatically rebuilt. The docs-cypher repo (and all CoreDB docs repos) will contain the following branches: * `4.4` - Long term support -* `5.x` - this is the currently published version, and therefore is the branch that we publish all v5 docs from. +* `5.x` - Long term support. +* `cypher-25` - this is the currently published version, and therefore is the branch that we publish all Cypher 25 docs from. ** PRs merged into this branch will be published live immediately. * `dev` - this is always the next release - this branch will be published on the staging server, as a preview, but we will never publish from this branch publicly. ** Next means the “next version of documentation”, and may not mirror other Neo4j engineering repos. @@ -60,11 +61,11 @@ Within Github we’ll update the branch descriptions with what the current and n Here is the workflow for creating PRs in the repo, and our publication process: -* For any work on the **current** version, all work should be raised & merged against the `dev` branch, and cherry-picked back to `5.x` branch. +* For any work on the **current** version, all work should be raised & merged against the `dev` branch, and cherry-picked back to `cypher-25` branch. There are a few edge cases where we might want to work only on the current branch, for example adding a warning that is not needed in the next version - this is ok! * For content relating to the **next** release, raise PRs against the dev branch and use labels to mark the specific version it is targeting. * For work on **next+n** docs (i.e a version beyond **next**), we have 2 options: -** Open a draft PR against `dev`, with a label for the specific version it is targeting - this can be shared & reviewed in draft mode, but will not be mergeable until it is pointed at the next release. +** Open a draft PR against `dev`, with a label for the specific server version it is targeting (e.g. `2025.01` ) - this can be shared & reviewed in draft mode, but will not be mergeable until it is pointed at the next release. ** Create a feature branch from `dev`, to be merged into `dev` when appropriate. -* When a new version is ready to published, the `5.x` branch will get a git tag, named with the exact version (for example, **5.1.0**), signifying that this point-in-time marks the completion of the work for that minor release. -* Updates merged into the `dev` branch for the next release are cherry-picked into the `5.x` branch. +* When a new version is ready to published, the `cypher-25` branch will get a git tag, named with the exact version (for example, **2025.01.00**), signifying that this point-in-time marks the completion of the work for that minor release. +* Updates merged into the `dev` branch for the next release are cherry-picked into the `cypher-25` branch. diff --git a/antora.yml b/antora.yml index ef51b64c7..a09f496d9 100644 --- a/antora.yml +++ b/antora.yml @@ -1,11 +1,10 @@ name: cypher-manual title: Cypher Manual -version: '5' +version: '25' start_page: ROOT:introduction/index.adoc nav: - modules/ROOT/content-nav.adoc asciidoc: attributes: - neo4j-version: '5' - neo4j-version-minor: '5.25' - neo4j-version-exact: '5.25.0' + neo4j-version: '2025.01' + neo4j-version-minor: '2025.01.00' diff --git a/preview.yml b/preview.yml index fa119684c..21a469097 100644 --- a/preview.yml +++ b/preview.yml @@ -25,7 +25,7 @@ urls: antora: extensions: - require: "@neo4j-antora/antora-modify-sitemaps" - sitemap_version: '5' + sitemap_version: '25' sitemap_loc_version: 'current' move_sitemaps_to_components: true @@ -53,7 +53,7 @@ asciidoc: includePDF: false nonhtmloutput: "" experimental: '' - copyright: "2024 Neo4j, Inc." + copyright: "2025 Neo4j, Inc." common-license-page-uri: https://neo4j.com/docs/license/ docs-base-uri: https://neo4j.com/docs check-mark: icon:check[] diff --git a/publish.yml b/publish.yml index 49ad0451a..a44a20995 100644 --- a/publish.yml +++ b/publish.yml @@ -6,7 +6,7 @@ site: content: sources: - url: ./ - branches: ['3.5', '4.0', '4.1', '4.2', '4.3', '4.4', 'HEAD'] + branches: ['4.4', '5.x' 'HEAD'] edit_url: https://github.com/neo4j/docs-cypher/tree/{refname}/{path} exclude: - '!**/_includes/*' @@ -25,7 +25,7 @@ urls: antora: extensions: - require: "@neo4j-antora/antora-modify-sitemaps" - sitemap_version: '5' + sitemap_version: '25' sitemap_loc_version: 'current' move_sitemaps_to_components: true @@ -53,18 +53,11 @@ asciidoc: includePDF: false nonhtmloutput: "" experimental: '' - copyright: "2024 Neo4j, Inc." + copyright: "2025 Neo4j, Inc." common-license-page-uri: https://neo4j.com/docs/license/ docs-base-uri: https://neo4j.com/docs check-mark: icon:check[] cross-mark: icon:times[] neo4j-base-uri: '' neo4j-docs-base-uri: /docs - # NODES 2024 AD - page-ad-overline-link: https://neo4j.registration.goldcast.io/events/03805ea9-fe3a-4cac-8c15-aa622666531a?utm_source=neodocs&utm_medium=banner&utm_campaign=std - page-ad-image: https://neo4j.com/docs/assets/img/nodes-24.png - page-ad-title: Neo4j Online Developer Conference - page-ad-description: Join us on November 7 for live and unique tech talks over 24 hours across all timezones. - page-ad-link: https://neo4j.registration.goldcast.io/events/03805ea9-fe3a-4cac-8c15-aa622666531a?utm_source=neodocs&utm_medium=banner&utm_campaign=std - page-ad-underline-role: button - page-ad-underline: Register \ No newline at end of file + \ No newline at end of file From 30bb19f123835cc946a5d3186100e10cbc9a7a0a Mon Sep 17 00:00:00 2001 From: Therese Magnusson Date: Tue, 5 Nov 2024 09:30:02 +0100 Subject: [PATCH 28/77] Cypher 25 show commands updates (#1090) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update createStatement for key constraints * Add optional keyword `PROPERTY` for `SHOW [NODE | REL[ATIONSHIP]] [PROPERTY] UNIQUE[NESS] CONSTRAINTS` filtering * Update return type and default values for some columns for `SHOW TRANSACTIONS` --------- Co-authored-by: Jens Pryce-Åklundh <112686610+JPryce-Aklundh@users.noreply.github.com> --- .../pages/clauses/transaction-clauses.adoc | 31 +-- .../constraints/managing-constraints.adoc | 188 +++++++++--------- modules/ROOT/pages/constraints/syntax.adoc | 18 +- ...ions-additions-removals-compatibility.adoc | 27 +++ 4 files changed, 146 insertions(+), 118 deletions(-) diff --git a/modules/ROOT/pages/clauses/transaction-clauses.adoc b/modules/ROOT/pages/clauses/transaction-clauses.adoc index a6eebbdc5..333ce8b62 100644 --- a/modules/ROOT/pages/clauses/transaction-clauses.adoc +++ b/modules/ROOT/pages/clauses/transaction-clauses.adoc @@ -34,7 +34,7 @@ a| The transaction ID. label:default-output[] m| STRING m| currentQueryId -a| The ID of the query currently executing in this transaction, or an empty `STRING` if no query is currently executing. label:default-output[] +a| The ID of the query currently executing in this transaction, or `null` if no query is currently executing. label:default-output[] m| STRING m| connectionId @@ -42,7 +42,7 @@ a| The ID of the database connection attached to the transaction or an empty `ST m| STRING m| clientAddress -a| The client address of the connection issuing the transaction or an empty `STRING` if unavailable. label:default-output[] +a| The client address of the connection issuing the transaction or `null` if unavailable. label:default-output[] m| STRING m| username @@ -50,12 +50,12 @@ a| The username of the user executing the transaction. label:default-output[] m| STRING m| currentQuery -a| The query text of the query currently executing in this transaction, or an empty `STRING` if no query is currently executing. label:default-output[] +a| The query text of the query currently executing in this transaction, or `null` if no query is currently executing. label:default-output[] m| STRING m| startTime a| The time at which the transaction was started. label:default-output[] -m| STRING +m| ZONED DATETIME m| status a| The current status of the transaction (`Terminated`, `Blocked`, `Closing`, or `Running`). label:default-output[] @@ -67,7 +67,7 @@ m| DURATION m| outerTransactionId a| -The ID of this transaction's outer transaction, if such exists, otherwise an empty `STRING`. +The ID of this transaction's outer transaction, if such exists, otherwise `null`. For details, see xref:subqueries/subqueries-in-transactions.adoc[`CALL { ... } IN TRANSACTIONS`]. m| STRING @@ -76,27 +76,28 @@ a| Any metadata associated with the transaction, or an empty map if there is non m| MAP m| parameters -a| A map containing all the parameters used by the query currently executing in this transaction, or an empty map if no query is currently executing. +a| A map containing all the parameters used by the query currently executing in this transaction, or `null` if no query is currently executing. m| MAP m| planner a| -The name of the Cypher planner used to plan the query currently executing in this transaction, or an empty `STRING` if no query is currently executing. +The name of the Cypher planner used to plan the query currently executing in this transaction, or `null` if no query is currently executing. For details, see xref::planning-and-tuning/query-tuning.adoc#cypher-planner[Cypher planner]. m| STRING m| runtime -a| The name of the Cypher runtime used by the query currently executing in this transaction, or an empty `STRING` if no query is currently executing. For details, see xref::planning-and-tuning/runtimes/index.adoc[Cypher runtime]. +a| The name of the Cypher runtime used by the query currently executing in this transaction, or `null` if no query is currently executing. +For details, see xref::planning-and-tuning/runtimes/index.adoc[Cypher runtime]. m| STRING m| indexes -a| The indexes utilised by the query currently executing in this transaction, or an empty list if no query is currently executing. +a| The indexes utilised by the query currently executing in this transaction, or `null` if no query is currently executing. m| LIST m| currentQueryStartTime -a| The time at which the query currently executing in this transaction was started, or an empty `STRING` if no query is currently executing. -m| STRING +a| The time at which the query currently executing in this transaction was started, or `null` if no query is currently executing. +m| ZONED DATETIME m| protocol a| @@ -111,7 +112,7 @@ m| STRING m| currentQueryStatus -a| The current status of the query currently executing in this transaction (`parsing`, `planning`, `planned`, `running`, or `waiting`), or an empty `STRING` if no query is currently executing. +a| The current status of the query currently executing in this transaction (`parsing`, `planning`, `planned`, `running`, or `waiting`), or `null` if no query is currently executing. m| STRING m| statusDetails @@ -249,8 +250,8 @@ SHOW TRANSACTIONS |=== | database | transactionId | currentQueryId | connectionId | clientAddress | username | currentQuery | startTime | status | elapsedTime -| "neo4j" | "neo4j-transaction-6" | "query-664" | "" | "" | "" | "SHOW TRANSACTIONS" | "2022-06-14T10:02:45.568Z" | "Running" | PT0.038S -| "neo4j" | "neo4j-transaction-4" | "query-663" | "" | "" | "" | "MATCH (n) RETURN n" | "2022-06-14T10:02:45.546Z" | "Running" | PT0.06S +| "neo4j" | "neo4j-transaction-6" | "query-664" | "" | null | "" | "SHOW TRANSACTIONS" | "2022-06-14T10:02:45.568Z" | "Running" | PT0.038S +| "neo4j" | "neo4j-transaction-4" | "query-663" | "" | null | "" | "MATCH (n) RETURN n" | "2022-06-14T10:02:45.546Z" | "Running" | PT0.06S 10+d|Rows: 2 |=== @@ -325,7 +326,7 @@ SHOW TRANSACTIONS "neo4j-transaction-3" |=== | database | transactionId | currentQueryId | connectionId | clientAddress | username | currentQuery | startTime | status | elapsedTime -| "neo4j" | "neo4j-transaction-3" | "query-1" | "" | "" | "" | "MATCH (n) RETURN n" | "2021-10-20T08:29:39.423Z" | "Running" | PT2.603S +| "neo4j" | "neo4j-transaction-3" | "query-1" | "" | null | "" | "MATCH (n) RETURN n" | "2021-10-20T08:29:39.423Z" | "Running" | PT2.603S 10+d|Rows: 1 |=== diff --git a/modules/ROOT/pages/constraints/managing-constraints.adoc b/modules/ROOT/pages/constraints/managing-constraints.adoc index 3fce10b6b..c10efff61 100644 --- a/modules/ROOT/pages/constraints/managing-constraints.adoc +++ b/modules/ROOT/pages/constraints/managing-constraints.adoc @@ -886,7 +886,7 @@ CREATE CONSTRAINT book_titles FOR (book:Book) REQUIRE (book.title, book.publicat .Error message [source, error] ---- -Constraint already exists: Constraint( id=7, name='book_title_year', type='UNIQUENESS', schema=(:Book {title, publicationYear}), ownedIndex=6 ) +Constraint already exists: Constraint( id=7, name='book_title_year', type='NODE PROPERTY UNIQUENESS', schema=(:Book {title, publicationYear}), ownedIndex=6 ) ---- ====== @@ -930,19 +930,19 @@ SHOW CONSTRAINTS WHERE ownedIndex IS NOT NULL .Result [source, queryresult] ---- -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| id | name | type | entityType | labelsOrTypes | properties | ownedIndex | propertyType | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 21 | "actor_fullname" | "NODE_KEY" | "NODE" | ["Actor"] | ["firstname", "surname"] | "actor_fullname" | NULL | -| 3 | "book_isbn" | "UNIQUENESS" | "NODE" | ["Book"] | ["isbn"] | "book_isbn" | NULL | -| 7 | "book_title_year" | "UNIQUENESS" | "NODE" | ["Book"] | ["title", "publicationYear"] | "book_title_year" | NULL | -| 17 | "director_imdbId" | "NODE_KEY" | "NODE" | ["Director"] | ["imdbId"] | "director_imdbId" | NULL | -| 23 | "knows_since_how" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["KNOWS"] | ["since", "how"] | "knows_since_how" | NULL | -| 25 | "node_uniqueness_param" | "UNIQUENESS" | "NODE" | ["Book"] | ["prop1"] | "node_uniqueness_param" | NULL | -| 19 | "ownershipId" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["OWNS"] | ["ownershipId"] | "ownershipId" | NULL | -| 9 | "prequels" | "RELATIONSHIP_UNIQUENESS" | "RELATIONSHIP" | ["PREQUEL_OF"] | ["order", "author"] | "prequels" | NULL | -| 5 | "sequels" | "RELATIONSHIP_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order"] | "sequels" | NULL | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| id | name | type | entityType | labelsOrTypes | properties | ownedIndex | propertyType | ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 21 | "actor_fullname" | "NODE_KEY" | "NODE" | ["Actor"] | ["firstname", "surname"] | "actor_fullname" | NULL | +| 3 | "book_isbn" | "NODE_PROPERTY_UNIQUENESS" | "NODE" | ["Book"] | ["isbn"] | "book_isbn" | NULL | +| 7 | "book_title_year" | "NODE_PROPERTY_UNIQUENESS" | "NODE" | ["Book"] | ["title", "publicationYear"] | "book_title_year" | NULL | +| 17 | "director_imdbId" | "NODE_KEY" | "NODE" | ["Director"] | ["imdbId"] | "director_imdbId" | NULL | +| 23 | "knows_since_how" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["KNOWS"] | ["since", "how"] | "knows_since_how" | NULL | +| 25 | "node_uniqueness_param" | "NODE_PROPERTY_UNIQUENESS" | "NODE" | ["Book"] | ["prop1"] | "node_uniqueness_param" | NULL | +| 19 | "ownershipId" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["OWNS"] | ["ownershipId"] | "ownershipId" | NULL | +| 9 | "prequels" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["PREQUEL_OF"] | ["order", "author"] | "prequels" | NULL | +| 5 | "sequels" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order"] | "sequels" | NULL | ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ---- ====== @@ -1319,7 +1319,7 @@ Either use xref:indexes/search-performance-indexes/managing-indexes.adoc[indexes .Error message [source, error] ---- -Unable to create Constraint( name='book_title', type='UNIQUENESS', schema=(:Book {title}) ): +Unable to create Constraint( name='book_title', type='NODE PROPERTY UNIQUENESS', schema=(:Book {title}) ): Both Node(0) and Node(1) have the label `Book` and property `title` = 'Moby Dick' ---- @@ -1487,28 +1487,28 @@ SHOW CONSTRAINTS .Result [source, queryresult] ---- -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| id | name | type | entityType | labelsOrTypes | properties | ownedIndex | propertyType | -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 21 | "actor_fullname" | "NODE_KEY" | "NODE" | ["Actor"] | ["firstname", "surname"] | "actor_fullname" | NULL | -| 10 | "author_name" | "NODE_PROPERTY_EXISTENCE" | "NODE" | ["Author"] | ["name"] | NULL | NULL | -| 3 | "book_isbn" | "NODE_PROPERTY_UNIQUENESS" | "NODE" | ["Book"] | ["isbn"] | "book_isbn" | NULL | -| 7 | "book_title_year" | "NODE_PROPERTY_UNIQUENESS" | "NODE" | ["Book"] | ["title", "publicationYear"] | "book_title_year" | NULL | -| 28 | "constraint_with_provider" | "NODE_KEY" | "NODE" | ["Actor"] | ["surname"] | "constraint_with_provider" | NULL | -| 17 | "director_imdbId" | "NODE_KEY" | "NODE" | ["Director"] | ["imdbId"] | "director_imdbId" | NULL | -| 23 | "knows_since_how" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["KNOWS"] | ["since", "how"] | "knows_since_how" | NULL | -| 14 | "movie_tagline" | "NODE_PROPERTY_TYPE" | "NODE" | ["Movie"] | ["tagline"] | NULL | "STRING | LIST" | -| 12 | "movie_title" | "NODE_PROPERTY_TYPE" | "NODE" | ["Movie"] | ["title"] | NULL | "STRING" | -| 25 | "node_uniqueness_param" | "NODE_PROPERTY_UNIQUENESS" | "NODE" | ["Book"] | ["prop1"] | "node_uniqueness_param" | NULL | -| 19 | "ownershipId" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["OWNS"] | ["ownershipId"] | "ownershipId" | NULL | -| 13 | "part_of" | "RELATIONSHIP_PROPERTY_TYPE" | "RELATIONSHIP" | ["PART_OF"] | ["order"] | NULL | "INTEGER" | -| 15 | "part_of_tags" | "RELATIONSHIP_PROPERTY_TYPE" | "RELATIONSHIP" | ["PART_OF"] | ["tags"] | NULL | "STRING | LIST" | -| 9 | "prequels" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["PREQUEL_OF"] | ["order", "author"] | "prequels" | NULL | -| 30 | "rel_constraint_with_options" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order", "seriesTitle", "number"] | "rel_constraint_with_options" | NULL | -| 26 | "rel_exist_param" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["published"] | NULL | NULL | -| 5 | "sequels" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order"] | "sequels" | NULL | -| 11 | "wrote_year" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["year"] | NULL | NULL | -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| id | name | type | entityType | labelsOrTypes | properties | ownedIndex | propertyType | ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 21 | "actor_fullname" | "NODE_KEY" | "NODE" | ["Actor"] | ["firstname", "surname"] | "actor_fullname" | NULL | +| 10 | "author_name" | "NODE_PROPERTY_EXISTENCE" | "NODE" | ["Author"] | ["name"] | NULL | NULL | +| 3 | "book_isbn" | "NODE_PROPERTY_UNIQUENESS" | "NODE" | ["Book"] | ["isbn"] | "book_isbn" | NULL | +| 7 | "book_title_year" | "NODE_PROPERTY_UNIQUENESS" | "NODE" | ["Book"] | ["title", "publicationYear"] | "book_title_year" | NULL | +| 28 | "constraint_with_provider" | "NODE_KEY" | "NODE" | ["Actor"] | ["surname"] | "constraint_with_provider" | NULL | +| 17 | "director_imdbId" | "NODE_KEY" | "NODE" | ["Director"] | ["imdbId"] | "director_imdbId" | NULL | +| 23 | "knows_since_how" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["KNOWS"] | ["since", "how"] | "knows_since_how" | NULL | +| 14 | "movie_tagline" | "NODE_PROPERTY_TYPE" | "NODE" | ["Movie"] | ["tagline"] | NULL | "STRING | LIST" | +| 12 | "movie_title" | "NODE_PROPERTY_TYPE" | "NODE" | ["Movie"] | ["title"] | NULL | "STRING" | +| 25 | "node_uniqueness_param" | "NODE_PROPERTY_UNIQUENESS" | "NODE" | ["Book"] | ["prop1"] | "node_uniqueness_param" | NULL | +| 19 | "ownershipId" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["OWNS"] | ["ownershipId"] | "ownershipId" | NULL | +| 13 | "part_of" | "RELATIONSHIP_PROPERTY_TYPE" | "RELATIONSHIP" | ["PART_OF"] | ["order"] | NULL | "INTEGER" | +| 15 | "part_of_tags" | "RELATIONSHIP_PROPERTY_TYPE" | "RELATIONSHIP" | ["PART_OF"] | ["tags"] | NULL | "STRING | LIST" | +| 9 | "prequels" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["PREQUEL_OF"] | ["order", "author"] | "prequels" | NULL | +| 30 | "rel_constraint_with_options" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order", "seriesTitle", "number"] | "rel_constraint_with_options" | NULL | +| 26 | "rel_exist_param" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["published"] | NULL | NULL | +| 5 | "sequels" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order"] | "sequels" | NULL | +| 11 | "wrote_year" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["year"] | NULL | NULL | ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ---- ====== @@ -1527,28 +1527,28 @@ SHOW CONSTRAINTS YIELD * .Result [source, queryresult] ---- -+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| id | name | type | entityType | labelsOrTypes | properties | ownedIndex | propertyType | options | createStatement | -+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 21 | "actor_fullname" | "NODE_KEY" | "NODE" | ["Actor"] | ["firstname", "surname"] | "actor_fullname" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `actor_fullname` FOR (n:`Actor`) REQUIRE (n.`firstname`, n.`surname`) IS NODE KEY" | -| 10 | "author_name" | "NODE_PROPERTY_EXISTENCE" | "NODE" | ["Author"] | ["name"] | NULL | NULL | NULL | "CREATE CONSTRAINT `author_name` FOR (n:`Author`) REQUIRE (n.`name`) IS NOT NULL" | -| 3 | "book_isbn" | "NODE_PROPERTY_UNIQUENESS" | "NODE" | ["Book"] | ["isbn"] | "book_isbn" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `book_isbn` FOR (n:`Book`) REQUIRE (n.`isbn`) IS UNIQUE" | -| 7 | "book_title_year" | "NODE_PROPERTY_UNIQUENESS" | "NODE" | ["Book"] | ["title", "publicationYear"] | "book_title_year" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `book_title_year` FOR (n:`Book`) REQUIRE (n.`title`, n.`publicationYear`) IS UNIQUE" | -| 28 | "constraint_with_provider" | "NODE_KEY" | "NODE" | ["Actor"] | ["surname"] | "constraint_with_provider" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `constraint_with_provider` FOR (n:`Actor`) REQUIRE (n.`surname`) IS NODE KEY" | -| 17 | "director_imdbId" | "NODE_KEY" | "NODE" | ["Director"] | ["imdbId"] | "director_imdbId" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `director_imdbId` FOR (n:`Director`) REQUIRE (n.`imdbId`) IS NODE KEY" | -| 23 | "knows_since_how" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["KNOWS"] | ["since", "how"] | "knows_since_how" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `knows_since_how` FOR ()-[r:`KNOWS`]-() REQUIRE (r.`since`, r.`how`) IS RELATIONSHIP KEY" | -| 14 | "movie_tagline" | "NODE_PROPERTY_TYPE" | "NODE" | ["Movie"] | ["tagline"] | NULL | "STRING | LIST" | NULL | "CREATE CONSTRAINT `movie_tagline` FOR (n:`Movie`) REQUIRE (n.`tagline`) IS :: STRING | LIST" | -| 12 | "movie_title" | "NODE_PROPERTY_TYPE" | "NODE" | ["Movie"] | ["title"] | NULL | "STRING" | NULL | "CREATE CONSTRAINT `movie_title` FOR (n:`Movie`) REQUIRE (n.`title`) IS :: STRING" | -| 25 | "node_uniqueness_param" | "NODE_PROPERTY_UNIQUENESS" | "NODE" | ["Book"] | ["prop1"] | "node_uniqueness_param" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `node_uniqueness_param` FOR (n:`Book`) REQUIRE (n.`prop1`) IS UNIQUE" | -| 19 | "ownershipId" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["OWNS"] | ["ownershipId"] | "ownershipId" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `ownershipId` FOR ()-[r:`OWNS`]-() REQUIRE (r.`ownershipId`) IS RELATIONSHIP KEY" | -| 13 | "part_of" | "RELATIONSHIP_PROPERTY_TYPE" | "RELATIONSHIP" | ["PART_OF"] | ["order"] | NULL | "INTEGER" | NULL | "CREATE CONSTRAINT `part_of` FOR ()-[r:`PART_OF`]-() REQUIRE (r.`order`) IS :: INTEGER" | -| 15 | "part_of_tags" | "RELATIONSHIP_PROPERTY_TYPE" | "RELATIONSHIP" | ["PART_OF"] | ["tags"] | NULL | "STRING | LIST" | NULL | "CREATE CONSTRAINT `part_of_tags` FOR ()-[r:`PART_OF`]-() REQUIRE (r.`tags`) IS :: STRING | LIST" | -| 9 | "prequels" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["PREQUEL_OF"] | ["order", "author"] | "prequels" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `prequels` FOR ()-[r:`PREQUEL_OF`]-() REQUIRE (r.`order`, r.`author`) IS UNIQUE" | -| 30 | "rel_constraint_with_options" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order", "seriesTitle", "number"] | "rel_constraint_with_options" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `rel_constraint_with_options` FOR ()-[r:`SEQUEL_OF`]-() REQUIRE (r.`order`, r.`seriesTitle`, r.`number`) IS UNIQUE" | -| 26 | "rel_exist_param" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["published"] | NULL | NULL | NULL | "CREATE CONSTRAINT `rel_exist_param` FOR ()-[r:`WROTE`]-() REQUIRE (r.`published`) IS NOT NULL" | -| 5 | "sequels" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order"] | "sequels" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `sequels` FOR ()-[r:`SEQUEL_OF`]-() REQUIRE (r.`order`) IS UNIQUE" | -| 11 | "wrote_year" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["year"] | NULL | NULL | NULL | "CREATE CONSTRAINT `wrote_year` FOR ()-[r:`WROTE`]-() REQUIRE (r.`year`) IS NOT NULL" | -+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| id | name | type | entityType | labelsOrTypes | properties | ownedIndex | propertyType | options | createStatement | ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 21 | "actor_fullname" | "NODE_KEY" | "NODE" | ["Actor"] | ["firstname", "surname"] | "actor_fullname" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `actor_fullname` FOR (n:`Actor`) REQUIRE (n.`firstname`, n.`surname`) IS KEY" | +| 10 | "author_name" | "NODE_PROPERTY_EXISTENCE" | "NODE" | ["Author"] | ["name"] | NULL | NULL | NULL | "CREATE CONSTRAINT `author_name` FOR (n:`Author`) REQUIRE (n.`name`) IS NOT NULL" | +| 3 | "book_isbn" | "NODE_PROPERTY_UNIQUENESS" | "NODE" | ["Book"] | ["isbn"] | "book_isbn" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `book_isbn` FOR (n:`Book`) REQUIRE (n.`isbn`) IS UNIQUE" | +| 7 | "book_title_year" | "NODE_PROPERTY_UNIQUENESS" | "NODE" | ["Book"] | ["title", "publicationYear"] | "book_title_year" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `book_title_year` FOR (n:`Book`) REQUIRE (n.`title`, n.`publicationYear`) IS UNIQUE" | +| 28 | "constraint_with_provider" | "NODE_KEY" | "NODE" | ["Actor"] | ["surname"] | "constraint_with_provider" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `constraint_with_provider` FOR (n:`Actor`) REQUIRE (n.`surname`) IS KEY" | +| 17 | "director_imdbId" | "NODE_KEY" | "NODE" | ["Director"] | ["imdbId"] | "director_imdbId" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `director_imdbId` FOR (n:`Director`) REQUIRE (n.`imdbId`) IS KEY" | +| 23 | "knows_since_how" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["KNOWS"] | ["since", "how"] | "knows_since_how" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `knows_since_how` FOR ()-[r:`KNOWS`]-() REQUIRE (r.`since`, r.`how`) IS KEY" | +| 14 | "movie_tagline" | "NODE_PROPERTY_TYPE" | "NODE" | ["Movie"] | ["tagline"] | NULL | "STRING | LIST" | NULL | "CREATE CONSTRAINT `movie_tagline` FOR (n:`Movie`) REQUIRE (n.`tagline`) IS :: STRING | LIST" | +| 12 | "movie_title" | "NODE_PROPERTY_TYPE" | "NODE" | ["Movie"] | ["title"] | NULL | "STRING" | NULL | "CREATE CONSTRAINT `movie_title` FOR (n:`Movie`) REQUIRE (n.`title`) IS :: STRING" | +| 25 | "node_uniqueness_param" | "NODE_PROPERTY_UNIQUENESS" | "NODE" | ["Book"] | ["prop1"] | "node_uniqueness_param" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `node_uniqueness_param` FOR (n:`Book`) REQUIRE (n.`prop1`) IS UNIQUE" | +| 19 | "ownershipId" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["OWNS"] | ["ownershipId"] | "ownershipId" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `ownershipId` FOR ()-[r:`OWNS`]-() REQUIRE (r.`ownershipId`) IS KEY" | +| 13 | "part_of" | "RELATIONSHIP_PROPERTY_TYPE" | "RELATIONSHIP" | ["PART_OF"] | ["order"] | NULL | "INTEGER" | NULL | "CREATE CONSTRAINT `part_of` FOR ()-[r:`PART_OF`]-() REQUIRE (r.`order`) IS :: INTEGER" | +| 15 | "part_of_tags" | "RELATIONSHIP_PROPERTY_TYPE" | "RELATIONSHIP" | ["PART_OF"] | ["tags"] | NULL | "STRING | LIST" | NULL | "CREATE CONSTRAINT `part_of_tags` FOR ()-[r:`PART_OF`]-() REQUIRE (r.`tags`) IS :: STRING | LIST" | +| 9 | "prequels" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["PREQUEL_OF"] | ["order", "author"] | "prequels" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `prequels` FOR ()-[r:`PREQUEL_OF`]-() REQUIRE (r.`order`, r.`author`) IS UNIQUE" | +| 30 | "rel_constraint_with_options" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order", "seriesTitle", "number"] | "rel_constraint_with_options" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `rel_constraint_with_options` FOR ()-[r:`SEQUEL_OF`]-() REQUIRE (r.`order`, r.`seriesTitle`, r.`number`) IS UNIQUE" | +| 26 | "rel_exist_param" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["published"] | NULL | NULL | NULL | "CREATE CONSTRAINT `rel_exist_param` FOR ()-[r:`WROTE`]-() REQUIRE (r.`published`) IS NOT NULL" | +| 5 | "sequels" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order"] | "sequels" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `sequels` FOR ()-[r:`SEQUEL_OF`]-() REQUIRE (r.`order`) IS UNIQUE" | +| 11 | "wrote_year" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["year"] | NULL | NULL | NULL | "CREATE CONSTRAINT `wrote_year` FOR ()-[r:`WROTE`]-() REQUIRE (r.`year`) IS NOT NULL" | ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ---- ====== @@ -1599,19 +1599,19 @@ WHERE entityType = 'RELATIONSHIP' .Result [source, queryresult] ---- -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| id | name | type | entityType | labelsOrTypes | properties | ownedIndex | propertyType | -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 23 | "knows_since_how" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["KNOWS"] | ["since", "how"] | "knows_since_how" | NULL | -| 19 | "ownershipId" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["OWNS"] | ["ownershipId"] | "ownershipId" | NULL | -| 13 | "part_of" | "RELATIONSHIP_PROPERTY_TYPE" | "RELATIONSHIP" | ["PART_OF"] | ["order"] | NULL | "INTEGER" | -| 15 | "part_of_tags" | "RELATIONSHIP_PROPERTY_TYPE" | "RELATIONSHIP" | ["PART_OF"] | ["tags"] | NULL | "STRING | LIST" | -| 9 | "prequels" | "RELATIONSHIP_UNIQUENESS" | "RELATIONSHIP" | ["PREQUEL_OF"] | ["order", "author"] | "prequels" | NULL | -| 30 | "rel_constraint_with_options" | "RELATIONSHIP_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order", "seriesTitle", "number"] | "rel_constraint_with_options" | NULL | -| 26 | "rel_exist_param" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["published"] | NULL | NULL | -| 5 | "sequels" | "RELATIONSHIP_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order"] | "sequels" | NULL | -| 11 | "wrote_year" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["year"] | NULL | NULL | -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| id | name | type | entityType | labelsOrTypes | properties | ownedIndex | propertyType | ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 23 | "knows_since_how" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["KNOWS"] | ["since", "how"] | "knows_since_how" | NULL | +| 19 | "ownershipId" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["OWNS"] | ["ownershipId"] | "ownershipId" | NULL | +| 13 | "part_of" | "RELATIONSHIP_PROPERTY_TYPE" | "RELATIONSHIP" | ["PART_OF"] | ["order"] | NULL | "INTEGER" | +| 15 | "part_of_tags" | "RELATIONSHIP_PROPERTY_TYPE" | "RELATIONSHIP" | ["PART_OF"] | ["tags"] | NULL | "STRING | LIST" | +| 9 | "prequels" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["PREQUEL_OF"] | ["order", "author"] | "prequels" | NULL | +| 30 | "rel_constraint_with_options" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order", "seriesTitle", "number"] | "rel_constraint_with_options" | NULL | +| 26 | "rel_exist_param" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["published"] | NULL | NULL | +| 5 | "sequels" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order"] | "sequels" | NULL | +| 11 | "wrote_year" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["year"] | NULL | NULL | ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ---- ====== @@ -1632,28 +1632,28 @@ YIELD name, type, createStatement .Result [source, queryresult] ---- -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| name | type | createStatement | -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| "actor_fullname" | "NODE_KEY" | "CREATE CONSTRAINT `actor_fullname` FOR (n:`Actor`) REQUIRE (n.`firstname`, n.`surname`) IS NODE KEY" | -| "author_name" | "NODE_PROPERTY_EXISTENCE" | "CREATE CONSTRAINT `author_name` FOR (n:`Author`) REQUIRE (n.`name`) IS NOT NULL" | -| "book_isbn" | "UNIQUENESS" | "CREATE CONSTRAINT `book_isbn` FOR (n:`Book`) REQUIRE (n.`isbn`) IS UNIQUE" | -| "book_title_year" | "UNIQUENESS" | "CREATE CONSTRAINT `book_title_year` FOR (n:`Book`) REQUIRE (n.`title`, n.`publicationYear`) IS UNIQUE" | -| "constraint_with_provider" | "NODE_KEY" | "CREATE CONSTRAINT `constraint_with_provider` FOR (n:`Actor`) REQUIRE (n.`surname`) IS NODE KEY" | -| "director_imdbId" | "NODE_KEY" | "CREATE CONSTRAINT `director_imdbId` FOR (n:`Director`) REQUIRE (n.`imdbId`) IS NODE KEY" | -| "knows_since_how" | "RELATIONSHIP_KEY" | "CREATE CONSTRAINT `knows_since_how` FOR ()-[r:`KNOWS`]-() REQUIRE (r.`since`, r.`how`) IS RELATIONSHIP KEY" | -| "movie_tagline" | "NODE_PROPERTY_TYPE" | "CREATE CONSTRAINT `movie_tagline` FOR (n:`Movie`) REQUIRE (n.`tagline`) IS :: STRING | LIST" | -| "movie_title" | "NODE_PROPERTY_TYPE" | "CREATE CONSTRAINT `movie_title` FOR (n:`Movie`) REQUIRE (n.`title`) IS :: STRING" | -| "node_uniqueness_param" | "UNIQUENESS" | "CREATE CONSTRAINT `node_uniqueness_param` FOR (n:`Book`) REQUIRE (n.`prop1`) IS UNIQUE" | -| "ownershipId" | "RELATIONSHIP_KEY" | "CREATE CONSTRAINT `ownershipId` FOR ()-[r:`OWNS`]-() REQUIRE (r.`ownershipId`) IS RELATIONSHIP KEY" | -| "part_of" | "RELATIONSHIP_PROPERTY_TYPE" | "CREATE CONSTRAINT `part_of` FOR ()-[r:`PART_OF`]-() REQUIRE (r.`order`) IS :: INTEGER" | -| "part_of_tags" | "RELATIONSHIP_PROPERTY_TYPE" | "CREATE CONSTRAINT `part_of_tags` FOR ()-[r:`PART_OF`]-() REQUIRE (r.`tags`) IS :: STRING | LIST" | -| "prequels" | "RELATIONSHIP_UNIQUENESS" | "CREATE CONSTRAINT `prequels` FOR ()-[r:`PREQUEL_OF`]-() REQUIRE (r.`order`, r.`author`) IS UNIQUE" | -| "rel_constraint_with_options" | "RELATIONSHIP_UNIQUENESS" | "CREATE CONSTRAINT `rel_constraint_with_options` FOR ()-[r:`SEQUEL_OF`]-() REQUIRE (r.`order`, r.`seriesTitle`, r.`number`) IS UNIQUE" | -| "rel_exist_param" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "CREATE CONSTRAINT `rel_exist_param` FOR ()-[r:`WROTE`]-() REQUIRE (r.`published`) IS NOT NULL" | -| "sequels" | "RELATIONSHIP_UNIQUENESS" | "CREATE CONSTRAINT `sequels` FOR ()-[r:`SEQUEL_OF`]-() REQUIRE (r.`order`) IS UNIQUE" | -| "wrote_year" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "CREATE CONSTRAINT `wrote_year` FOR ()-[r:`WROTE`]-() REQUIRE (r.`year`) IS NOT NULL" | -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| name | type | createStatement | ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| "actor_fullname" | "NODE_KEY" | "CREATE CONSTRAINT `actor_fullname` FOR (n:`Actor`) REQUIRE (n.`firstname`, n.`surname`) IS KEY" | +| "author_name" | "NODE_PROPERTY_EXISTENCE" | "CREATE CONSTRAINT `author_name` FOR (n:`Author`) REQUIRE (n.`name`) IS NOT NULL" | +| "book_isbn" | "NODE_PROPERTY_UNIQUENESS" | "CREATE CONSTRAINT `book_isbn` FOR (n:`Book`) REQUIRE (n.`isbn`) IS UNIQUE" | +| "book_title_year" | "NODE_PROPERTY_UNIQUENESS" | "CREATE CONSTRAINT `book_title_year` FOR (n:`Book`) REQUIRE (n.`title`, n.`publicationYear`) IS UNIQUE" | +| "constraint_with_provider" | "NODE_KEY" | "CREATE CONSTRAINT `constraint_with_provider` FOR (n:`Actor`) REQUIRE (n.`surname`) IS KEY" | +| "director_imdbId" | "NODE_KEY" | "CREATE CONSTRAINT `director_imdbId` FOR (n:`Director`) REQUIRE (n.`imdbId`) IS KEY" | +| "knows_since_how" | "RELATIONSHIP_KEY" | "CREATE CONSTRAINT `knows_since_how` FOR ()-[r:`KNOWS`]-() REQUIRE (r.`since`, r.`how`) IS KEY" | +| "movie_tagline" | "NODE_PROPERTY_TYPE" | "CREATE CONSTRAINT `movie_tagline` FOR (n:`Movie`) REQUIRE (n.`tagline`) IS :: STRING | LIST" | +| "movie_title" | "NODE_PROPERTY_TYPE" | "CREATE CONSTRAINT `movie_title` FOR (n:`Movie`) REQUIRE (n.`title`) IS :: STRING" | +| "node_uniqueness_param" | "NODE_PROPERTY_UNIQUENESS" | "CREATE CONSTRAINT `node_uniqueness_param` FOR (n:`Book`) REQUIRE (n.`prop1`) IS UNIQUE" | +| "ownershipId" | "RELATIONSHIP_KEY" | "CREATE CONSTRAINT `ownershipId` FOR ()-[r:`OWNS`]-() REQUIRE (r.`ownershipId`) IS KEY" | +| "part_of" | "RELATIONSHIP_PROPERTY_TYPE" | "CREATE CONSTRAINT `part_of` FOR ()-[r:`PART_OF`]-() REQUIRE (r.`order`) IS :: INTEGER" | +| "part_of_tags" | "RELATIONSHIP_PROPERTY_TYPE" | "CREATE CONSTRAINT `part_of_tags` FOR ()-[r:`PART_OF`]-() REQUIRE (r.`tags`) IS :: STRING | LIST" | +| "prequels" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "CREATE CONSTRAINT `prequels` FOR ()-[r:`PREQUEL_OF`]-() REQUIRE (r.`order`, r.`author`) IS UNIQUE" | +| "rel_constraint_with_options" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "CREATE CONSTRAINT `rel_constraint_with_options` FOR ()-[r:`SEQUEL_OF`]-() REQUIRE (r.`order`, r.`seriesTitle`, r.`number`) IS UNIQUE" | +| "rel_exist_param" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "CREATE CONSTRAINT `rel_exist_param` FOR ()-[r:`WROTE`]-() REQUIRE (r.`published`) IS NOT NULL" | +| "sequels" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "CREATE CONSTRAINT `sequels` FOR ()-[r:`SEQUEL_OF`]-() REQUIRE (r.`order`) IS UNIQUE" | +| "wrote_year" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "CREATE CONSTRAINT `wrote_year` FOR ()-[r:`WROTE`]-() REQUIRE (r.`year`) IS NOT NULL" | ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ---- ====== diff --git a/modules/ROOT/pages/constraints/syntax.adoc b/modules/ROOT/pages/constraints/syntax.adoc index e7762d7c3..48533dd83 100644 --- a/modules/ROOT/pages/constraints/syntax.adoc +++ b/modules/ROOT/pages/constraints/syntax.adoc @@ -221,9 +221,9 @@ Listing constraints requires the link:{neo4j-docs-base-uri}/operations-manual/{p ---- SHOW [ ALL - |NODE UNIQUE[NESS] - |REL[ATIONSHIP] UNIQUE[NESS] - |UNIQUE[NESS] + |NODE [PROPERTY] UNIQUE[NESS] + |REL[ATIONSHIP] [PROPERTY] UNIQUE[NESS] + |[PROPERTY] UNIQUE[NESS] |NODE [PROPERTY] EXIST[ENCE] |REL[ATIONSHIP] [PROPERTY] EXIST[ENCE] |[PROPERTY] EXIST[ENCE] @@ -242,9 +242,9 @@ SHOW [ ---- SHOW [ ALL - |NODE UNIQUE[NESS] - |REL[ATIONSHIP] UNIQUE[NESS] - |UNIQUE[NESS] + |NODE [PROPERTY] UNIQUE[NESS] + |REL[ATIONSHIP] [PROPERTY] UNIQUE[NESS] + |[PROPERTY] UNIQUE[NESS] |NODE [PROPERTY] EXIST[ENCE] |REL[ATIONSHIP] [PROPERTY] EXIST[ENCE] |[PROPERTY] EXIST[ENCE] @@ -272,13 +272,13 @@ The type filtering keywords filters the returned constraints on constraint type: | Returns all constraints, no filtering on constraint type. This is the default if none is given. -|NODE UNIQUE[NESS] +|NODE [PROPERTY] UNIQUE[NESS] | Returns the node property uniqueness constraints. -|REL[ATIONSHIP] UNIQUE[NESS] +|REL[ATIONSHIP] [PROPERTY] UNIQUE[NESS] | Returns the relationship property uniqueness constraints. -|UNIQUE[NESS] +|[PROPERTY] UNIQUE[NESS] | Returns all property uniqueness constraints, for both nodes and relationships. |NODE [PROPERTY] EXIST[ENCE] diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index 0c4380ae1..615fef195 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -105,6 +105,33 @@ a| The column `propertyTypes` returned by the procedures link:{neo4j-docs-base-uri}/operations-manual/{page-version}/procedures/#procedure_db_schema_nodetypeproperties[`db.schema.nodeTypeProperties()`] and link:{neo4j-docs-base-uri}/operations-manual/{page-version}/procedures/#procedure_db_schema_reltypeproperties[`db.schema.relTypeProperties()`] previously returned a list of strings representing the potential Java types for a given property. It now returns a list of strings representing the possible Cypher Types the given property has. For all available Cypher types, see the section on xref::values-and-types/property-structural-constructed.adoc#types-synonyms[types and their synonyms]. + +a| +label:syntax[] +label:updated[] +[source, cypher, role="noheader"] +---- +SHOW NODE PROPERTY UNIQUENESS CONSTRAINTS +SHOW RELATIONSHIP PROPERTY UNIQUENESS CONSTRAINTS +SHOW PROPERTY UNIQUENESS CONSTRAINTS +---- +a| +The constraint type keyword filtering for xref:constraints/syntax.adoc#list-constraints[`SHOW CONSTRAINTS`] now allows the optional keyword `PROPERTY` when filtering on property uniqueness constraints. +The constraint type column returned is also updated to return `NODE_PROPERTY_UNIQUENESS` and `RELATIONSHIP_PROPERTY_UNIQUENESS`. + +a| +label:functionality[] +label:updated[] +[source, cypher, role="noheader"] +---- +SHOW TRANSACTIONS YIELD startTime, clientAddress, outerTransactionId, currentQuery, currentQueryId, parameters, planner, runtime, indexes, currentQueryStartTime, currentQueryElapsedTime, currentQueryCpuTime, currentQueryIdleTime, currentQueryStatus +---- +a| +Several xref:clauses/transaction-clauses.adoc#query-listing-transactions[`SHOW TRANSACTIONS`] columns have been updated: + +* `startTime` and `currentQueryStartTime` now return a `ZONED DATETIME` instead of a `STRING` representation of a temporal value. +* `clientAddress` and `outerTransactionId` now return `null` instead of an empty `STRING` when unavailable. +* The current query-related columns — `currentQuery`, `currentQueryId`, `parameters`, `planner`, `runtime`, `indexes`, `currentQueryStartTime`, `currentQueryElapsedTime`, `currentQueryCpuTime`, `currentQueryIdleTime`, and `currentQueryStatus` — now return `null` when no query is executing. |=== [[cypher-deprecations-additions-removals-5.26]] From 354fa979d969e1d79291121adc85f53947aafb91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Tue, 5 Nov 2024 10:07:02 +0100 Subject: [PATCH 29/77] Fix query plan versions (#1097) --- .../tutorials/advanced-query-tuning.adoc | 10 +- .../tutorials/basic-query-tuning.adoc | 6 +- .../tutorials/shortestpath-planning.adoc | 6 +- .../index-hints.adoc | 26 +- .../operators/operators-detail.adoc | 292 +++++++++--------- .../runtimes/concepts.adoc | 6 +- 6 files changed, 173 insertions(+), 173 deletions(-) diff --git a/modules/ROOT/pages/appendix/tutorials/advanced-query-tuning.adoc b/modules/ROOT/pages/appendix/tutorials/advanced-query-tuning.adoc index 2546d7b8a..9db47e053 100644 --- a/modules/ROOT/pages/appendix/tutorials/advanced-query-tuning.adoc +++ b/modules/ROOT/pages/appendix/tutorials/advanced-query-tuning.adoc @@ -669,7 +669,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -711,7 +711,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -776,7 +776,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -823,7 +823,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -878,7 +878,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 diff --git a/modules/ROOT/pages/appendix/tutorials/basic-query-tuning.adoc b/modules/ROOT/pages/appendix/tutorials/basic-query-tuning.adoc index 6b30f55a0..170ac0111 100644 --- a/modules/ROOT/pages/appendix/tutorials/basic-query-tuning.adoc +++ b/modules/ROOT/pages/appendix/tutorials/basic-query-tuning.adoc @@ -623,7 +623,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -680,7 +680,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -747,7 +747,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 diff --git a/modules/ROOT/pages/appendix/tutorials/shortestpath-planning.adoc b/modules/ROOT/pages/appendix/tutorials/shortestpath-planning.adoc index 64b0a5233..96887c531 100644 --- a/modules/ROOT/pages/appendix/tutorials/shortestpath-planning.adoc +++ b/modules/ROOT/pages/appendix/tutorials/shortestpath-planning.adoc @@ -81,7 +81,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -158,7 +158,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 1024 @@ -261,7 +261,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 diff --git a/modules/ROOT/pages/indexes/search-performance-indexes/index-hints.adoc b/modules/ROOT/pages/indexes/search-performance-indexes/index-hints.adoc index 75540eccf..93d9cec90 100644 --- a/modules/ROOT/pages/indexes/search-performance-indexes/index-hints.adoc +++ b/modules/ROOT/pages/indexes/search-performance-indexes/index-hints.adoc @@ -72,7 +72,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -173,7 +173,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -226,7 +226,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -267,7 +267,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -318,7 +318,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -362,7 +362,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -419,7 +419,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -477,7 +477,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -534,7 +534,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -587,7 +587,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -645,7 +645,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -704,7 +704,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -741,7 +741,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 diff --git a/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc b/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc index 0a9cccc30..984d631d1 100644 --- a/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc +++ b/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc @@ -108,7 +108,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -153,7 +153,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -204,7 +204,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -250,7 +250,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -293,7 +293,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -339,7 +339,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -384,7 +384,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -430,7 +430,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -475,7 +475,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -520,7 +520,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -564,7 +564,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -607,7 +607,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -651,7 +651,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -695,7 +695,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -747,7 +747,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -792,7 +792,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -837,7 +837,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -882,7 +882,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -934,7 +934,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -982,7 +982,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1029,7 +1029,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1077,7 +1077,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1120,7 +1120,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1163,7 +1163,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1204,7 +1204,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1248,7 +1248,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1291,7 +1291,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1334,7 +1334,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1373,7 +1373,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1415,7 +1415,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1451,7 +1451,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1492,7 +1492,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1534,7 +1534,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1579,7 +1579,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1620,7 +1620,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1664,7 +1664,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1709,7 +1709,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1757,7 +1757,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1802,7 +1802,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1850,7 +1850,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1892,7 +1892,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1935,7 +1935,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1980,7 +1980,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2026,7 +2026,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2078,7 +2078,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2124,7 +2124,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2178,7 +2178,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2236,7 +2236,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2288,7 +2288,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2339,7 +2339,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2386,7 +2386,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2432,7 +2432,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2484,7 +2484,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2529,7 +2529,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2573,7 +2573,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2620,7 +2620,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2668,7 +2668,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2719,7 +2719,7 @@ Planner COST Runtime SLOTTED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +-----------------+-------------------------------------+----------------+------+---------+------------------------+ | Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | @@ -2775,7 +2775,7 @@ Planner COST Runtime SLOTTED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +-------------------+--------------------------------------------------------+----------------+------+---------+----------------+------------------------+ | Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | @@ -2833,7 +2833,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2888,7 +2888,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2952,7 +2952,7 @@ Planner COST Runtime SLOTTED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +--------------------+-----------------------------------------+----------------+------+---------+------------------------+ | Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | @@ -3016,7 +3016,7 @@ Planner COST Runtime SLOTTED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +--------------------+-----------------------------------------+----------------+------+---------+------------------------+ | Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | +--------------------+-----------------------------------------+----------------+------+---------+------------------------+ @@ -3078,7 +3078,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3136,7 +3136,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3196,7 +3196,7 @@ Planner COST Runtime SLOTTED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +-----------------------+-----------------------------------------+----------------+------+---------+------------------------+ | Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | @@ -3258,7 +3258,7 @@ Planner COST Runtime SLOTTED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +---------------------------+-----------------------------------------+----------------+------+---------+------------------------+ | Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | @@ -3323,7 +3323,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3371,7 +3371,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3426,7 +3426,7 @@ Planner COST Runtime SLOTTED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +-----------------+-----------------------------------+----------------+------+---------+------------------------+ | Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | @@ -3477,7 +3477,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3536,7 +3536,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +--------------------+----+---------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ | Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | @@ -3591,7 +3591,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3638,7 +3638,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3690,7 +3690,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3739,7 +3739,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3786,7 +3786,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3833,7 +3833,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3886,7 +3886,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3941,7 +3941,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3990,7 +3990,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4050,7 +4050,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4111,7 +4111,7 @@ Planner COST Runtime SLOTTED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +---------------------------------+-------------------------------------------------------+----------------+------+---------+------------------------+ | Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | @@ -4164,7 +4164,7 @@ Planner COST Runtime SLOTTED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +-------------------------------------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+------------------------+ | Operator | Id | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | @@ -4216,7 +4216,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4262,7 +4262,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4306,7 +4306,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4369,7 +4369,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4429,7 +4429,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4483,7 +4483,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4540,7 +4540,7 @@ Planner COST Runtime SLOTTED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +-------------------+----------------------------------------+----------------+------+---------+------------------------+ | Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | @@ -4599,7 +4599,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4664,7 +4664,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4727,7 +4727,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4775,7 +4775,7 @@ Planner COST Runtime SLOTTED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +-----------------+---------------------------------------------------------+----------------+------+---------+------------------------+ | Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | @@ -4821,7 +4821,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4875,7 +4875,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4937,7 +4937,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5002,7 +5002,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5055,7 +5055,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5103,7 +5103,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5149,7 +5149,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5193,7 +5193,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5243,7 +5243,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5289,7 +5289,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5335,7 +5335,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5382,7 +5382,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5433,7 +5433,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5484,7 +5484,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5534,7 +5534,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5586,7 +5586,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5635,7 +5635,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5690,7 +5690,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5736,7 +5736,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5782,7 +5782,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5832,7 +5832,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5883,7 +5883,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5935,7 +5935,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5981,7 +5981,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -6038,7 +6038,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -6089,7 +6089,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -6147,7 +6147,7 @@ Planner COST Runtime SLOTTED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +-----------------+--------------------------------------+----------------+------+---------+------------------------+ | Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | @@ -6199,7 +6199,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -6247,7 +6247,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -6300,7 +6300,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -6346,7 +6346,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -6393,7 +6393,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -6445,7 +6445,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -6492,7 +6492,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -6539,7 +6539,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -6586,7 +6586,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -6633,7 +6633,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -6679,7 +6679,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -6735,7 +6735,7 @@ Planner ADMINISTRATION Runtime SCHEMA -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +-------------------+------------------------------------------------------------------+ | Operator | Details | @@ -6777,7 +6777,7 @@ Planner ADMINISTRATION Runtime SCHEMA -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +--------------------------------+------------------------------------------------------------------+ | Operator | Details | @@ -6819,7 +6819,7 @@ Planner ADMINISTRATION Runtime SCHEMA -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +-----------------+---------------------------------+ | Operator | Details | @@ -6858,7 +6858,7 @@ Planner COST Runtime SLOTTED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +------------------+-------------------------------------------------------------------+----------------+------+---------+------------------------+ | Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | @@ -6902,7 +6902,7 @@ Planner ADMINISTRATION Runtime SCHEMA -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +--------------+-----------------------------------------------+ | Operator | Details | @@ -6944,7 +6944,7 @@ Planner ADMINISTRATION Runtime SCHEMA -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +---------------------------+----------------------------------------------------+ | Operator | Details | @@ -6984,7 +6984,7 @@ Planner ADMINISTRATION Runtime SCHEMA -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +------------+---------------+ | Operator | Details | @@ -7023,7 +7023,7 @@ Planner COST Runtime SLOTTED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +-----------------+-------------------------------------------------------------------------------------------------+----------------+------+---------+------------------------+ | Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | @@ -7066,7 +7066,7 @@ Planner COST Runtime SLOTTED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +-----------------+-----------------------------------------------------+----------------+------+---------+------------------------+ | Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | @@ -7107,7 +7107,7 @@ Planner COST Runtime SLOTTED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +-----------------+----------------------------------------+----------------+------+---------+------------------------+ | Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | @@ -7145,7 +7145,7 @@ Planner COST Runtime SLOTTED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +-----------------+---------------------------------------------------+----------------+------+---------+------------------------+ | Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | @@ -7185,7 +7185,7 @@ Planner COST Runtime SLOTTED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +-------------------+-----------------------------------------------------------------------------------------------+----------------+------+---------+------------------------+ | Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | @@ -7226,7 +7226,7 @@ Planner COST Runtime SLOTTED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +------------------------+--------------------------------------------------------+----------------+------+---------+------------------------+ | Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | diff --git a/modules/ROOT/pages/planning-and-tuning/runtimes/concepts.adoc b/modules/ROOT/pages/planning-and-tuning/runtimes/concepts.adoc index 456de836f..731799097 100644 --- a/modules/ROOT/pages/planning-and-tuning/runtimes/concepts.adoc +++ b/modules/ROOT/pages/planning-and-tuning/runtimes/concepts.adoc @@ -73,7 +73,7 @@ Planner COST Runtime SLOTTED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +-------------------+----+------------------------------------------------------------------------+----------------+ | Operator | Id | Details | Estimated Rows | @@ -165,7 +165,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -267,7 +267,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 From 99026bafc7c716f7f54ce1384ff9b53fcf2a5297 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Tue, 5 Nov 2024 15:48:09 +0100 Subject: [PATCH 30/77] Cherry pick 1096 (index provider deprecation) (#1099) Co-authored-by: emmaholmbergohlsson --- .../constraints/managing-constraints.adoc | 63 ------------------- modules/ROOT/pages/constraints/syntax.adoc | 24 ------- ...ions-additions-removals-compatibility.adoc | 13 ++++ .../managing-indexes.adoc | 32 ++-------- .../semantic-indexes/vector-indexes.adoc | 5 +- modules/ROOT/pages/indexes/syntax.adoc | 24 +++---- 6 files changed, 29 insertions(+), 132 deletions(-) diff --git a/modules/ROOT/pages/constraints/managing-constraints.adoc b/modules/ROOT/pages/constraints/managing-constraints.adoc index c10efff61..c64eecaf3 100644 --- a/modules/ROOT/pages/constraints/managing-constraints.adoc +++ b/modules/ROOT/pages/constraints/managing-constraints.adoc @@ -895,7 +895,6 @@ Constraint already exists: Constraint( id=7, name='book_title_year', type='NODE === Constraints and indexes * xref:constraints/managing-constraints.adoc#constraints-and-backing-indexes[] -* xref:constraints/managing-constraints.adoc#create-constraint-with-index-provider[] * xref:constraints/managing-constraints.adoc#constraint-failures-and-indexes[] [[constraints-and-backing-indexes]] @@ -979,60 +978,6 @@ SHOW INDEXES WHERE owningConstraint IS NOT NULL [NOTE] Property existence and property type constraints are not backed by indexes. -[[create-constraint-with-index-provider]] -==== Creating constraints with an index provider - -Because property uniqueness and key constraints have backing indexes, an index provider can be provided when creating these constraints using the `OPTIONS` clause and the `indexProvider` option. - -The only valid value for the index provider is: - -* `range-1.0` label:default[] - - -.Create a node key constraint with a specified index provider -====== - -.Create a constraint requiring `Actor` nodes to have a unique `surname` property as a node key, specifying `range-1.0` as index provider -[source, cypher] ----- -CREATE CONSTRAINT constraint_with_provider -FOR (actor:Actor) REQUIRE actor.surname IS NODE KEY -OPTIONS { - indexProvider: 'range-1.0' -} ----- - -.Result -[source, queryresult] ----- -Added 1 constraint. ----- - -====== - -.Create a relationship property uniqueness constraint with a specified index provider -====== - -.Create a constraint requiring `SEQUEL_OF` relationships to have a unique combination of `order`, `seriesTitle`, and `number` properties, specifying `range-1.0` as index provider -[source, cypher] ----- -CREATE CONSTRAINT rel_constraint_with_options -FOR ()-[sequel:SEQUEL_OF]-() REQUIRE (sequel.order, sequel.seriesTitle, sequel.number) IS UNIQUE -OPTIONS { - indexProvider: 'range-1.0' -} ----- - -.Result -[source, queryresult] ----- -Added 1 constraint. ----- - -====== - -There are no valid index configuration values for the constraint-backing range indexes. - [[constraint-failures-and-indexes]] ==== Constraint failures and indexes @@ -1494,7 +1439,6 @@ SHOW CONSTRAINTS | 10 | "author_name" | "NODE_PROPERTY_EXISTENCE" | "NODE" | ["Author"] | ["name"] | NULL | NULL | | 3 | "book_isbn" | "NODE_PROPERTY_UNIQUENESS" | "NODE" | ["Book"] | ["isbn"] | "book_isbn" | NULL | | 7 | "book_title_year" | "NODE_PROPERTY_UNIQUENESS" | "NODE" | ["Book"] | ["title", "publicationYear"] | "book_title_year" | NULL | -| 28 | "constraint_with_provider" | "NODE_KEY" | "NODE" | ["Actor"] | ["surname"] | "constraint_with_provider" | NULL | | 17 | "director_imdbId" | "NODE_KEY" | "NODE" | ["Director"] | ["imdbId"] | "director_imdbId" | NULL | | 23 | "knows_since_how" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["KNOWS"] | ["since", "how"] | "knows_since_how" | NULL | | 14 | "movie_tagline" | "NODE_PROPERTY_TYPE" | "NODE" | ["Movie"] | ["tagline"] | NULL | "STRING | LIST" | @@ -1504,7 +1448,6 @@ SHOW CONSTRAINTS | 13 | "part_of" | "RELATIONSHIP_PROPERTY_TYPE" | "RELATIONSHIP" | ["PART_OF"] | ["order"] | NULL | "INTEGER" | | 15 | "part_of_tags" | "RELATIONSHIP_PROPERTY_TYPE" | "RELATIONSHIP" | ["PART_OF"] | ["tags"] | NULL | "STRING | LIST" | | 9 | "prequels" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["PREQUEL_OF"] | ["order", "author"] | "prequels" | NULL | -| 30 | "rel_constraint_with_options" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order", "seriesTitle", "number"] | "rel_constraint_with_options" | NULL | | 26 | "rel_exist_param" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["published"] | NULL | NULL | | 5 | "sequels" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order"] | "sequels" | NULL | | 11 | "wrote_year" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["year"] | NULL | NULL | @@ -1534,7 +1477,6 @@ SHOW CONSTRAINTS YIELD * | 10 | "author_name" | "NODE_PROPERTY_EXISTENCE" | "NODE" | ["Author"] | ["name"] | NULL | NULL | NULL | "CREATE CONSTRAINT `author_name` FOR (n:`Author`) REQUIRE (n.`name`) IS NOT NULL" | | 3 | "book_isbn" | "NODE_PROPERTY_UNIQUENESS" | "NODE" | ["Book"] | ["isbn"] | "book_isbn" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `book_isbn` FOR (n:`Book`) REQUIRE (n.`isbn`) IS UNIQUE" | | 7 | "book_title_year" | "NODE_PROPERTY_UNIQUENESS" | "NODE" | ["Book"] | ["title", "publicationYear"] | "book_title_year" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `book_title_year` FOR (n:`Book`) REQUIRE (n.`title`, n.`publicationYear`) IS UNIQUE" | -| 28 | "constraint_with_provider" | "NODE_KEY" | "NODE" | ["Actor"] | ["surname"] | "constraint_with_provider" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `constraint_with_provider` FOR (n:`Actor`) REQUIRE (n.`surname`) IS KEY" | | 17 | "director_imdbId" | "NODE_KEY" | "NODE" | ["Director"] | ["imdbId"] | "director_imdbId" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `director_imdbId` FOR (n:`Director`) REQUIRE (n.`imdbId`) IS KEY" | | 23 | "knows_since_how" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["KNOWS"] | ["since", "how"] | "knows_since_how" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `knows_since_how` FOR ()-[r:`KNOWS`]-() REQUIRE (r.`since`, r.`how`) IS KEY" | | 14 | "movie_tagline" | "NODE_PROPERTY_TYPE" | "NODE" | ["Movie"] | ["tagline"] | NULL | "STRING | LIST" | NULL | "CREATE CONSTRAINT `movie_tagline` FOR (n:`Movie`) REQUIRE (n.`tagline`) IS :: STRING | LIST" | @@ -1544,7 +1486,6 @@ SHOW CONSTRAINTS YIELD * | 13 | "part_of" | "RELATIONSHIP_PROPERTY_TYPE" | "RELATIONSHIP" | ["PART_OF"] | ["order"] | NULL | "INTEGER" | NULL | "CREATE CONSTRAINT `part_of` FOR ()-[r:`PART_OF`]-() REQUIRE (r.`order`) IS :: INTEGER" | | 15 | "part_of_tags" | "RELATIONSHIP_PROPERTY_TYPE" | "RELATIONSHIP" | ["PART_OF"] | ["tags"] | NULL | "STRING | LIST" | NULL | "CREATE CONSTRAINT `part_of_tags` FOR ()-[r:`PART_OF`]-() REQUIRE (r.`tags`) IS :: STRING | LIST" | | 9 | "prequels" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["PREQUEL_OF"] | ["order", "author"] | "prequels" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `prequels` FOR ()-[r:`PREQUEL_OF`]-() REQUIRE (r.`order`, r.`author`) IS UNIQUE" | -| 30 | "rel_constraint_with_options" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order", "seriesTitle", "number"] | "rel_constraint_with_options" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `rel_constraint_with_options` FOR ()-[r:`SEQUEL_OF`]-() REQUIRE (r.`order`, r.`seriesTitle`, r.`number`) IS UNIQUE" | | 26 | "rel_exist_param" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["published"] | NULL | NULL | NULL | "CREATE CONSTRAINT `rel_exist_param` FOR ()-[r:`WROTE`]-() REQUIRE (r.`published`) IS NOT NULL" | | 5 | "sequels" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order"] | "sequels" | NULL | {indexConfig: {}, indexProvider: "range-1.0"} | "CREATE CONSTRAINT `sequels` FOR ()-[r:`SEQUEL_OF`]-() REQUIRE (r.`order`) IS UNIQUE" | | 11 | "wrote_year" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["year"] | NULL | NULL | NULL | "CREATE CONSTRAINT `wrote_year` FOR ()-[r:`WROTE`]-() REQUIRE (r.`year`) IS NOT NULL" | @@ -1574,7 +1515,6 @@ SHOW KEY CONSTRAINTS | id | name | type | entityType | labelsOrTypes | properties | ownedIndex | propertyType | +--------------------------------------------------------------------------------------------------------------------------------------------------------------+ | 21 | "actor_fullname" | "NODE_KEY" | "NODE" | ["Actor"] | ["firstname", "surname"] | "actor_fullname" | NULL | -| 28 | "constraint_with_provider" | "NODE_KEY" | "NODE" | ["Actor"] | ["surname"] | "constraint_with_provider" | NULL | | 17 | "director_imdbId" | "NODE_KEY" | "NODE" | ["Director"] | ["imdbId"] | "director_imdbId" | NULL | | 23 | "knows_since_how" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["KNOWS"] | ["since", "how"] | "knows_since_how" | NULL | | 19 | "ownershipId" | "RELATIONSHIP_KEY" | "RELATIONSHIP" | ["OWNS"] | ["ownershipId"] | "ownershipId" | NULL | @@ -1607,7 +1547,6 @@ WHERE entityType = 'RELATIONSHIP' | 13 | "part_of" | "RELATIONSHIP_PROPERTY_TYPE" | "RELATIONSHIP" | ["PART_OF"] | ["order"] | NULL | "INTEGER" | | 15 | "part_of_tags" | "RELATIONSHIP_PROPERTY_TYPE" | "RELATIONSHIP" | ["PART_OF"] | ["tags"] | NULL | "STRING | LIST" | | 9 | "prequels" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["PREQUEL_OF"] | ["order", "author"] | "prequels" | NULL | -| 30 | "rel_constraint_with_options" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order", "seriesTitle", "number"] | "rel_constraint_with_options" | NULL | | 26 | "rel_exist_param" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["published"] | NULL | NULL | | 5 | "sequels" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order"] | "sequels" | NULL | | 11 | "wrote_year" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"] | ["year"] | NULL | NULL | @@ -1639,7 +1578,6 @@ YIELD name, type, createStatement | "author_name" | "NODE_PROPERTY_EXISTENCE" | "CREATE CONSTRAINT `author_name` FOR (n:`Author`) REQUIRE (n.`name`) IS NOT NULL" | | "book_isbn" | "NODE_PROPERTY_UNIQUENESS" | "CREATE CONSTRAINT `book_isbn` FOR (n:`Book`) REQUIRE (n.`isbn`) IS UNIQUE" | | "book_title_year" | "NODE_PROPERTY_UNIQUENESS" | "CREATE CONSTRAINT `book_title_year` FOR (n:`Book`) REQUIRE (n.`title`, n.`publicationYear`) IS UNIQUE" | -| "constraint_with_provider" | "NODE_KEY" | "CREATE CONSTRAINT `constraint_with_provider` FOR (n:`Actor`) REQUIRE (n.`surname`) IS KEY" | | "director_imdbId" | "NODE_KEY" | "CREATE CONSTRAINT `director_imdbId` FOR (n:`Director`) REQUIRE (n.`imdbId`) IS KEY" | | "knows_since_how" | "RELATIONSHIP_KEY" | "CREATE CONSTRAINT `knows_since_how` FOR ()-[r:`KNOWS`]-() REQUIRE (r.`since`, r.`how`) IS KEY" | | "movie_tagline" | "NODE_PROPERTY_TYPE" | "CREATE CONSTRAINT `movie_tagline` FOR (n:`Movie`) REQUIRE (n.`tagline`) IS :: STRING | LIST" | @@ -1649,7 +1587,6 @@ YIELD name, type, createStatement | "part_of" | "RELATIONSHIP_PROPERTY_TYPE" | "CREATE CONSTRAINT `part_of` FOR ()-[r:`PART_OF`]-() REQUIRE (r.`order`) IS :: INTEGER" | | "part_of_tags" | "RELATIONSHIP_PROPERTY_TYPE" | "CREATE CONSTRAINT `part_of_tags` FOR ()-[r:`PART_OF`]-() REQUIRE (r.`tags`) IS :: STRING | LIST" | | "prequels" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "CREATE CONSTRAINT `prequels` FOR ()-[r:`PREQUEL_OF`]-() REQUIRE (r.`order`, r.`author`) IS UNIQUE" | -| "rel_constraint_with_options" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "CREATE CONSTRAINT `rel_constraint_with_options` FOR ()-[r:`SEQUEL_OF`]-() REQUIRE (r.`order`, r.`seriesTitle`, r.`number`) IS UNIQUE" | | "rel_exist_param" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "CREATE CONSTRAINT `rel_exist_param` FOR ()-[r:`WROTE`]-() REQUIRE (r.`published`) IS NOT NULL" | | "sequels" | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "CREATE CONSTRAINT `sequels` FOR ()-[r:`SEQUEL_OF`]-() REQUIRE (r.`order`) IS UNIQUE" | | "wrote_year" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "CREATE CONSTRAINT `wrote_year` FOR ()-[r:`WROTE`]-() REQUIRE (r.`year`) IS NOT NULL" | diff --git a/modules/ROOT/pages/constraints/syntax.adoc b/modules/ROOT/pages/constraints/syntax.adoc index 48533dd83..77b63b930 100644 --- a/modules/ROOT/pages/constraints/syntax.adoc +++ b/modules/ROOT/pages/constraints/syntax.adoc @@ -26,10 +26,6 @@ It may still throw an error if conflicting data, indexes, or constraints exist. Examples of this are nodes with missing properties, indexes with the same name, or constraints with same schema but a different conflicting constraint type. An informational notification is returned in case nothing happens showing the existing constraint which blocks the creation. -For constraints that are backed by an index, the index provider for the backing index can be specified using the `OPTIONS` clause. -Only one valid value exists for the index provider, `range-1.0`, which is the default value. -There is no supported index configuration for range indexes. - [[create-property-uniqueness-constraints]] === Create property uniqueness constraints @@ -39,7 +35,6 @@ There is no supported index configuration for range indexes. CREATE CONSTRAINT [constraint_name] [IF NOT EXISTS] FOR (n:LabelName) REQUIRE n.propertyName IS [NODE] UNIQUE -[OPTIONS "{" option: value[, ...] "}"] ---- .Syntax for creating a composite node property uniqueness constraint on multiple properties @@ -48,7 +43,6 @@ REQUIRE n.propertyName IS [NODE] UNIQUE CREATE CONSTRAINT [constraint_name] [IF NOT EXISTS] FOR (n:LabelName) REQUIRE (n.propertyName_1, ..., n.propertyName_n) IS [NODE] UNIQUE -[OPTIONS "{" option: value[, ...] "}"] ---- .Syntax for creating a relationship property uniqueness constraint on a single property @@ -57,7 +51,6 @@ REQUIRE (n.propertyName_1, ..., n.propertyName_n) IS [NODE] UNIQUE CREATE CONSTRAINT [constraint_name] [IF NOT EXISTS] FOR ()-"["r:RELATIONSHIP_TYPE"]"-() REQUIRE r.propertyName IS [REL[ATIONSHIP]] UNIQUE -[OPTIONS "{" option: value[, ...] "}"] ---- .Syntax for creating a composite relationship property uniqueness constraint on multiple properties @@ -66,11 +59,8 @@ REQUIRE r.propertyName IS [REL[ATIONSHIP]] UNIQUE CREATE CONSTRAINT [constraint_name] [IF NOT EXISTS] FOR ()-"["r:RELATIONSHIP_TYPE"]"-() REQUIRE (r.propertyName_1, ..., r.propertyName_n) IS [REL[ATIONSHIP]] UNIQUE -[OPTIONS "{" option: value[, ...] "}"] ---- -An index provider can be specified using the `OPTIONS` clause. - For examples on how to create property uniqueness constraints, see xref:constraints/managing-constraints.adoc#create-property-uniqueness-constraints[Create, show, and drop constraints -> Create property uniqueness constraint]. Property uniqueness constraints are xref:constraints/managing-constraints.adoc#constraints-and-indexes[index-backed]. @@ -84,7 +74,6 @@ Property uniqueness constraints are xref:constraints/managing-constraints.adoc#c CREATE CONSTRAINT [constraint_name] [IF NOT EXISTS] FOR (n:LabelName) REQUIRE n.propertyName IS NOT NULL -[OPTIONS "{" "}"] ---- .Syntax for creating a relationship property existence constraint @@ -93,11 +82,8 @@ REQUIRE n.propertyName IS NOT NULL CREATE CONSTRAINT [constraint_name] [IF NOT EXISTS] FOR ()-"["r:RELATIONSHIP_TYPE"]"-() REQUIRE r.propertyName IS NOT NULL -[OPTIONS "{" "}"] ---- -There are no supported `OPTIONS` values for property existence constraints, but an empty options map is allowed for consistency. - For examples on how to create property existence constraints, see xref:constraints/managing-constraints.adoc#create-property-existence-constraints[Create, show, and drop constraints -> Create property existence constraints]. [role=label--enterprise-edition] @@ -110,7 +96,6 @@ For examples on how to create property existence constraints, see xref:constrai CREATE CONSTRAINT [constraint_name] [IF NOT EXISTS] FOR (n:LabelName) REQUIRE n.propertyName {[IS] :: | IS TYPED} -[OPTIONS "{" "}"] ---- .Syntax for creating a relationship property type constraint @@ -119,7 +104,6 @@ REQUIRE n.propertyName {[IS] :: | IS TYPED} CREATE CONSTRAINT [constraint_name] [IF NOT EXISTS] FOR ()-"["r:RELATIONSHIP_TYPE"]"-() REQUIRE r.propertyName {[IS] :: | IS TYPED} -[OPTIONS "{" "}"] ---- The three variations of the expression, `IS ::`, `::`, and `IS TYPED` are syntactic synonyms for the same expression. @@ -153,8 +137,6 @@ Where `` is one of the following property types: Allowed syntax variations of these types are listed in xref::values-and-types/property-structural-constructed.adoc#types-synonyms[Types and their synonyms]. -There are no supported `OPTIONS` values for property type constraints, but an empty options map is allowed for consistency. - For examples on how to create property type constraints, see xref:constraints/managing-constraints.adoc#create-property-type-constraint[Create, show, and drop constraints -> Create property type constraints]. @@ -168,7 +150,6 @@ For examples on how to create property type constraints, see xref:constraints/m CREATE CONSTRAINT [constraint_name] [IF NOT EXISTS] FOR (n:LabelName) REQUIRE n.propertyName IS [NODE] KEY -[OPTIONS "{" option: value[, ...] "}"] ---- .Syntax for creating a composite node key constraint on multiple properties @@ -177,7 +158,6 @@ REQUIRE n.propertyName IS [NODE] KEY CREATE CONSTRAINT [constraint_name] [IF NOT EXISTS] FOR (n:LabelName) REQUIRE (n.propertyName_1, ..., n.propertyName_n) IS [NODE] KEY -[OPTIONS "{" option: value[, ...] "}"] ---- .Syntax for creating a relationship key constraint on a single property @@ -186,7 +166,6 @@ REQUIRE (n.propertyName_1, ..., n.propertyName_n) IS [NODE] KEY CREATE CONSTRAINT [constraint_name] [IF NOT EXISTS] FOR ()-"["r:RELATIONSHIP_TYPE"]"-() REQUIRE r.propertyName IS [REL[ATIONSHIP]] KEY -[OPTIONS "{" option: value[, ...] "}"] ---- .Syntax for creating a composite relationship key constraint on multiple properties @@ -195,11 +174,8 @@ REQUIRE r.propertyName IS [REL[ATIONSHIP]] KEY CREATE CONSTRAINT [constraint_name] [IF NOT EXISTS] FOR ()-"["r:RELATIONSHIP_TYPE"]"-() REQUIRE (r.propertyName_1, ..., r.propertyName_n) IS [REL[ATIONSHIP]] KEY -[OPTIONS "{" option: value[, ...] "}"] ---- -An index provider can be specified using the `OPTIONS` clause. - For examples on how to create key constraints, see xref:constraints/managing-constraints.adoc#create-key-constraints[Create, show, and drop constraints -> Create key constraints]. Key constraints are xref:constraints/managing-constraints.adoc#constraints-and-indexes[index-backed]. diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index 615fef195..07c832fed 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -144,6 +144,19 @@ Several xref:clauses/transaction-clauses.adoc#query-listing-transactions[`SHOW | Feature | Details +a| +label:functionality[] +label:deprecated[] +[source, cypher, role="noheader"] +---- +CREATE ... INDEX ... OPTIONS { indexProvider: ... } +CREATE ... CONSTRAINTS ... OPTIONS { indexProvider: ... } +---- +| Specifying an index provider in the `OPTIONS` map when creating an index or constraint is deprecated. + +This also means that the xref:indexes/semantic-indexes/vector-indexes.adoc[vector index] index provider, `vector-1.0`, is deprecated. +Use the default index provider, `vector-2.0`, instead. + a| label:functionality[] label:deprecated[] diff --git a/modules/ROOT/pages/indexes/search-performance-indexes/managing-indexes.adoc b/modules/ROOT/pages/indexes/search-performance-indexes/managing-indexes.adoc index d235707e9..764aacc89 100644 --- a/modules/ROOT/pages/indexes/search-performance-indexes/managing-indexes.adoc +++ b/modules/ROOT/pages/indexes/search-performance-indexes/managing-indexes.adoc @@ -33,10 +33,8 @@ If `IF NOT EXISTS` is appended to the command, no error is thrown and nothing ha It may still throw an error if conflicting constraints exist, such as constraints with the same name or schema and backing index type. Instead, an informational notification is returned showing the existing index which blocks the creation. -Index providers and configuration settings can be specified using the `OPTIONS` clause.footnote:[Index providers are essentially different implementations of the same index type. -Different providers are only available for xref:indexes/search-performance-indexes/managing-indexes.adoc#create-a-text-index-specifying-the-index-provider[text indexes].] - -However, not all indexes have available configuration settings or more than one provider. +Index configuration settings can be specified using the `OPTIONS` clause. +However, not all indexes have available configuration settings. In those cases, nothing needs to be specified and the `OPTIONS` map should be omitted from the query. [TIP] @@ -50,7 +48,7 @@ A newly created index is not immediately available but is created in the backgro Creating a range index can be done with the `CREATE INDEX` command. Note that the index name must be unique. -Range indexes have only one index provider available, `range-1.0`, and no supported index configuration. +Range indexes have no supported index configuration. [[range-indexes-supported-predicates]] [discrete] @@ -292,7 +290,6 @@ Text indexes are only used for exact query matches. To perform approximate match * xref:indexes/search-performance-indexes/managing-indexes.adoc#create-a-relationship-text-index[] * xref:indexes/search-performance-indexes/managing-indexes.adoc#create-a-text-index-by-param[] * xref:indexes/search-performance-indexes/managing-indexes.adoc#create-a-text-index-only-if-it-does-not-already-exist[] -* xref:indexes/search-performance-indexes/managing-indexes.adoc#create-a-text-index-specifying-the-index-provider[] [discrete] [[create-a-node-text-index]] @@ -362,30 +359,13 @@ Instead, an informational notification is returned. `TEXT INDEX node_text_index_nickname FOR (e:Person) ON (e.nickname)` already exists. ---- -[discrete] -[[create-a-text-index-specifying-the-index-provider]] -===== Create a text index specifying the index provider - -To create a text index with a specific index provider, the `OPTIONS` clause is used. -The valid values for the index provider are `text-2.0` and `text-1.0` (deprecated). -The default provider is `text-2.0`. - -.Creating a text index with index provider -[source, cypher] ----- -CREATE TEXT INDEX text_index_with_indexprovider FOR ()-[r:TYPE]-() ON (r.prop1) -OPTIONS {indexProvider: 'text-2.0'} ----- - -There is no supported index configuration for text indexes. - [[create-point-index]] === Create a point index Creating a point index can be done with the `CREATE POINT INDEX` command. Note that the index name must be unique. -Point indexes have supported index configuration, but only one index provider available, `point-1.0`. +Point indexes have supported index configuration. [discrete] [[point-indexes-supported-predicates]] @@ -548,7 +528,7 @@ Only one node label and one relationship type lookup index can exist at the same If a token lookup index has been deleted, it can be recreated with the `CREATE LOOKUP INDEX` command. Note that the index name must be unique. -Token lookup indexes have only one index provider available, `token-lookup-1.0`, and no supported index configuration. +Token lookup indexes have no supported index configuration. [discrete] [[lookup-index-supported-predicates]] @@ -838,7 +818,6 @@ SHOW INDEXES | 7 | "rel_text_index_name" | "ONLINE" | 100.0 | "TEXT" | "RELATIONSHIP" | ["KNOWS"] | ["interest"] | "text-2.0" | NULL | 2023-04-01T10:40:44.537Z | 3 | | 15 | "rel_type_lookup_index" | "ONLINE" | 100.0 | "LOOKUP" | "RELATIONSHIP" | NULL | NULL | "token-lookup-1.0" | NULL | 2023-04-12T21:41:44.537Z | 7 | | 8 | "text_index_param" | "ONLINE" | 100.0 | "TEXT" | "NODE" | ["Person"] | ["favoriteColor"] | "text-2.0" | NULL | NULL | 0 | -| 9 | "text_index_with_indexprovider" | "ONLINE" | 100.0 | "TEXT" | "RELATIONSHIP" | ["TYPE"] | ["prop1"] | "text-2.0" | NULL | NULL | 0 | | 18 | "uniqueBookIsbn" | "ONLINE" | 100.0 | "RANGE" | "NODE" | ["Book"] | ["isbn"] | "range-1.0" | "uniqueBookIsbn" | 2023-04-13T11:41:44.692Z | 6 | +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 18 rows @@ -881,7 +860,6 @@ RETURN name, type, provider, options.indexConfig AS config, createStatement | "rel_point_index_name" | "POINT" | "point-1.0" | {`spatial.cartesian.min`: [-1000000.0, -1000000.0], `spatial.wgs-84.min`: [-180.0, -90.0], `spatial.wgs-84.max`: [180.0, 90.0], `spatial.cartesian.max`: [1000000.0, 1000000.0], `spatial.wgs-84-3d.max`: [180.0, 90.0, 1000000.0], `spatial.cartesian-3d.min`: [-1000000.0, -1000000.0, -1000000.0], `spatial.cartesian-3d.max`: [1000000.0, 1000000.0, 1000000.0], `spatial.wgs-84-3d.min`: [-180.0, -90.0, -1000000.0]} | "CREATE POINT INDEX `rel_point_index_name` FOR ()-[r:`STREET`]-() ON (r.`intersection`) OPTIONS {indexConfig: {`spatial.cartesian-3d.max`: [1000000.0, 1000000.0, 1000000.0],`spatial.cartesian-3d.min`: [-1000000.0, -1000000.0, -1000000.0],`spatial.cartesian.max`: [1000000.0, 1000000.0],`spatial.cartesian.min`: [-1000000.0, -1000000.0],`spatial.wgs-84-3d.max`: [180.0, 90.0, 1000000.0],`spatial.wgs-84-3d.min`: [-180.0, -90.0, -1000000.0],`spatial.wgs-84.max`: [180.0, 90.0],`spatial.wgs-84.min`: [-180.0, -90.0]}, indexProvider: 'point-1.0'}" | | "rel_range_index_name" | "RANGE" | "range-1.0" | {} | "CREATE RANGE INDEX `rel_range_index_name` FOR ()-[r:`KNOWS`]-() ON (r.`since`)" | | "rel_text_index_name" | "TEXT" | "text-2.0" | {} | "CREATE TEXT INDEX `rel_text_index_name` FOR ()-[r:`KNOWS`]-() ON (r.`interest`) OPTIONS {indexConfig: {}, indexProvider: 'text-2.0'}" | -| "text_index_with_indexprovider" | "TEXT" | "text-2.0" | {} | "CREATE TEXT INDEX `text_index_with_indexprovider` FOR ()-[r:`TYPE`]-() ON (r.`prop1`) OPTIONS {indexConfig: {}, indexProvider: 'text-2.0'}" | | "uniqueBookIsbn" | "RANGE" | "range-1.0" | {} | "CREATE CONSTRAINT `uniqueBookIsbn` FOR (n:`Book`) REQUIRE (n.`isbn`) IS UNIQUE OPTIONS {indexConfig: {}, indexProvider: 'range-1.0'}" | +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ---- diff --git a/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc b/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc index 9ca635bbd..dd7701427 100644 --- a/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc +++ b/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc @@ -68,7 +68,7 @@ A vector index allows you to retrieve a neighborhood of nodes or relationships b A vector index is a single-label, single-property index for nodes or a single-relationship-type, single-property index for relationships. It can be used to index nodes or relationships by `LIST` properties valid to the dimensions and vector similarity function of the index. -Note that the available vector index providers (`vector-2.0` (default) and `vector-1.0`) support different index schemas, property value types, and vector dimensions. +Note that the available vector index providers (`vector-2.0` (default) and `vector-1.0` (deprecated)) support different index schemas, property value types, and vector dimensions. For more information, see xref:indexes/semantic-indexes/vector-indexes.adoc#vector-index-providers[]. A vector index is created by using the `CREATE VECTOR INDEX` command. @@ -338,9 +338,8 @@ DROP INDEX moviePlots [[vector-index-providers]] == Vector index providers for compatibility -The default and preferred vector index provider is `vector-2.0`. +As of Neo4j 5.18, the default index provider is `vector-2.0`. Previously created `vector-1.0` indexes will continue to function. -New indexes can still be created with the `vector-1.0` provider if it is specified in the `OPTIONS` map. .Learn more about vector index provider differences [%collapsible] diff --git a/modules/ROOT/pages/indexes/syntax.adoc b/modules/ROOT/pages/indexes/syntax.adoc index 9c8342c7f..0678c7d98 100644 --- a/modules/ROOT/pages/indexes/syntax.adoc +++ b/modules/ROOT/pages/indexes/syntax.adoc @@ -27,8 +27,8 @@ Instead, an informational notification is returned showing the existing index wh The index name must be unique among both indexes and constraints. A random name will be assigned if no name is explicitly given when an index is created. -Index providers and configuration settings can be specified using the `OPTIONS` clause. -However, not all indexes have available configuration settings or multiple providers. +Index configuration settings can be specified using the `OPTIONS` clause. +However, not all indexes have available configuration settings. In those cases, nothing needs to be specified and the `OPTIONS` map should be omitted from the query. [TIP] @@ -37,8 +37,8 @@ Creating an index requires link:{neo4j-docs-base-uri}/operations-manual/{page-ve [[create-range-index]] === Range indexes -Range indexes have only one index provider, `range-1.0`, and no supported index configuration. -Since the index provider will be assigned by default, the `OPTIONS` map has been omitted from the syntax below. +Range indexes have no supported index configuration. +The `OPTIONS` map has, therefore, been omitted from the syntax below. .Create a range index for a node label, either on a single property or composite [source,syntax] @@ -67,13 +67,15 @@ For more information, see xref:indexes/search-performance-indexes/managing-index [[create-text-index]] === Text indexes +Text indexes have no supported index configuration. +The `OPTIONS` map has, therefore, been omitted from the syntax below. + .Create a text index for a node label on a single property [source,syntax] ---- CREATE TEXT INDEX [index_name] [IF NOT EXISTS] FOR (n:LabelName) ON (n.propertyName_1) -[OPTIONS “{“ option: value[, …] “}”] ---- .Create a text index for a relationship type on a single property @@ -82,11 +84,8 @@ ON (n.propertyName_1) CREATE TEXT INDEX [index_name] [IF NOT EXISTS] FOR ()-”[“r:TYPE_NAME”]”-() ON (r.propertyName_1) -[OPTIONS “{“ option: value[, …] “}”] ---- -Text indexes have no supported index configuration and they have two index providers available, `text-2.0` (default) and `text-1.0` (deprecated). - [NOTE] It is not possible to create composite text indexes on multiple properties. @@ -113,7 +112,6 @@ ON (r.propertyName_1) [OPTIONS “{“ option: value[, …] “}”] ---- -Point indexes have only one index provider available, `point-1.0`. The following settings can be specified for point indexes: * `spatial.cartesian.min` @@ -133,8 +131,8 @@ For more information, see xref:indexes/search-performance-indexes/managing-index [[create-lookup-index]] === Token lookup indexes -Token lookup indexes have only one index provider, `token-lookup-1.0`, and no supported index configuration. -Since the index provider will be assigned by default, the `OPTIONS` map has been omitted from the syntax below. +Token lookup indexes have no supported index configuration. +The `OPTIONS` map has, therefore, been omitted from the syntax below. .Create a node label lookup index [source,syntax] @@ -177,7 +175,6 @@ ON EACH “[“ r.propertyName[, ...] “]” [OPTIONS “{“ option: value[, …] “}”] ---- -Full-text indexes have only one index provider available, `fulltext-1.0`. The following settings can be specified for full-text indexes: * `fulltext.analyzer` - specifies what analyzer to use (the `db.index.fulltext.listAvailableAnalyzers` procedure lists what analyzers are available). @@ -207,9 +204,6 @@ ON (r.propertyName) [OPTIONS “{“ option: value[, …] “}”] ---- -Vector indexes have two vector index providers available, `vector-2.0` (default) and `vector-1.0`. -For more information, see xref:indexes/semantic-indexes/vector-indexes.adoc#vector-index-providers[Vector index providers for compatibility]. - For a full list of all vector index settings, see xref:indexes/semantic-indexes/vector-indexes.adoc#configuration-settings[Vector index configuration settings]. From 179fa1823b98bb6d884fa4a4477841c84119aea7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Thu, 7 Nov 2024 10:52:33 +0100 Subject: [PATCH 31/77] Update README to include documenting changes to language and GQL (#1100) (#1102) --- README.adoc | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/README.adoc b/README.adoc index a3dfe1c43..eb90de94d 100644 --- a/README.adoc +++ b/README.adoc @@ -1,5 +1,13 @@ = Neo4j Cypher Manual +This page covers the following topics: + +* xref:README.adoc#building-locally[] +* xref:README.adoc#raising-prs[] +* xref:README.adoc#documenting-changes[] +* xref:README.adoc#cypher-gql[] + +[[building-locally]] == Building locally === Prereqs @@ -39,7 +47,7 @@ When you run `npm start`, the project is monitored for updates to asciidoc files If a change to an asciidoc file is detected, the site is automatically rebuilt. - +[[raising-prs]] == Raising PRs @@ -69,3 +77,43 @@ There are a few edge cases where we might want to work only on the current branc ** Create a feature branch from `dev`, to be merged into `dev` when appropriate. * When a new version is ready to published, the `cypher-25` branch will get a git tag, named with the exact version (for example, **2025.01.00**), signifying that this point-in-time marks the completion of the work for that minor release. * Updates merged into the `dev` branch for the next release are cherry-picked into the `cypher-25` branch. + +[[documenting-changes]] +== Documenting changes to Cypher + +New, updated, deprecated, and removed features must be recorded on the xref:modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc[Deprecations, additions, and compatibility] page. + +New and deprecated features should also be marked with a label: + +* If the impacted feature has its own header in the Cypher Manual, use the following: + +.... +[role=label--new-2025.mm] +== Header +.... + +.... +[role=label--deprecated] +== Header +.... + +* If the impacted feature is documented within a table (such as a return column in a `SHOW` command), use the following: + +`featureX` label:new[Introduced in 2025.mm] + +`featureY` label:deprecated[] + +Labels can be difficult to apply to updated features. +In these cases, it is often preferable to note the change in a sentence. +For example: "As of Neo4j 2025.mm, `featureX` supports ..." + +Removed features should be deleted from the Cypher Manual. + +[[cypher-gql]] +== Cypher and GQL + +When documenting a new Cypher feature, its relationship with GQL must be considered: + +* If the feature is part of GQL's mandatory features, it should be recorded on the page xref:modules/ROOT/pages/appendix/gql-conformance/supported-mandatory.adoc[Supported mandatory GQL features]. +* If the feature is part of GQL's optional features, it should be recorded on the page xref:modules/ROOT/pages/appendix/gql-conformance/supported-optional.adoc[Supported optional GQL features]. +* if the feature adds functionality for which there exists an analogous, optional GQL feature, it should be recorded on the page xref:modules/ROOT/pages/appendix/gql-conformance/analogous-cypher.adoc[Optional GQL features and analogous Cypher]. +* If the feature adds functionality for which there exists no GQL equivalent, it should be recorded on the page xref:modules/ROOT/pages/appendix/gql-conformance/additional-cypher.adoc[Additional Cypher features]. From 3c17dadb69167b9d493b06aa200befec682561ec Mon Sep 17 00:00:00 2001 From: Lasse Heemann <7661319+l-heemann@users.noreply.github.com> Date: Fri, 8 Nov 2024 11:57:19 +0100 Subject: [PATCH 32/77] Document the deprecation of the `indexProvider` option (#1101) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `SHOW INDEX ... YIELD createStatement` no longer includes indexProvider - Add note about 5.26 in "Vector index providers for compatibility" --------- Co-authored-by: Jens Pryce-Åklundh <112686610+JPryce-Aklundh@users.noreply.github.com> --- .../managing-indexes.adoc | 36 +++++++++---------- .../semantic-indexes/full-text-indexes.adoc | 14 ++++---- .../semantic-indexes/vector-indexes.adoc | 13 ++++--- 3 files changed, 33 insertions(+), 30 deletions(-) diff --git a/modules/ROOT/pages/indexes/search-performance-indexes/managing-indexes.adoc b/modules/ROOT/pages/indexes/search-performance-indexes/managing-indexes.adoc index 764aacc89..b0e462370 100644 --- a/modules/ROOT/pages/indexes/search-performance-indexes/managing-indexes.adoc +++ b/modules/ROOT/pages/indexes/search-performance-indexes/managing-indexes.adoc @@ -844,24 +844,24 @@ RETURN name, type, provider, options.indexConfig AS config, createStatement .Result [queryresult] ---- -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| name | type | provider | config | createStatement | -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| "composite_range_node_index_name" | "RANGE" | "range-1.0" | {} | "CREATE RANGE INDEX `composite_range_node_index_name` FOR (n:`Person`) ON (n.`age`, n.`country`)" | -| "composite_range_rel_index_name" | "RANGE" | "range-1.0" | {} | "CREATE RANGE INDEX `composite_range_rel_index_name` FOR ()-[r:`PURCHASED`]-() ON (r.`date`, r.`amount`)" | -| "example_index" | "RANGE" | "range-1.0" | {} | "CREATE RANGE INDEX `example_index` FOR (n:`Book`) ON (n.`title`)" | -| "indexOnBooks" | "TEXT" | "text-2.0" | {} | "CREATE TEXT INDEX `indexOnBooks` FOR (n:`Label1`) ON (n.`prop1`) OPTIONS {indexConfig: {}, indexProvider: 'text-2.0'}" | -| "index_343aff4e" | "LOOKUP" | "token-lookup-1.0" | {} | "CREATE LOOKUP INDEX `index_343aff4e` FOR (n) ON EACH labels(n)" | -| "index_f7700477" | "LOOKUP" | "token-lookup-1.0" | {} | "CREATE LOOKUP INDEX `index_f7700477` FOR ()-[r]-() ON EACH type(r)" | -| "node_point_index_name" | "POINT" | "point-1.0" | {`spatial.cartesian.min`: [-1000000.0, -1000000.0], `spatial.wgs-84.min`: [-180.0, -90.0], `spatial.wgs-84.max`: [180.0, 90.0], `spatial.cartesian.max`: [1000000.0, 1000000.0], `spatial.wgs-84-3d.max`: [180.0, 90.0, 1000000.0], `spatial.cartesian-3d.min`: [-1000000.0, -1000000.0, -1000000.0], `spatial.cartesian-3d.max`: [1000000.0, 1000000.0, 1000000.0], `spatial.wgs-84-3d.min`: [-180.0, -90.0, -1000000.0]} | "CREATE POINT INDEX `node_point_index_name` FOR (n:`Person`) ON (n.`sublocation`) OPTIONS {indexConfig: {`spatial.cartesian-3d.max`: [1000000.0, 1000000.0, 1000000.0],`spatial.cartesian-3d.min`: [-1000000.0, -1000000.0, -1000000.0],`spatial.cartesian.max`: [1000000.0, 1000000.0],`spatial.cartesian.min`: [-1000000.0, -1000000.0],`spatial.wgs-84-3d.max`: [180.0, 90.0, 1000000.0],`spatial.wgs-84-3d.min`: [-180.0, -90.0, -1000000.0],`spatial.wgs-84.max`: [180.0, 90.0],`spatial.wgs-84.min`: [-180.0, -90.0]}, indexProvider: 'point-1.0'}" | -| "node_range_index" | "RANGE" | "range-1.0" | {} | "CREATE RANGE INDEX `node_range_index` FOR (n:`Person`) ON (n.`surname`)" | -| "node_text_index_nickname" | "TEXT" | "text-2.0" | {} | "CREATE TEXT INDEX `node_text_index_nickname` FOR (n:`Person`) ON (n.`nickname`) OPTIONS {indexConfig: {}, indexProvider: 'text-2.0'}" | -| "point_index_with_config" | "POINT" | "point-1.0" | {`spatial.cartesian.min`: [-100.0, -100.0], `spatial.wgs-84.min`: [-180.0, -90.0], `spatial.wgs-84.max`: [180.0, 90.0], `spatial.cartesian.max`: [100.0, 100.0], `spatial.wgs-84-3d.max`: [180.0, 90.0, 1000000.0], `spatial.cartesian-3d.min`: [-1000000.0, -1000000.0, -1000000.0], `spatial.cartesian-3d.max`: [1000000.0, 1000000.0, 1000000.0], `spatial.wgs-84-3d.min`: [-180.0, -90.0, -1000000.0]} | "CREATE POINT INDEX `point_index_with_config` FOR (n:`Label`) ON (n.`prop2`) OPTIONS {indexConfig: {`spatial.cartesian-3d.max`: [1000000.0, 1000000.0, 1000000.0],`spatial.cartesian-3d.min`: [-1000000.0, -1000000.0, -1000000.0],`spatial.cartesian.max`: [100.0, 100.0],`spatial.cartesian.min`: [-100.0, -100.0],`spatial.wgs-84-3d.max`: [180.0, 90.0, 1000000.0],`spatial.wgs-84-3d.min`: [-180.0, -90.0, -1000000.0],`spatial.wgs-84.max`: [180.0, 90.0],`spatial.wgs-84.min`: [-180.0, -90.0]}, indexProvider: 'point-1.0'}" | -| "rel_point_index_name" | "POINT" | "point-1.0" | {`spatial.cartesian.min`: [-1000000.0, -1000000.0], `spatial.wgs-84.min`: [-180.0, -90.0], `spatial.wgs-84.max`: [180.0, 90.0], `spatial.cartesian.max`: [1000000.0, 1000000.0], `spatial.wgs-84-3d.max`: [180.0, 90.0, 1000000.0], `spatial.cartesian-3d.min`: [-1000000.0, -1000000.0, -1000000.0], `spatial.cartesian-3d.max`: [1000000.0, 1000000.0, 1000000.0], `spatial.wgs-84-3d.min`: [-180.0, -90.0, -1000000.0]} | "CREATE POINT INDEX `rel_point_index_name` FOR ()-[r:`STREET`]-() ON (r.`intersection`) OPTIONS {indexConfig: {`spatial.cartesian-3d.max`: [1000000.0, 1000000.0, 1000000.0],`spatial.cartesian-3d.min`: [-1000000.0, -1000000.0, -1000000.0],`spatial.cartesian.max`: [1000000.0, 1000000.0],`spatial.cartesian.min`: [-1000000.0, -1000000.0],`spatial.wgs-84-3d.max`: [180.0, 90.0, 1000000.0],`spatial.wgs-84-3d.min`: [-180.0, -90.0, -1000000.0],`spatial.wgs-84.max`: [180.0, 90.0],`spatial.wgs-84.min`: [-180.0, -90.0]}, indexProvider: 'point-1.0'}" | -| "rel_range_index_name" | "RANGE" | "range-1.0" | {} | "CREATE RANGE INDEX `rel_range_index_name` FOR ()-[r:`KNOWS`]-() ON (r.`since`)" | -| "rel_text_index_name" | "TEXT" | "text-2.0" | {} | "CREATE TEXT INDEX `rel_text_index_name` FOR ()-[r:`KNOWS`]-() ON (r.`interest`) OPTIONS {indexConfig: {}, indexProvider: 'text-2.0'}" | -| "uniqueBookIsbn" | "RANGE" | "range-1.0" | {} | "CREATE CONSTRAINT `uniqueBookIsbn` FOR (n:`Book`) REQUIRE (n.`isbn`) IS UNIQUE OPTIONS {indexConfig: {}, indexProvider: 'range-1.0'}" | -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| name | type | provider | config | createStatement | ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| "composite_range_node_index_name" | "RANGE" | "range-1.0" | {} | "CREATE RANGE INDEX `composite_range_node_index_name` FOR (n:`Person`) ON (n.`age`, n.`country`)" | +| "composite_range_rel_index_name" | "RANGE" | "range-1.0" | {} | "CREATE RANGE INDEX `composite_range_rel_index_name` FOR ()-[r:`PURCHASED`]-() ON (r.`date`, r.`amount`)" | +| "example_index" | "RANGE" | "range-1.0" | {} | "CREATE RANGE INDEX `example_index` FOR (n:`Book`) ON (n.`title`)" | +| "indexOnBooks" | "TEXT" | "text-2.0" | {} | "CREATE TEXT INDEX `indexOnBooks` FOR (n:`Label1`) ON (n.`prop1`)" | +| "index_343aff4e" | "LOOKUP" | "token-lookup-1.0" | {} | "CREATE LOOKUP INDEX `index_343aff4e` FOR (n) ON EACH labels(n)" | +| "index_f7700477" | "LOOKUP" | "token-lookup-1.0" | {} | "CREATE LOOKUP INDEX `index_f7700477` FOR ()-[r]-() ON EACH type(r)" | +| "node_point_index_name" | "POINT" | "point-1.0" | {`spatial.cartesian.min`: [-1000000.0, -1000000.0], `spatial.wgs-84.min`: [-180.0, -90.0], `spatial.wgs-84.max`: [180.0, 90.0], `spatial.cartesian.max`: [1000000.0, 1000000.0], `spatial.wgs-84-3d.max`: [180.0, 90.0, 1000000.0], `spatial.cartesian-3d.min`: [-1000000.0, -1000000.0, -1000000.0], `spatial.cartesian-3d.max`: [1000000.0, 1000000.0, 1000000.0], `spatial.wgs-84-3d.min`: [-180.0, -90.0, -1000000.0]} | "CREATE POINT INDEX `node_point_index_name` FOR (n:`Person`) ON (n.`sublocation`) OPTIONS {indexConfig: {`spatial.cartesian-3d.max`: [1000000.0, 1000000.0, 1000000.0],`spatial.cartesian-3d.min`: [-1000000.0, -1000000.0, -1000000.0],`spatial.cartesian.max`: [1000000.0, 1000000.0],`spatial.cartesian.min`: [-1000000.0, -1000000.0],`spatial.wgs-84-3d.max`: [180.0, 90.0, 1000000.0],`spatial.wgs-84-3d.min`: [-180.0, -90.0, -1000000.0],`spatial.wgs-84.max`: [180.0, 90.0],`spatial.wgs-84.min`: [-180.0, -90.0]}}" | +| "node_range_index" | "RANGE" | "range-1.0" | {} | "CREATE RANGE INDEX `node_range_index` FOR (n:`Person`) ON (n.`surname`)" | +| "node_text_index_nickname" | "TEXT" | "text-2.0" | {} | "CREATE TEXT INDEX `node_text_index_nickname` FOR (n:`Person`) ON (n.`nickname`)" | +| "point_index_with_config" | "POINT" | "point-1.0" | {`spatial.cartesian.min`: [-100.0, -100.0], `spatial.wgs-84.min`: [-180.0, -90.0], `spatial.wgs-84.max`: [180.0, 90.0], `spatial.cartesian.max`: [100.0, 100.0], `spatial.wgs-84-3d.max`: [180.0, 90.0, 1000000.0], `spatial.cartesian-3d.min`: [-1000000.0, -1000000.0, -1000000.0], `spatial.cartesian-3d.max`: [1000000.0, 1000000.0, 1000000.0], `spatial.wgs-84-3d.min`: [-180.0, -90.0, -1000000.0]} | "CREATE POINT INDEX `point_index_with_config` FOR (n:`Label`) ON (n.`prop2`) OPTIONS {indexConfig: {`spatial.cartesian-3d.max`: [1000000.0, 1000000.0, 1000000.0],`spatial.cartesian-3d.min`: [-1000000.0, -1000000.0, -1000000.0],`spatial.cartesian.max`: [100.0, 100.0],`spatial.cartesian.min`: [-100.0, -100.0],`spatial.wgs-84-3d.max`: [180.0, 90.0, 1000000.0],`spatial.wgs-84-3d.min`: [-180.0, -90.0, -1000000.0],`spatial.wgs-84.max`: [180.0, 90.0],`spatial.wgs-84.min`: [-180.0, -90.0]}}" | +| "rel_point_index_name" | "POINT" | "point-1.0" | {`spatial.cartesian.min`: [-1000000.0, -1000000.0], `spatial.wgs-84.min`: [-180.0, -90.0], `spatial.wgs-84.max`: [180.0, 90.0], `spatial.cartesian.max`: [1000000.0, 1000000.0], `spatial.wgs-84-3d.max`: [180.0, 90.0, 1000000.0], `spatial.cartesian-3d.min`: [-1000000.0, -1000000.0, -1000000.0], `spatial.cartesian-3d.max`: [1000000.0, 1000000.0, 1000000.0], `spatial.wgs-84-3d.min`: [-180.0, -90.0, -1000000.0]} | "CREATE POINT INDEX `rel_point_index_name` FOR ()-[r:`STREET`]-() ON (r.`intersection`) OPTIONS {indexConfig: {`spatial.cartesian-3d.max`: [1000000.0, 1000000.0, 1000000.0],`spatial.cartesian-3d.min`: [-1000000.0, -1000000.0, -1000000.0],`spatial.cartesian.max`: [1000000.0, 1000000.0],`spatial.cartesian.min`: [-1000000.0, -1000000.0],`spatial.wgs-84-3d.max`: [180.0, 90.0, 1000000.0],`spatial.wgs-84-3d.min`: [-180.0, -90.0, -1000000.0],`spatial.wgs-84.max`: [180.0, 90.0],`spatial.wgs-84.min`: [-180.0, -90.0]}}" | +| "rel_range_index_name" | "RANGE" | "range-1.0" | {} | "CREATE RANGE INDEX `rel_range_index_name` FOR ()-[r:`KNOWS`]-() ON (r.`since`)" | +| "rel_text_index_name" | "TEXT" | "text-2.0" | {} | "CREATE TEXT INDEX `rel_text_index_name` FOR ()-[r:`KNOWS`]-() ON (r.`interest`)" | +| "uniqueBookIsbn" | "RANGE" | "range-1.0" | {} | "CREATE CONSTRAINT `uniqueBookIsbn` FOR (n:`Book`) REQUIRE (n.`isbn`) IS UNIQUE" | ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ---- Note that `YIELD` is mandatory if the `RETURN` clause is used. diff --git a/modules/ROOT/pages/indexes/semantic-indexes/full-text-indexes.adoc b/modules/ROOT/pages/indexes/semantic-indexes/full-text-indexes.adoc index 0dca5ae71..85a612075 100644 --- a/modules/ROOT/pages/indexes/semantic-indexes/full-text-indexes.adoc +++ b/modules/ROOT/pages/indexes/semantic-indexes/full-text-indexes.adoc @@ -326,13 +326,13 @@ SHOW FULLTEXT INDEXES YIELD * .Result ---- -+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| id | name | state | populationPercent | type | entityType | labelsOrTypes | properties | indexProvider | owningConstraint | lastRead | readCount | trackedSince | options | failureMessage | createStatement | -+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 4 | "communications" | "ONLINE" | 100.0 | "FULLTEXT" | "RELATIONSHIP" | ["REVIEWED", "EMAILED"] | ["message"] | "fulltext-1.0" | NULL | NULL | 0 | 2023-11-01T09:27:57.024Z | {indexConfig: {`fulltext.analyzer`: "standard-no-stop-words", `fulltext.eventually_consistent`: FALSE}, indexProvider: "fulltext-1.0"} | "" | "CREATE FULLTEXT INDEX `communications` FOR ()-[r:`REVIEWED`|`EMAILED`]-() ON EACH [r.`message`] OPTIONS {indexConfig: {`fulltext.analyzer`: 'standard-no-stop-words',`fulltext.eventually_consistent`: false}, indexProvider: 'fulltext-1.0'}" | -| 5 | "namesAndTeams" | "ONLINE" | 100.0 | "FULLTEXT" | "NODE" | ["Employee", "Manager"] | ["name", "team"] | "fulltext-1.0" | NULL | NULL | 0 | 2023-11-01T12:24:48.002Z | {indexConfig: {`fulltext.analyzer`: "standard-no-stop-words", `fulltext.eventually_consistent`: FALSE}, indexProvider: "fulltext-1.0"} | "" | "CREATE FULLTEXT INDEX `namesAndTeams` FOR (n:`Employee`|`Manager`) ON EACH [n.`name`, n.`team`] OPTIONS {indexConfig: {`fulltext.analyzer`: 'standard-no-stop-words',`fulltext.eventually_consistent`: false}, indexProvider: 'fulltext-1.0'}" | -| 6 | "peerReviews" | "ONLINE" | 100.0 | "FULLTEXT" | "NODE" | ["Employee", "Manager"] | ["peerReviews"] | "fulltext-1.0" | NULL | NULL | 0 | 2023-11-01T12:25:41.495Z | {indexConfig: {`fulltext.analyzer`: "english", `fulltext.eventually_consistent`: TRUE}, indexProvider: "fulltext-1.0"} | "" | "CREATE FULLTEXT INDEX `peerReviews` FOR (n:`Employee`|`Manager`) ON EACH [n.`peerReviews`] OPTIONS {indexConfig: {`fulltext.analyzer`: 'english',`fulltext.eventually_consistent`: true}, indexProvider: 'fulltext-1.0'}" | -+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| id | name | state | populationPercent | type | entityType | labelsOrTypes | properties | indexProvider | owningConstraint | lastRead | readCount | trackedSince | options | failureMessage | createStatement | ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 4 | "communications" | "ONLINE" | 100.0 | "FULLTEXT" | "RELATIONSHIP" | ["REVIEWED", "EMAILED"] | ["message"] | "fulltext-1.0" | NULL | NULL | 0 | 2023-11-01T09:27:57.024Z | {indexConfig: {`fulltext.analyzer`: "standard-no-stop-words", `fulltext.eventually_consistent`: FALSE}} | "" | "CREATE FULLTEXT INDEX `communications` FOR ()-[r:`REVIEWED`|`EMAILED`]-() ON EACH [r.`message`] OPTIONS {indexConfig: {`fulltext.analyzer`: 'standard-no-stop-words',`fulltext.eventually_consistent`: false}}" | +| 5 | "namesAndTeams" | "ONLINE" | 100.0 | "FULLTEXT" | "NODE" | ["Employee", "Manager"] | ["name", "team"] | "fulltext-1.0" | NULL | NULL | 0 | 2023-11-01T12:24:48.002Z | {indexConfig: {`fulltext.analyzer`: "standard-no-stop-words", `fulltext.eventually_consistent`: FALSE}} | "" | "CREATE FULLTEXT INDEX `namesAndTeams` FOR (n:`Employee`|`Manager`) ON EACH [n.`name`, n.`team`] OPTIONS {indexConfig: {`fulltext.analyzer`: 'standard-no-stop-words',`fulltext.eventually_consistent`: false}}" | +| 6 | "peerReviews" | "ONLINE" | 100.0 | "FULLTEXT" | "NODE" | ["Employee", "Manager"] | ["peerReviews"] | "fulltext-1.0" | NULL | NULL | 0 | 2023-11-01T12:25:41.495Z | {indexConfig: {`fulltext.analyzer`: "english", `fulltext.eventually_consistent`: TRUE}} | "" | "CREATE FULLTEXT INDEX `peerReviews` FOR (n:`Employee`|`Manager`) ON EACH [n.`peerReviews`] OPTIONS {indexConfig: {`fulltext.analyzer`: 'english',`fulltext.eventually_consistent`: true}}" | ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ---- For a full description of all return columns, see xref:indexes/search-performance-indexes/managing-indexes.adoc#listing-indexes-result-columns[Search-performance indexes -> Result columns for listing indexes]. diff --git a/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc b/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc index dd7701427..fe045b75d 100644 --- a/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc +++ b/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc @@ -294,11 +294,11 @@ SHOW VECTOR INDEXES YIELD * .Result [source, role=queryresult] ---- -+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| id | name | state | populationPercent | type | entityType | labelsOrTypes | properties | indexProvider | owningConstraint| lastRead | readCount | trackedSince | options | failureMessage | createStatement | -+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 2 | "moviePlots"| "ONLINE" | 100.0 | "VECTOR" | "NODE" | ["Movie"] | ["embedding"] | "vector-2.0" | NULL | 2024-05-07T09:19:09.225Z | 47 | 2024-05-07T08:26:19.072Z | {indexConfig: {indexConfig: {`vector.dimensions`: 1536, `vector.hnsw.m`: 16, `vector.quantization.enabled`: TRUE, `vector.similarity_function`: "COSINE", `vector.hnsw.ef_construction`: 100}, indexProvider: "vector-2.0"}, indexProvider: "vector-2.0"} | "" | "CREATE VECTOR INDEX `moviePlots` FOR (n:`Movie`) ON (n.`embedding`) OPTIONS {indexConfig: {`vector.dimensions`: 1536,`vector.hnsw.ef_construction`: 100,`vector.hnsw.m`: 16,`vector.quantization.enabled`: true,`vector.similarity_function`: 'COSINE'}, indexProvider: 'vector-2.0'}" | -+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| id | name | state | populationPercent | type | entityType | labelsOrTypes | properties | indexProvider | owningConstraint| lastRead | readCount | trackedSince | options | failureMessage | createStatement | ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 2 | "moviePlots"| "ONLINE" | 100.0 | "VECTOR" | "NODE" | ["Movie"] | ["embedding"] | "vector-2.0" | NULL | 2024-05-07T09:19:09.225Z | 47 | 2024-05-07T08:26:19.072Z | {indexConfig: {`vector.dimensions`: 1536, `vector.hnsw.m`: 16, `vector.quantization.enabled`: TRUE, `vector.similarity_function`: "COSINE", `vector.hnsw.ef_construction`: 100}, indexProvider: "vector-2.0"} | "" | "CREATE VECTOR INDEX `moviePlots` FOR (n:`Movie`) ON (n.`embedding`) OPTIONS {indexConfig: {`vector.dimensions`: 1536,`vector.hnsw.ef_construction`: 100,`vector.hnsw.m`: 16,`vector.quantization.enabled`: true,`vector.similarity_function`: 'COSINE'}}" | ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ---- To return only specific details, specify the desired column name(s) after the `YIELD` clause. @@ -339,6 +339,9 @@ DROP INDEX moviePlots == Vector index providers for compatibility As of Neo4j 5.18, the default index provider is `vector-2.0`. +As of Neo4j 5.26, it is no longer possible to specify an index provider when creating indexes. +Instead, Neo4j selects the most performant provider (currently `vector-2.0`). + Previously created `vector-1.0` indexes will continue to function. .Learn more about vector index provider differences From 220046a37515e2ee17094dd60e172c733fae366e Mon Sep 17 00:00:00 2001 From: Mark Dixon <1756429+mnd999@users.noreply.github.com> Date: Mon, 11 Nov 2024 08:23:02 +0000 Subject: [PATCH 33/77] Further deprecations to options in CREATE DATABASE (#1083) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Deprecate seedCredentials and seedConfig options without a (language) replacement. * Deprecate standard and high_limit store formats - [x] Still waiting on information from cluster as to how to do seeding from buckets now. Depends on: https://github.com/neo4j/docs-operations/pull/1909 --------- Co-authored-by: Therese Magnusson Co-authored-by: Jens Pryce-Åklundh <112686610+JPryce-Aklundh@users.noreply.github.com> --- ...ions-additions-removals-compatibility.adoc | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index 07c832fed..6ae323664 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -244,6 +244,30 @@ a| The column `propertyTypes` currently returned by the procedures link:{neo4j-docs-base-uri}/operations-manual/{page-version}/procedures/#procedure_db_schema_nodetypeproperties[`db.schema.nodeTypeProperties()`] and link:{neo4j-docs-base-uri}/operations-manual/{page-version}/procedures/#procedure_db_schema_reltypeproperties[`db.schema.relTypeProperties()`] produces a list of strings representing the potential Java types for a given property. In an upcoming major release of Neo4j, this will be updated to represent the possible Cypher types for that property instead. For all available Cypher types, see the section on xref::values-and-types/property-structural-constructed.adoc#types-synonyms[types and their synonyms]. + +a| +label:functionality[] +label:deprecated[] +[source, cypher, role="noheader"] +---- +CREATE DATABASE db OPTIONS { seedCredentials: ..., seedConfig: ... } +---- +| The `CREATE DATABASE` option `seedCredentials` has been deprecated. +For seeding from cloud storage, it is recommended to use `CloudSeedProvider` which will read cloud credentials and configuration from standard locations. +For further information, see link:{neo4j-docs-base-uri}/operations-manual/{page-version}/clustering/databases/#cloud-seed-provider[Managing databases in a cluster -> CloudSeedProvider]. + +a| +label:functionality[] +label:deprecated[] +[source, cypher, role="noheader"] +---- +CREATE DATABASE db OPTIONS { storeFormat: 'standard' } + +CREATE DATABASE db OPTIONS { storeFormat: 'high_limit' } +---- +| The `standard` and `high_limit` store formats have been deprecated. +Creating databases with these formats is therefore also deprecated. +For more information on the deprecation of these formats, see link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-internals/store-formats/#format-deprecations[Store formats -> Format deprecations]. |=== From 7056849bf5e1ffa7c6d16aba46fd71b52fa78b66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Mon, 11 Nov 2024 09:49:24 +0100 Subject: [PATCH 34/77] Change SHOW SETTINGS filter query example (#1103) --- .../ROOT/pages/clauses/listing-settings.adoc | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/modules/ROOT/pages/clauses/listing-settings.adoc b/modules/ROOT/pages/clauses/listing-settings.adoc index ab6da6766..95bea97a7 100644 --- a/modules/ROOT/pages/clauses/listing-settings.adoc +++ b/modules/ROOT/pages/clauses/listing-settings.adoc @@ -180,13 +180,13 @@ For a full list of all available settings in Neo4j, refer to link:{neo4j-docs-ba == Listing settings with filtering on output columns The listed settings can be filtered by using the `WHERE` clause. -For example, the following query returns the name, value, and description of the first three settings starting with 'dbms': +For example, the following query returns the name, value, and description of the first three settings starting with 'server': .Query [source, cypher] ---- SHOW SETTINGS YIELD name, value, description -WHERE name STARTS WITH 'dbms' +WHERE name STARTS WITH 'server' RETURN name, value, description LIMIT 3 ---- @@ -196,17 +196,17 @@ LIMIT 3 |=== | name | value | description -| "dbms.cluster.catchup.client_inactivity_timeout" -| "10m" -| "The catchup protocol times out if the given duration elapses with no network activity. Every message received by the client from the server extends the timeout duration." +| "server.backup.enabled" +| "true" +| "Enable support for running online backups." -| "dbms.cluster.discovery.endpoints" -| null -| "A comma-separated list of endpoints that a server should contact in order to discover other cluster members. Typically, all cluster members, including the current server, must be specified in this list. The setting configures the endpoints for Discovery service V1." +| "server.backup.exec_connector.command" +| "" +| "Command to execute for ExecDataConnector list" -| "dbms.cluster.discovery.log_level" -| "WARN" -| "The level of middleware logging." +| "server.backup.exec_connector.scheme" +| "" +| "Schemes ExecDataConnector will match on" 3+d|Rows: 3 |=== From bbdd15347e06b85ab7ad9bbb3c03abad353db48c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Mon, 11 Nov 2024 13:12:26 +0100 Subject: [PATCH 35/77] Explain return values from vector functions (#1104) --- modules/ROOT/pages/functions/vector.adoc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/ROOT/pages/functions/vector.adoc b/modules/ROOT/pages/functions/vector.adoc index 467c4b80d..7664ae28a 100644 --- a/modules/ROOT/pages/functions/vector.adoc +++ b/modules/ROOT/pages/functions/vector.adoc @@ -34,6 +34,8 @@ For more details, see the {link-vector-indexes}#similarity-functions[vector inde | Both vectors must be of the same dimension. | Both vectors must be {link-vector-indexes}#indexes-vector-similarity-cosine[*valid*] with respect to cosine similarity. | The implementation is identical to that of the latest available vector index provider (`vector-2.0`). +| `vector.similarity.cosine()` returns the neighborhood of nodes along with their respective cosine similarity scores, sorted in descending order of similarity. +The similarity score range from `0` and `1`, with scores closer to `1` indicating a higher degree of similarity between the indexed vector and the query vector. |=== @@ -62,6 +64,8 @@ For more details, see the {link-vector-indexes}#similarity-functions[vector inde | Both vectors must be of the same dimension. | Both vectors must be {link-vector-indexes}#indexes-vector-similarity-euclidean[*valid*] with respect to Euclidean similarity. | The implementation is identical to that of the latest available vector index provider (`vector-2.0`). +| `vector.similarity.euclidean()` returns the neighborhood of nodes along with their respective Euclidean similarity scores, sorted in descending order of similarity. +The similarity score range from `0` and `1`, with scores closer to `1` indicating a higher degree of similarity between the indexed vector and the query vector. |=== From d43f3c481b19dfdc1371162380aa84eadbc3df86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Mon, 11 Nov 2024 13:32:37 +0100 Subject: [PATCH 36/77] fix xref on LOAD CSV page (#1107) --- modules/ROOT/pages/clauses/load-csv.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ROOT/pages/clauses/load-csv.adoc b/modules/ROOT/pages/clauses/load-csv.adoc index 3f17dc8cb..b35b5281b 100644 --- a/modules/ROOT/pages/clauses/load-csv.adoc +++ b/modules/ROOT/pages/clauses/load-csv.adoc @@ -175,7 +175,7 @@ You can import data from a number of different cloud storages: * xref:clauses/load-csv.adoc#azure-cloud-storage[Azure Cloud Storage] * xref:clauses/load-csv.adoc#google-cloud-storage[Google Cloud Storage] -* ref:clauses/load-csv.adoc#aws-s3[AWS S3] +* xref:clauses/load-csv.adoc#aws-s3[AWS S3] See link:{neo4j-docs-base-uri}/operations-manual/current/backup-restore/restore-dump/#load-dump-cloud-storage[Operations Manual -> Load a dump from a cloud storage] on how to set up access to cloud storages. From af6ea303f43a9b96afb65066449113b6f8de63c5 Mon Sep 17 00:00:00 2001 From: NataliaIvakina <82437520+NataliaIvakina@users.noreply.github.com> Date: Mon, 11 Nov 2024 14:37:03 +0100 Subject: [PATCH 37/77] Fix links to the Operations manual (#1106) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jens Pryce-Åklundh <112686610+JPryce-Aklundh@users.noreply.github.com> --- .../pages/deprecations-additions-removals-compatibility.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index 6ae323664..6fee56ce3 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -318,7 +318,7 @@ label:deprecated[] ---- CREATE DATABASE db OPTIONS { existingDataSeedInstance: ... } ---- -| The `CREATE DATABASE` option `existingDataSeedInstance` has been deprecated and replaced with the option link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/standard-databases/create-database/#manage-databases-create-database-options[`existingDataSeedServer`]. The functionality is unchanged. +| The `CREATE DATABASE` option `existingDataSeedInstance` has been deprecated and replaced with the option link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/standard-databases/create-databases/#manage-databases-create-database-options[`existingDataSeedServer`]. The functionality is unchanged. |=== === Updated features @@ -356,7 +356,7 @@ label:new[] ---- CREATE DATABASE db OPTIONS { existingDataSeedServer: ... } ---- -| The option link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/standard-databases/create-database/#manage-databases-create-database-options[`existingDataSeedServer`] has been added to `CREATE DATABASE`. The functionality is the same as the deprecated option `existingDataSeedServer`, which this replaces. +| The option link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/standard-databases/create-databases/#manage-databases-create-database-options[`existingDataSeedServer`] has been added to `CREATE DATABASE`. The functionality is the same as the deprecated option `existingDataSeedServer`, which this replaces. |=== [[cypher-deprecations-additions-removals-5.24]] From 67b46108f9250f80578149ac590065bd015fe3d9 Mon Sep 17 00:00:00 2001 From: Mark Dixon <1756429+mnd999@users.noreply.github.com> Date: Thu, 14 Nov 2024 12:50:35 +0000 Subject: [PATCH 38/77] Document old deprecation for database naming (#1105) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Database names containing `.` have been deprecated since 5.0, and this has been documented in the operations manual. Document it here also for consistency. Co-authored-by: Jens Pryce-Åklundh <112686610+JPryce-Aklundh@users.noreply.github.com> --- modules/ROOT/pages/syntax/naming.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/ROOT/pages/syntax/naming.adoc b/modules/ROOT/pages/syntax/naming.adoc index 7f812d2b0..93bf90654 100644 --- a/modules/ROOT/pages/syntax/naming.adoc +++ b/modules/ROOT/pages/syntax/naming.adoc @@ -27,8 +27,8 @@ For example, `MATCH ( a ) RETURN a` is equivalent to `MATCH (a) RETURN a`. === Using special characters in names Non-alphabetic characters, including numbers, symbols and whitespace characters, *can* be used in names, but *must* be escaped using backticks. For example: `++`^n`++`, `++`1first`++`, `++`$$n`++`, and `++`my variable has spaces`++`. -Database names are an exception and may include dots without the need for escaping. -For example: naming a database `foo.bar.baz` is perfectly valid. +Database names are an exception and may include dots without the need for escaping, although this behavior is deprecated as it may introduce ambiguity when addressing composite databases. +For example: naming a database `foo.bar.baz` is valid, but deprecated. `++`foo.bar.baz`++` is valid. Within an escaped name, the following escaping sequences are allowed: From e5c832dea35a08ec8365175ea324bcbe8d18897c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Thu, 14 Nov 2024 16:00:10 +0100 Subject: [PATCH 39/77] use quote in backticks rather than escape (#1111) Ops Manual PR: https://github.com/neo4j/docs-operations/pull/1959 --- ...ions-additions-removals-compatibility.adoc | 28 +++++++++---------- modules/ROOT/pages/styleguide.adoc | 2 +- modules/ROOT/pages/syntax/naming.adoc | 10 +++---- modules/ROOT/pages/syntax/reserved.adoc | 2 +- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index 6fee56ce3..2d3c5dcd8 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -167,8 +167,8 @@ MATCH (where {...}) ---- MATCH (...)-[where {...}]->() ---- -a| The unescaped variable named `where` (or any casing variant, like `WHERE`) used in a node or relationship pattern followed directly by a property key-value expression is deprecated. -To continue using variables with this name, use backticks to escape the variable name: +a| The variable named `where` (or any casing variant, like `WHERE`) used in a node or relationship pattern followed directly by a property key-value expression is deprecated. +To continue using variables with this name, use backticks to quote the variable name: * Node patterns: `MATCH (++`where`++ { ... })` * Relationship patterns: `MATCH (...)-[++`where`++ { ... }]->()` @@ -196,8 +196,8 @@ label:deprecated[] ---- CASE x ... WHEN is :: STRING THEN ... END ---- -a| Using an unescaped variable named `is` (or any casing variant, like `IS`) as a `WHEN` operand in a xref:queries/case.adoc#case-simple[simple `CASE`] expression is deprecated. -To continue using variables with this name in simple `CASE` expressions, use backticks to escape the variable name: `CASE x ... WHEN ++`is`++ :: STRING THEN ... END` +a| Using a variable named `is` (or any casing variant, like `IS`) as a `WHEN` operand in a xref:queries/case.adoc#case-simple[simple `CASE`] expression is deprecated. +To continue using variables with this name in simple `CASE` expressions, use backticks to quote the variable name: `CASE x ... WHEN ++`is`++ :: STRING THEN ... END` a| label:functionality[] @@ -209,8 +209,8 @@ CASE x ... WHEN contains + 1 THEN ... END ---- CASE x ... WHEN contains - 1 THEN ... END ---- -a| Using an unescaped variable named `contains` (or any casing variant, like `CONTAINS`) in addition or subtraction operations within a `WHEN` operand of a xref:queries/case.adoc#case-simple[simple `CASE`] expression is deprecated. -To continue using variables with this name, use backticks to escape the variable name: +a| Using a variable named `contains` (or any casing variant, like `CONTAINS`) in addition or subtraction operations within a `WHEN` operand of a xref:queries/case.adoc#case-simple[simple `CASE`] expression is deprecated. +To continue using variables with this name, use backticks to quote the variable name: * Additions: `CASE x ... WHEN ++`contains`++ + 1 THEN ... END` * Subtractions: `CASE x ... WHEN ++`contains`++ - 1 THEN ... END` @@ -225,8 +225,8 @@ CASE x ... WHEN in[1] THEN ... END ---- CASE x ... WHEN in["abc"] THEN ... END ---- -a| Using the `[]` operator on an unescaped variable named `in` (or any casing variant, like `IN`) within a `WHEN` operand of a xref:queries/case.adoc#case-simple[simple `CASE`] expression is deprecated. -To continue using variables with this name, use backticks to escape the variable name: +a| Using the `[]` operator on a variable named `in` (or any casing variant, like `IN`) within a `WHEN` operand of a xref:queries/case.adoc#case-simple[simple `CASE`] expression is deprecated. +To continue using variables with this name, use backticks to quote the variable name: * `CASE x ... WHEN ++`in`++[1] THEN ... END` * `CASE x ... WHEN ++`in`++["abc"] THEN ... END` @@ -1117,9 +1117,9 @@ label:deprecated[] RETURN 1 as my\u0085identifier ---- a| -The Unicode character \`\u0085` is deprecated for unescaped identifiers and will be considered as a whitespace character in the future. -To continue using it, escape the identifier by adding backticks around the identifier. -This applies to all unescaped identifiers in Cypher, such as label expressions, properties, variable names or parameters. +The Unicode character \`\u0085` is deprecated for identifiers not quoted in backticks and will be considered as a whitespace character in the future. +To continue using it, quote the identifier with backticks. +This applies to all identifiers in Cypher, such as label expressions, properties, variable names or parameters. In the given example, the quoted identifier would be \`my�identifier`. a| @@ -1130,8 +1130,8 @@ label:deprecated[] RETURN 1 as my$Identifier ---- a| -The character with the Unicode representation \`\u0024` is deprecated for unescaped identifiers and will not be supported in the future. To continue using it, escape the identifier by adding backticks around the identifier. -This applies to all unescaped identifiers in Cypher, such as label expressions, properties, variable names or parameters. In the given example, the quoted identifier would be \`my$identifier`. +The character with the Unicode representation \`\u0024` is deprecated for identifiers not quoted in backticks and will not be supported in the future. To continue using it, quote the identifier with backticks. +This applies to all identifiers in Cypher, such as label expressions, properties, variable names or parameters. In the given example, the quoted identifier would be \`my$identifier`. The following Unicode Characters are deprecated in identifiers: '\u0000', '\u0001', '\u0002', '\u0003', '\u0004', '\u0005', '\u0006', '\u0007', @@ -2799,7 +2799,7 @@ label:deprecated[] CREATE DATABASE databaseName.withDot ... ---- a| -Creating a database with unescaped dots in the name has been deprecated, instead escape the database name: +Creating a database with dots in the name has been deprecated, instead quote the database name using backticks: [source, cypher, role="noheader"] ---- diff --git a/modules/ROOT/pages/styleguide.adoc b/modules/ROOT/pages/styleguide.adoc index 0874703f7..bff296f2e 100644 --- a/modules/ROOT/pages/styleguide.adoc +++ b/modules/ROOT/pages/styleguide.adoc @@ -472,7 +472,7 @@ RETURN 'Cypher\'s a nice language', "Mats' quote: \"statement\"" RETURN "Cypher's a nice language", 'Mats\' quote: "statement"' ---- -* Avoid having to use back-ticks to escape characters and keywords. +* Avoid using characters and keywords that require the input to be quoted with backticks. .Bad [source, cypher] diff --git a/modules/ROOT/pages/syntax/naming.adoc b/modules/ROOT/pages/syntax/naming.adoc index 93bf90654..6960d1491 100644 --- a/modules/ROOT/pages/syntax/naming.adoc +++ b/modules/ROOT/pages/syntax/naming.adoc @@ -25,23 +25,23 @@ For example, `MATCH ( a ) RETURN a` is equivalent to `MATCH (a) RETURN a`. [[symbolic-names-escaping-rules]] === Using special characters in names -Non-alphabetic characters, including numbers, symbols and whitespace characters, *can* be used in names, but *must* be escaped using backticks. +Non-alphabetic characters, including numbers, symbols and whitespace characters, *can* be used in names, but *must* be quoted using backticks. For example: `++`^n`++`, `++`1first`++`, `++`$$n`++`, and `++`my variable has spaces`++`. -Database names are an exception and may include dots without the need for escaping, although this behavior is deprecated as it may introduce ambiguity when addressing composite databases. +Database names are an exception and may include dots without the need for quoting using backticks, although this behavior is deprecated as it may introduce ambiguity when addressing composite databases. For example: naming a database `foo.bar.baz` is valid, but deprecated. `++`foo.bar.baz`++` is valid. -Within an escaped name, the following escaping sequences are allowed: +Within a name quoted by backticks, the following character representations are allowed: [options="header", cols=">1,<2"] |=== -|Escape sequence|Character +| Character representation | Description |````| Backtick |`\uxxxx`| Unicode UTF-16 code point (4 hex digits must follow the `\u`) |=== [NOTE] ==== -Using escaped names with unsanitized user input makes you vulnerable to Cypher injection. +Using names quoted in backticks with unsanitized user input makes you vulnerable to Cypher injection. Some techniques to mitigate this are: * sanitizing (and validating) the user input. diff --git a/modules/ROOT/pages/syntax/reserved.adoc b/modules/ROOT/pages/syntax/reserved.adoc index e38ba0ed2..fe298c19b 100644 --- a/modules/ROOT/pages/syntax/reserved.adoc +++ b/modules/ROOT/pages/syntax/reserved.adoc @@ -16,7 +16,7 @@ The reserved keywords are not permitted to be used as identifiers in the followi * Function names * Parameters -If any reserved keyword is escaped -- i.e. is encapsulated by backticks ```, such as `++`AND`++` -- it would become a valid identifier in the above contexts. +If any reserved keyword is quoted in backticks (```), such as `++`AND`++`, it would become a valid identifier in the above contexts; however, this approach is not recommended. == Clauses From 366712279acef5630ba601325385033c7352c729 Mon Sep 17 00:00:00 2001 From: juantoser <136793699+juantoser@users.noreply.github.com> Date: Fri, 15 Nov 2024 09:24:26 +0100 Subject: [PATCH 40/77] Typo fix (#1110) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jens Pryce-Åklundh <112686610+JPryce-Aklundh@users.noreply.github.com> --- modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc b/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc index 1a6664bb5..b2eb52351 100644 --- a/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc +++ b/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc @@ -664,7 +664,7 @@ If so, the impacted transactions are always rolled back, and an error is thrown ==== The following query tries to create `Movie` and `Year` nodes connected by a `RELEASED_IN` relationship. -Note that there are only three different years in the CSV file, meaning hat only three `Year` nodes should be created. +Note that there are only three different years in the CSV file, meaning that only three `Year` nodes should be created. .Query with concurrent transaction causing a deadlock [source, cypher, role=test-fail] From 562f0722cb016818bb64d95d21a8acca06ec179c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Tue, 19 Nov 2024 15:04:21 +0100 Subject: [PATCH 41/77] Cypher 25 Dynamic labels/types (#1114) Co-authored-by: Stefano Ottolenghi --- modules/ROOT/images/graph_match_clause.svg | 2 +- .../gql-conformance/additional-cypher.adoc | 87 +++++++++++ modules/ROOT/pages/clauses/create.adoc | 51 ++++++- modules/ROOT/pages/clauses/load-csv.adoc | 39 +++++ modules/ROOT/pages/clauses/match.adoc | 138 +++++++++++++++++- modules/ROOT/pages/clauses/merge.adoc | 56 +++++++ modules/ROOT/pages/clauses/remove.adoc | 16 +- modules/ROOT/pages/clauses/set.adoc | 17 +-- ...ions-additions-removals-compatibility.adoc | 41 +++++- 9 files changed, 420 insertions(+), 27 deletions(-) diff --git a/modules/ROOT/images/graph_match_clause.svg b/modules/ROOT/images/graph_match_clause.svg index d2481798f..393b3fe23 100644 --- a/modules/ROOT/images/graph_match_clause.svg +++ b/modules/ROOT/images/graph_match_clause.svg @@ -1 +1 @@ -DIRECTEDACTED_INrole:'Gordon Gekko'ACTED_INrole:'Carl Fox'ACTED_INrole:'President Andrew Shepherd'ACTED_INrole:'A.J. MacInerney'ACTED_INrole:'Bud Fox'DIRECTEDPersonname:'Oliver Stone'Movietitle:'Wall Street'Personname:'Michael Douglas'Personname:'Martin Sheen'Movietitle:'The American President'Personname:'Charlie Sheen'Personname:'Rob Reiner' +DIRECTEDACTED_INrole:'Gordon Gekko'ACTED_INrole:'Carl Fox'ACTED_INrole:'President Andrew Shepherd'ACTED_INrole:'A.J. MacInerney'ACTED_INrole:'Bud Fox'DIRECTEDPersonDirectorname:'Oliver Stone'Movietitle:'Wall Street'PersonActorname:'Michael Douglas'PersonActorname:'Martin Sheen'Movietitle:'The American President'PersonActorname:'Charlie Sheen'PersonDirectorname:'Rob Reiner' \ No newline at end of file diff --git a/modules/ROOT/pages/appendix/gql-conformance/additional-cypher.adoc b/modules/ROOT/pages/appendix/gql-conformance/additional-cypher.adoc index 46134dceb..837a32330 100644 --- a/modules/ROOT/pages/appendix/gql-conformance/additional-cypher.adoc +++ b/modules/ROOT/pages/appendix/gql-conformance/additional-cypher.adoc @@ -78,6 +78,93 @@ Either the pattern already exists, or it needs to be created. | Syntactic construct for creating a `LIST` based on matchings of a pattern. |=== +[[dynamic-queries]] +== Dynamic queries + +Node labels, relationship types, properties, and CSV columns can be referenced dynamically using Cypher. +This allows for more flexible queries and mitigates the risk of Cypher injection. +(For more information about Cypher injection, see link:https://neo4j.com/developer/kb/protecting-against-cypher-injection/[Neo4j Knowledge Base -> Protecting against Cypher injection]). + +[options="header", cols="2a,5a"] +|=== +| Cypher feature +| Description + +a| +[source, cypher, role="noheader"] +---- +MATCH (n:$($label)), + ()-[r:$($type))]->() +---- + +| xref:clauses/match.adoc#dynamic-match[`MATCH` nodes and relationships using dynamic node labels and relationship types] + +a| +[source, cypher, role="noheader"] +---- +CREATE (n:$($label)), + ()-[r:$($type)]->() +---- + +| xref:clauses/create.adoc#dynamic-create[`CREATE` nodes and relationships using dynamic node labels and relationship types] + +a| +[source, cypher, role="noheader"] +---- +MERGE (n:$($label)), + ()-[r:$($type)]->() +---- + +| xref:clauses/merge.adoc#dynamic-merge[`MERGE` nodes and relationships using dynamic node labels and relationship types] + +a| +[source, cypher, role="noheader"] +---- +LOAD CSV WITH HEADERS FROM 'file:///artists-with-headers.csv' AS line +CREATE (n:$(line.label) {name: line.Name}) +---- + +| xref:clauses/load-csv.adoc#dynamic-columns[Import CSV files using dynamic columns] + + +a| +[source, cypher, role="noheader"] +---- +MATCH (n) +SET n[$key] = value +---- + +| xref:clauses/set.adoc#dynamic-set-property[Dynamically `SET` or update a property] + +a| +[source, cypher, role="noheader"] +---- +MATCH (n:Label) +SET n:$(n.property) +---- + +| xref:clauses/set.adoc#dynamic-set-node-label[Dynamically `SET` a node label] + +a| +[source, cypher, role="noheader"] +---- +MATCH (n {name: 'Peter'}) +REMOVE n:$($label) +---- + +| xref:clauses/remove.adoc#dynamic-remove-property[Dynamically `REMOVE` a property] + +a| +[source, cypher, role="noheader"] +---- +MATCH (n {name: 'Peter'}) +REMOVE n:$($label) +---- + +| xref:clauses/remove.adoc#dynamic-remove-node-label[Dynamically `REMOVE` a node label] + +|=== + [[functions]] == Functions diff --git a/modules/ROOT/pages/clauses/create.adoc b/modules/ROOT/pages/clauses/create.adoc index f27945c18..4f674b8bc 100644 --- a/modules/ROOT/pages/clauses/create.adoc +++ b/modules/ROOT/pages/clauses/create.adoc @@ -205,10 +205,59 @@ Nodes created: 2 + Properties set: 4 |=== +[[dynamic-create]] +== CREATE using dynamic node labels and relationship types + +Node labels and relationship types can be referenced dynamically in expressions, parameters, and variables when creating nodes and relationships. +This allows for more flexible queries and mitigates the risk of Cypher injection. +(For more information about Cypher injection, see link:https://neo4j.com/developer/kb/protecting-against-cypher-injection/[Neo4j Knowledge Base -> Protecting against Cypher injection]). + +.Syntax for creating nodes and relationships dynamically +[source, syntax] +---- +CREATE (n:$()) +CREATE ()-[r:$()]->() +---- + +The expression must evaluate to a `STRING NOT NULL | LIST NOT NULL` value. +Using a `LIST` with more than one item when creating a relationship using dynamic relationship types will fail. +This is because a relationship can only have exactly one type. + +.Parameters +[source, parameters] +---- +{ + "nodeLabels": ["Person", "Director"], + "relType": "DIRECTED", + "movies": ["Ladybird", "Little Women", "Barbie"] +} +---- + +.Create nodes and relationships using dynamic node labels and relationship types +[source, cypher] +---- +CREATE (greta:$($nodeLabels) {name: 'Greta Gerwig'}) +WITH greta +UNWIND $movies AS movieTitle +CREATE (greta)-[rel:$($relType)]->(m:Movie {title: movieTitle}) +RETURN greta.name AS name, labels(greta) AS labels, type(rel) AS relType, collect(m.title) AS movies +---- + +.Result +[role="queryresult",options="footer",cols="4* Protecting against Cypher injection]). + +.bands-with-headers.csv +[source, csv, filename="artists-with-headers.csv"] +---- +Id,Label,Name +1,Band,The Beatles +2,Band,The Rolling Stones +3,Band,Pink Floyd +4,Band,Led Zeppelin +---- + +.Query +[source, cypher, role=test-skip] +---- +LOAD CSV WITH HEADERS FROM 'file:///bands-with-headers.csv' AS line +MERGE (n:$(line.Label) {name: line.Name}) +RETURN n AS bandNodes +---- + +.Result +[role="queryresult",options="header,footer",cols="1*(wallStreet), (martin)-[:ACTED_IN {role: 'Carl Fox'}]->(wallStreet), @@ -124,8 +124,10 @@ The above query uses the xref:functions/list.adoc#functions-labels[`labels()`] a [role="queryresult",options="header,footer",cols="2* Label expressions]. @@ -490,3 +492,125 @@ The above query uses the xref:functions/aggregating.adoc#functions-collect[`coll For more information about how Cypher queries work, see xref:clauses/clause-composition.adoc[]. +[[dynamic-match]] +== MATCH using dynamic node labels and relationship types + +Node labels and relationship types can be referenced dynamically in expressions, parameters, and variables when matching nodes and relationships. +This allows for more flexible queries and mitigates the risk of Cypher injection. +(For more information about Cypher injection, see link:https://neo4j.com/developer/kb/protecting-against-cypher-injection/[Neo4j Knowledge Base -> Protecting against Cypher injection]). + +.Syntax for matching node labels dynamically +[source, syntax] +---- +MATCH (n:$()) +MATCH (n:$any()) +MATCH (n:$all()) +---- + +[NOTE] +`MATCH (n:$all())` is functionally equivalent to `MATCH (n:$())`. + +.Syntax for matching relationship types dynamically +[source, syntax] +---- +MATCH ()-[r:$())]->() +MATCH ()-[r:$any()]->() +MATCH ()-[r:$all())]->() +---- + +The expression must evaluate to a `STRING NOT NULL | LIST NOT NULL` value. +If you use a `LIST` with more than one item in a relationship pattern with dynamic relationship types, no results will be returned. +This is because a relationship can only have exactly one type. + +[NOTE] +Queries using dynamic values may not be as performant as those using static values. +This is because the xref:planning-and-tuning/execution-plans.adoc[Cypher planner] uses statically available information when planning queries to determine whether to use an xref:indexes/search-performance-indexes/overview.adoc[index] or not, and this is not possible when using dynamic values. + +.Match labels dynamically +[source, cypher] +---- +WITH ["Person", "Director"] AS labels +MATCH (directors:$(labels)) +RETURN directors +---- + +.Result +[role="queryresult",options="header,footer",cols="1*() +RETURN relationshipType, count(r) AS relationshipCount +---- + +.Result +[role="queryresult",options="header,footer",cols="2* Protecting against Cypher injection]). + +.Syntax for merging nodes and relationships dynamically +[source, syntax] +---- +MERGE (n:$()) +MERGE ()-[r:$()]->() +---- + +The expression must evaluate to a `STRING NOT NULL | LIST NOT NULL` value. +Using a `LIST` with more than one item when merging a relationship using dynamic relationship types will fail. +This is because a relationship can only have exactly one type. + +[NOTE] +Queries using dynamic values may not be as performant as those using static values. +This is because the xref:planning-and-tuning/execution-plans.adoc[Cypher planner] uses statically available information when planning queries to determine whether to use an xref:indexes/search-performance-indexes/overview.adoc[index] or not, and this is not possible when using dynamic values. + +.Parameters +[source, parameters] +---- +{ + "nodeLabels": ["Person", "Director"], + "relType": "DIRECTED", + "movies": ["Ladybird", "Little Women", "Barbie"] +} +---- + +.Merge nodes and relationships using dynamic node labels and relationship types +[source, cypher] +---- +MERGE (greta:$($nodeLabels) {name: 'Greta Gerwig'}) +WITH greta +UNWIND $movies AS movieTitle +MERGE (greta)-[rel:$($relType)]->(m:Movie {title: movieTitle}) +RETURN greta.name AS name, labels(greta) AS labels, type(rel) AS relType, collect(m.title) AS movies +---- + +.Result +[role="queryresult",options="footer",cols="3* Protecting against Cypher injection]). [source, syntax] ---- @@ -82,7 +83,6 @@ REMOVE n[key] The dynamically calculated key must evaluate to a `STRING` value. This query creates a copy of every property on the nodes: - .Query [source, cypher, indent=0] ---- @@ -130,19 +130,19 @@ RETURN n.name, labels(n) Labels removed: 1 |=== - -[[remove-remove-a-label-dynamically-from-a-node]] -== Dynamically removing a label +[[dynamic-remove-node-label]] +== Dynamically remove a node label `REMOVE` can be used to remove a label on a node even when the label is not statically known. - [source, syntax] ---- MATCH (n) REMOVE n:$(expr) ---- +The expression must evaluate to a `STRING NOT NULL | LIST NOT NULL` value. + .Query [source, cypher, indent=0] ---- diff --git a/modules/ROOT/pages/clauses/set.adoc b/modules/ROOT/pages/clauses/set.adoc index 8f16fd210..f87390304 100644 --- a/modules/ROOT/pages/clauses/set.adoc +++ b/modules/ROOT/pages/clauses/set.adoc @@ -161,11 +161,12 @@ Properties set: 1 |=== - -[[set-dynamically-a-property]] -== Dynamically setting or updating a property +[[dynamic-set-property]] +== Dynamically set or update a property `SET` can be used to set or update a property on a node or relationship even when the property key name is not statically known. +This allows for more flexible queries and mitigates the risk of Cypher injection. +(For more information about Cypher injection, see link:https://neo4j.com/developer/kb/protecting-against-cypher-injection/[Neo4j Knowledge Base -> Protecting against Cypher injection]). [source, syntax] ---- @@ -540,16 +541,15 @@ The newly-labeled node is returned by the query. Labels added: 1 |=== - -[[set-set-a-dynamic-label-on-a-node]] -== Dynamically setting a label +[[dynamic-set-node-label]] +== Dynamically set a node label `SET` can be used to set a label on a node even when the label is not statically known. [source, syntax] ---- MATCH (n) -SET n:$(expr) +SET n:$() ---- .Query @@ -628,8 +628,7 @@ The newly-labeled node is returned by the query. Labels added: 2 |=== - -[[set-set-multiple-dynamic-labels-on-a-node]] +[[dynamic-set-multiple-node-labels]] == Set multiple labels dynamically on a node It is possible to set multiple labels dynamically using a `LIST` and/or by chaining them separately with a `:`: diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index 2d3c5dcd8..780cfaf1f 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -302,6 +302,45 @@ GRANT READ {*} ON GRAPH * FOR (n) WHERE n.createdAt > date('2024-10-25') TO regu |=== +=== New features + +[cols="2", options="header"] +|=== +| Feature +| Details + +a| +label:functionality[] +label:new[] +[source, cypher, role="noheader"] +---- +MATCH (n:$($label)), + ()-[r:$($type))]->() +---- + +[source, cypher, role="noheader"] +---- +CREATE (n:$($label)), + ()-[r:$($type)]->() +---- + +[source, cypher, role="noheader"] +---- +MERGE (n:$($label)), + ()-[r:$($type)]->() +---- + +[source, cypher, role="noheader"] +---- +LOAD CSV WITH HEADERS FROM 'file:///artists-with-headers.csv' AS line +CREATE (n:$(line.label) {name: line.Name}) +---- + +| Added the ability to dynamically reference node labels and relationship types in xref:clauses/match.adoc#dynamic-match[`MATCH`], xref:clauses/create.adoc#dynamic-create[`CREATE`], and xref:clauses/merge.adoc#dynamic-merge[`MERGE`] clauses. +Also introduced the ability to specify CSV columns dynamically when using xref:clauses/load-csv.adoc#dynamic-load[`LOAD CSV`]. +|=== + + [[cypher-deprecations-additions-removals-5.25]] == Neo4j 5.25 @@ -436,7 +475,7 @@ label:new[] SET n[$prop] = "hello world" REMOVE n[$prop] ---- -| Added the ability to dynamically reference properties in xref:clauses/set.adoc#set-dynamically-a-property[SET] and xref:clauses/remove.adoc#remove-remove-a-property-dynamically[REMOVE] clauses. +| Added the ability to dynamically reference properties in xref:clauses/set.adoc#dynamic-set-property[SET] and xref:clauses/remove.adoc#dynamic-remove-property[REMOVE] clauses. a| label:functionality[] From 11dfaceaab27a8c6e33fd1528704acba16ba78b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Tue, 19 Nov 2024 15:11:17 +0100 Subject: [PATCH 42/77] Fix vector config performance suggestion (#1115) --- modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc b/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc index fe045b75d..fc1d93979 100644 --- a/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc +++ b/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc @@ -246,7 +246,7 @@ If you are using a compatible version of Java, you can add the following setting .Configuration settings [source,config] ---- -server.jvm.additional=--add-modules jdk.incubator.vector +server.jvm.additional=--add-modules=jdk.incubator.vector ---- [[show-vector-indexes]] From 0c1fa8845715b97435d699519b1c1d72ccd31203 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Mon, 25 Nov 2024 10:10:25 +0100 Subject: [PATCH 43/77] add complete fulltext stop words and clarify populating state (#1116) --- .../managing-indexes.adoc | 4 +++- .../semantic-indexes/full-text-indexes.adoc | 15 +++++++-------- .../indexes/semantic-indexes/vector-indexes.adoc | 4 ++++ 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/modules/ROOT/pages/indexes/search-performance-indexes/managing-indexes.adoc b/modules/ROOT/pages/indexes/search-performance-indexes/managing-indexes.adoc index b0e462370..82a7a92d6 100644 --- a/modules/ROOT/pages/indexes/search-performance-indexes/managing-indexes.adoc +++ b/modules/ROOT/pages/indexes/search-performance-indexes/managing-indexes.adoc @@ -40,7 +40,9 @@ In those cases, nothing needs to be specified and the `OPTIONS` map should be om [TIP] Creating an index requires link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/database-administration/#access-control-database-administration-index[the `CREATE INDEX` privilege]. -A newly created index is not immediately available but is created in the background. +[NOTE] +An index cannot be used while its `state` is `POPULATING`, which occurs immediately after it is created. +To check the `state` of an index -- whether it is `ONLINE` (usable) or `POPULATING` (still being built; the `populationPercent` column shows the progress of the index creation) -- run the following command: `SHOW INDEXES`. [[create-range-index]] === Create a range index diff --git a/modules/ROOT/pages/indexes/semantic-indexes/full-text-indexes.adoc b/modules/ROOT/pages/indexes/semantic-indexes/full-text-indexes.adoc index 85a612075..50c08ee63 100644 --- a/modules/ROOT/pages/indexes/semantic-indexes/full-text-indexes.adoc +++ b/modules/ROOT/pages/indexes/semantic-indexes/full-text-indexes.adoc @@ -3,7 +3,7 @@ = Full-text indexes A full-text index is used to index nodes and relationships by `STRING` properties. -Unlike xref:indexes/search-performance-indexes/managing-indexes.adoc#indexes-create-range-index[range] and xref:indexes/search-performance-indexes/managing-indexes.adoc#indexes-create-text-index[text] indexes, which can only perform limited `STRING` matching (exact, prefix, substring, or suffix matches), full-text indexes stores individual words in any given `STRING` property. +Unlike xref:indexes/search-performance-indexes/managing-indexes.adoc#create-range-index[range] and xref:indexes/search-performance-indexes/managing-indexes.adoc#create-text-index[text] indexes, which can only perform limited `STRING` matching (exact, prefix, substring, or suffix matches), full-text indexes stores individual words in any given `STRING` property. This means that full-text indexes can be used to match within the _content_ of a `STRING` property. Full-text indexes also return a score of proximity between a given query string and the `STRING` values stored in the database, thus enabling them to semantically interpret data. @@ -83,15 +83,15 @@ The default analyzer (`standard-no-stop-words`) analyzes both the indexed values Stop words are common words in a language that can be filtered out during information retrieval tasks since they are considered to be of little use when determining the meaning of a string. These words are typically short and frequently used across various contexts. -For example, the following stop words are included in Lucene’s english analyzer: "a", "an", "and", "are", "as", "at", "be", "but”, and so on. +For example, the following stop words are included in Lucene’s `english` analyzer: "a", "an", "and", "are", "as", "at", "be", "but", "by", "for", "if", "in", "into", "is", "it", "no", "not", "of", "on", "or", "such", "that", "the", "their", "then", "there", "these", "they", "this", "to", "was", "will", and "with". Removing stop words can help reduce the size of stored data and thereby improve the efficiency of data retrieval. ==== In some cases, using different analyzers for the indexed values and query string is more appropriate. -For example, if handling `STRING` values written in Swedish, it may be beneficial to select the _swedish_ analyzer, which knows how to tokenize Swedish words, and will avoid indexing Swedish stop words. +For example, if handling `STRING` values written in Swedish, it may be beneficial to select the `swedish` analyzer, which knows how to tokenize Swedish words, and will avoid indexing Swedish stop words. -A complete list of all available analyzers is included in the result of the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_index_fulltext_listavailableanalyzers[`db.index.fulltext.listAvailableAnalyzers`] procedure. +The link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_index_fulltext_listavailableanalyzers[`db.index.fulltext.listAvailableAnalyzers()`] procedure shows all available analyzers. Neo4j also supports the use of custom analyzers. For more information, see the link:{neo4j-docs-base-uri}/java-reference/{page-version}/extending-neo4j/full-text-analyzer-provider[Java Reference Manual -> Full-text index analyzer providers]. @@ -133,13 +133,12 @@ For more information on how to configure full-text indexes, refer to the link:{n [[query-full-text-indexes]] == Query full-text indexes +Unlike xref:indexes/search-performance-indexes/managing-indexes.adoc[search-performance indexes], full-text indexes are not automatically used by the xref:planning-and-tuning/execution-plans.adoc[Cypher query planner]. To query a full-text index, use either the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_index_fulltext_querynodes[`db.index.fulltext.queryNodes`] or the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_index_fulltext_relationships[`db.index.fulltext.queryRelationships`] procedure. [NOTE] -==== -Unlike other xref:indexes/search-performance-indexes/managing-indexes.adoc[search-performance indexes], full-text indexes are not automatically used by the xref:planning-and-tuning/execution-plans.adoc[Cypher query planner]. -To access full-text indexes, they must be explicitly called with the above-mentioned procedures. -==== +An index cannot be used while its `state` is `POPULATING`, which occurs immediately after it is created. +To check the `state` of a full-text index -- whether it is `ONLINE` (usable) or `POPULATING` (still being built; the `populationPercent` column shows the progress of the index creation) -- run the following command: `SHOW FULLTEXT INDEXES`. This query uses the `db.index.fulltext.queryNodes` to look for `nils` in the previously created full-text index `namesAndTeams`: diff --git a/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc b/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc index fc1d93979..cbce11432 100644 --- a/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc +++ b/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc @@ -184,6 +184,10 @@ Default value::: `100` To query a node vector index, use the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_index_vector_queryNodes[`db.index.vector.queryNodes`] procedure. +[NOTE] +An index cannot be used while its `state` is `POPULATING`, which occurs immediately after it is created. +To check the `state` of a vector index -- whether it is `ONLINE` (usable) or `POPULATING` (still being built; the `populationPercent` column shows the progress of the index creation) -- run the following command: `SHOW VECTOR INDEXES`. + .Signature for `db.index.vector.queryNodes` [source,syntax] ---- From e5158f196cd388869b1574bebb9545ee62cdd8b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Mon, 25 Nov 2024 10:18:25 +0100 Subject: [PATCH 44/77] Fix failing query example (#1119) --- .../ROOT/pages/appendix/gql-conformance/additional-cypher.adoc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/ROOT/pages/appendix/gql-conformance/additional-cypher.adoc b/modules/ROOT/pages/appendix/gql-conformance/additional-cypher.adoc index 837a32330..6731cb737 100644 --- a/modules/ROOT/pages/appendix/gql-conformance/additional-cypher.adoc +++ b/modules/ROOT/pages/appendix/gql-conformance/additional-cypher.adoc @@ -1,4 +1,5 @@ :description: Information about Cypher features not included in GQL. +:test-skip: true = Additional Cypher features While the link:https://www.iso.org/standard/76120.html[GQL Standard] incorporates a lot of capabilities in Cypher, Cypher contains additional features that are not part of GQL and no GQL alternatives currently exist for them. @@ -94,7 +95,7 @@ a| [source, cypher, role="noheader"] ---- MATCH (n:$($label)), - ()-[r:$($type))]->() + ()-[r:$($type)]->() ---- | xref:clauses/match.adoc#dynamic-match[`MATCH` nodes and relationships using dynamic node labels and relationship types] From 9a713c649e33c0994990769461f68153800064fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Tue, 26 Nov 2024 15:41:01 +0100 Subject: [PATCH 45/77] graph.byElemendId (#1121) --- .../appendix/gql-conformance/additional-cypher.adoc | 3 ++- modules/ROOT/pages/clauses/use.adoc | 12 ++++++++---- ...precations-additions-removals-compatibility.adoc | 12 ++++++++++++ modules/ROOT/pages/functions/graph.adoc | 13 +++++++++++-- 4 files changed, 33 insertions(+), 7 deletions(-) diff --git a/modules/ROOT/pages/appendix/gql-conformance/additional-cypher.adoc b/modules/ROOT/pages/appendix/gql-conformance/additional-cypher.adoc index 6731cb737..6e7f49ec1 100644 --- a/modules/ROOT/pages/appendix/gql-conformance/additional-cypher.adoc +++ b/modules/ROOT/pages/appendix/gql-conformance/additional-cypher.adoc @@ -206,7 +206,8 @@ REMOVE n:$($label) | Description | xref:functions/graph.adoc#functions-graph-by-elementid[`graph.byElementId()`] -| Returns the graph reference with the given element id. It is only supported in the `USE` clause, on composite databases. +| Returns the graph reference with the given element id. +It is only supported in the xref:clauses/use.adoc[`USE`] clause. | xref:functions/graph.adoc#functions-graph-byname[`graph.byName()`] | Returns the graph reference of the given name. It is only supported in the `USE` clause, on composite databases. diff --git a/modules/ROOT/pages/clauses/use.adoc b/modules/ROOT/pages/clauses/use.adoc index 4f1811d20..7433484ce 100644 --- a/modules/ROOT/pages/clauses/use.adoc +++ b/modules/ROOT/pages/clauses/use.adoc @@ -92,7 +92,7 @@ MATCH (n) RETURN n [[query-use-examples-query-composite-database-constituent-graph-dynamically]] === Query a composite database constituent graph dynamically -The built-in function `graph.byName()` can be used in the `USE` clause to resolve a constituent graph from a `STRING` value containing the qualified name of a constituent. +The xref:functions/graph.adoc#functions-graph-byname[`graph.byName()`] function can be used in the `USE` clause to resolve a constituent graph from a `STRING` value containing the qualified name of a constituent. This example uses a composite database named `myComposite` that includes an alias named `myConstituent`: @@ -116,9 +116,13 @@ MATCH (n) RETURN n [[query-use-examples-query-composite-database-by-element-id]] === Query a composite database constituent using elementId -The `graph.byElementId()` function, can be used in the `USE` clause to resolve a constituent graph to which a given element id belongs. -In the below example, it is assumed that the DBMS contains a composite database constituent, which contains the element id `4:c0a65d96-4993-4b0c-b036-e7ebd9174905:0`. -If the constituent database is not a standard database in the DBMS an error will be thrown: +The xref:functions/graph.adoc#functions-graph-by-elementid[`graph.byElementId()`] function can be used in the `USE` clause to resolve a constituent graph to which a given xref:functions/scalar.adoc#functions-elementid[element id] belongs. + +[NOTE] +On a standard database, a `USE` clause with `graph.byElementId()` cannot be combined with other `USE` clauses unless the subsequent `USE` clauses reference the same element id. + +In the below example, it is assumed that the DBMS contains the database corresponding to the given element id. If you are connected to a composite database it needs to be a element id to a constituent database, which is a standard database in the DBMS. + .Query [source, cypher, role=test-skip] ---- diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index 780cfaf1f..b674532d7 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -278,6 +278,18 @@ For more information on the deprecation of these formats, see link:{neo4j-docs-b | Feature | Details +a| +label:functionality[] +label:updated[] +[source, cypher, role="noheader"] +---- +USE graph.byElementId("4:c0a65d96-4993-4b0c-b036-e7ebd9174905:0") +MATCH (n) RETURN n +---- + +| xref:functions/graph.adoc#functions-graph-by-elementid[`graph.byElementId()`] can now be used on both link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/[standard and composite databases]. +Previously it could only be used on composite databases. + a| label:functionality[] label:updated[] diff --git a/modules/ROOT/pages/functions/graph.adoc b/modules/ROOT/pages/functions/graph.adoc index 3d7b7028d..57545af0f 100644 --- a/modules/ROOT/pages/functions/graph.adoc +++ b/modules/ROOT/pages/functions/graph.adoc @@ -144,12 +144,18 @@ For more information, see xref:subqueries/call-subquery.adoc#import-variables[CA .Details |=== | *Syntax* 3+| `graph.byName(name)` -| *Description* 3+| Returns the graph reference of the given name. It is only supported in the `USE` clause, on composite databases. +| *Description* 3+| Returns the graph reference of the given name. .2+| *Arguments* | *Name* | *Type* | *Description* | `name` | `STRING` | The name of the graph to be resolved. | *Returns* 3+| `GRAPH` |=== + +.Considerations +|=== +| `graph.byName()` is only supported in the xref:clauses/use.adoc[`USE`] clause, on composite databases. +|=== + .+graph.byName()+ ====== @@ -178,7 +184,7 @@ Returns all nodes from all graphs on the current composite database. .Details |=== | *Syntax* 3+| `graph.byElementId(elementId)` -| *Description* 3+| Returns the graph reference with the given element id. It is only supported in the `USE` clause, on composite databases. +| *Description* 3+| Returns the graph reference with the given element id. .2+| *Arguments* | *Name* | *Type* | *Description* | `elementId` | `STRING` | An element id of a node or relationship. | *Returns* 3+| `GRAPH` @@ -187,6 +193,9 @@ Returns all nodes from all graphs on the current composite database. .Considerations |=== | If the constituent database is not a standard database in the DBMS, an error will be thrown. +| `graph.byElementId()` is only supported in the xref:clauses/use.adoc[`USE`] clause. +| `graph.byElementId()` is supported on both link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/[standard and composite databases]. +| On a standard database, a `USE` clause with `graph.byElementId()` cannot be combined with other `USE` clauses unless the subsequent `USE` clauses reference the same element id. |=== .+graph.byElementId()+ From 01eb3cd1130d536eb13f6db44f466e74e9b1d262 Mon Sep 17 00:00:00 2001 From: Gem Lamont <106068376+gem-neo4j@users.noreply.github.com> Date: Wed, 27 Nov 2024 09:30:02 +0100 Subject: [PATCH 46/77] UNION ordering undeprecated (#1113) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jens Pryce-Åklundh <112686610+JPryce-Aklundh@users.noreply.github.com> --- ...ions-additions-removals-compatibility.adoc | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index b674532d7..f7691d071 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -311,6 +311,28 @@ label:updated[] GRANT READ {*} ON GRAPH * FOR (n) WHERE n.createdAt > date('2024-10-25') TO regularUsers ---- | link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/property-based-access-control/[Property-based access control] now supports xref:values-and-types/spatial.adoc[spatial] and xref:values-and-types/temporal.adoc[temporal] values. + + +a| +label:functionality[] +label:updated[] +[source, cypher, role="noheader"] +---- +RETURN 'val' as one, 'val' as two +UNION +RETURN 'val' as two, 'val' as one +---- + +[source, cypher, role="noheader"] +---- +RETURN 'val' as one, 'val' as two +UNION ALL +RETURN 'val' as two, 'val' as one +---- +a| + +Using differently ordered return items in a `UNION [ALL]` clause has been un-deprecated. + |=== From 193b701cf8f623cf69603bace6ab0ea3cd83f015 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Fri, 29 Nov 2024 11:52:54 +0100 Subject: [PATCH 47/77] New operator groupings (#1126) --- .../planning-and-tuning/execution-plans.adoc | 2 +- .../operators/operators-detail.adoc | 5216 ++++++++--------- .../planning-and-tuning/query-tuning.adoc | 2 +- 3 files changed, 2534 insertions(+), 2686 deletions(-) diff --git a/modules/ROOT/pages/planning-and-tuning/execution-plans.adoc b/modules/ROOT/pages/planning-and-tuning/execution-plans.adoc index 022232e42..031723c36 100644 --- a/modules/ROOT/pages/planning-and-tuning/execution-plans.adoc +++ b/modules/ROOT/pages/planning-and-tuning/execution-plans.adoc @@ -71,7 +71,7 @@ image::patterns_qpp_solutions.svg[width="700",role="middle"] For the purposes of understanding Cypher execution plans, however, the query result is less interesting than the planning that produces it. -[[runtimes-reading-execution-plans]] +[[reading-execution-plans]] == Reading execution plans The Cypher planner produces logical plans which describe how a particular query is going to be executed. diff --git a/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc b/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc index 984d631d1..2b6b818e4 100644 --- a/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc +++ b/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc @@ -2,11 +2,26 @@ :page-aliases: execution-plans/operators.adoc = Operators in detail -This page contains details and an example query for all operators available in Cypher. -The operators are grouped by the similarity of their characteristics. +Understanding the roles of different operators in an execution plan can be an important step in making queries more efficient. +This page contains details and examples for each of the operators used by the Cypher planner. +For an overview of how the Cypher planner uses operators, see xref:planning-and-tuning/execution-plans.adoc#reading-execution-plans[ Understanding execution plans -> Reading execution plans]. + +The operators are grouped into categories based on the role they fulfill in executing a Cypher query: + +* xref:planning-and-tuning/operators/operators-detail.adoc#leaf-operators[Leaf operators (scans and seeks)] +* xref:planning-and-tuning/operators/operators-detail.adoc#nested-loops-join-operators[Nested loops and join operators] +* xref:planning-and-tuning/operators/operators-detail.adoc#traversal-operators[Traversal operators] +* xref:planning-and-tuning/operators/operators-detail.adoc#union-operators[Union operators] +* xref:planning-and-tuning/operators/operators-detail.adoc#aggregation-operators[Aggregation operators] +* xref:planning-and-tuning/operators/operators-detail.adoc#filter-order-projection-operators[Filter, order, and projection operators] +* xref:planning-and-tuning/operators/operators-detail.adoc#sort-limit-operators[Sort and limit operators] +* xref:planning-and-tuning/operators/operators-detail.adoc#data-modification-operators[Data modification operators] +* xref:planning-and-tuning/operators/operators-detail.adoc#schema-system-operators[Schema and system operators] + +[NOTE] +Certain operators are only used by particular xref:planning-and-tuning/runtimes/concepts.adoc[runtime]. +If so, the example queries will be prefixed with a runtime selection. -Certain operators are only used by a subset of the xref::planning-and-tuning/runtimes/concepts.adoc[runtimes] that Cypher can choose from. -If that is the case, the example queries will be prefixed with an option to choose one of these runtimes. //// [source, cypher, role=test-setup] @@ -81,9 +96,16 @@ CREATE CONSTRAINT constraint_WORKS_IN_badgeNumber_unique IF NOT EXISTS FOR ()-[r //// +[[leaf-operators]] +== Leaf operators (scans and seeks) + +Leaf operators are the initial operations in a query execution plan that directly access data. They are called "leaf" because they are at the outermost level of the query execution tree, with no operations below them. Once these operators retrieve the necessary data, the results are passed to subsequent operators that perform more complex operations. + +Seek operators target specific data items (indexed or otherwise) while scan operators iterate through the data (indexed or otherwise) to find matches. + + [[query-plan-all-nodes-scan]] -== All Nodes Scan -// AllNodesScan +=== All Nodes Scan The `AllNodesScan` operator reads all nodes from the node store. The variable that will contain the nodes is seen in the arguments. @@ -127,9 +149,7 @@ Total database accesses: 36, total allocated memory: 184 [[query-plan-partitioned-all-nodes-scan]] -== Partitioned All Nodes Scan -// PartitionedAllNodesScan - +=== Partitioned All Nodes Scan The `PartitionedAllNodesScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-all-nodes-scan[`AllNodesScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. It allows the store to be partitioned into different segments where each segment can be scanned independently in parallel. @@ -171,30 +191,22 @@ Total database accesses: 106 ====== -[[query-plan-directed-relationship-index-scan]] -== Directed Relationship Index Scan -// DirectedRelationshipIndexScan - -//// -[source, cypher, role=test-setup] ----- -CREATE RANGE INDEX range_worksin_title FOR ()-[r:WORKS_IN]->() ON (r.title) ----- -//// +[[query-plan-node-by-label-scan]] +=== Node By Label Scan +// NodeByLabelScan -The `DirectedRelationshipIndexScan` operator examines all values stored in an index, returning all relationships and their start and end nodes with a particular relationship type and a specified property. +The `NodeByLabelScan` operator fetches all nodes with a specific label from the node label index. -.DirectedRelationshipIndexScan +.NodeByLabelScan ====== .Query [source, cypher] ---- PROFILE -MATCH ()-[r: WORKS_IN]->() -WHERE r.title IS NOT NULL -RETURN r +MATCH (person:Person) +RETURN person ---- .Query Plan @@ -208,29 +220,28 @@ Runtime version {neo4j-version} Batch size 128 -+--------------------------------+----------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+--------------------------------+----------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | r | 15 | 15 | 0 | | | | | -| | +----------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +DirectedRelationshipIndexScan | RANGE INDEX (anon_0)-[r:WORKS_IN(title)]->(anon_1) WHERE title IS NOT NULL | 15 | 15 | 16 | 120 | 3/1 | 2.464 | Fused in Pipeline 0 | -+--------------------------------+----------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++------------------+---------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++------------------+---------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | person | 14 | 14 | 0 | | | | | +| | +---------------+----------------+------+---------+----------------+ | | | +| +NodeByLabelScan | person:Person | 14 | 14 | 15 | 120 | 2/1 | 0.522 | Fused in Pipeline 0 | ++------------------+---------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 16, total allocated memory: 184 +Total database accesses: 15, total allocated memory: 184 ---- ====== -[[query-plan-partitioned-directed-relationship-index-scan]] -== Partitioned Directed Relationship Index Scan -// PartitionedDirectedRelationshipIndexScan - +[[query-plan-partitioned-node-by-label-scan]] +=== Partitioned Node By Label Scan -The `PartitionedDirectedRelationshipIndexScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-directed-relationship-index-scan[`DirectedRelationshipIndexScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. +The `PartitionedNodeByLabelScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-node-by-label-scan[`NodeByLabelScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. -.PartitionedDirectedRelationshipIndexScan + +.PartitionedNodeByLabelScan ====== .Query @@ -238,9 +249,8 @@ It allows the index to be partitioned into different segments where each segment ---- CYPHER runtime=parallel PROFILE -MATCH ()-[r: WORKS_IN]->() -WHERE r.title IS NOT NULL -RETURN r +MATCH (person:Person) +RETURN person ---- .Query Plan @@ -254,36 +264,32 @@ Runtime version {neo4j-version} Batch size 128 -+-------------------------------------------+----+----------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-------------------------------------------+----+----------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -| +ProduceResults | 0 | r | 15 | 15 | 70 | 1/0 | 2.865 | In Pipeline 1 | -| | +----+----------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -| +PartitionedDirectedRelationshipIndexScan | 1 | RANGE INDEX (anon_0)-[r:WORKS_IN(title)]->(anon_1) WHERE title IS NOT NULL | 15 | 15 | 16 | 2/0 | 0.527 | In Pipeline 0 | -+-------------------------------------------+----+----------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ ++-----------------------------+----+---------------+----------------+------+---------+------------------------+-----------+---------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-----------------------------+----+---------------+----------------+------+---------+------------------------+-----------+---------------+ +| +ProduceResults | 0 | person | 14 | 14 | 28 | 2/0 | 0.623 | In Pipeline 1 | +| | +----+---------------+----------------+------+---------+------------------------+-----------+---------------+ +| +PartitionedNodeByLabelScan | 1 | person:Person | 14 | 14 | 15 | 1/0 | 0.094 | In Pipeline 0 | ++-----------------------------+----+---------------+----------------+------+---------+------------------------+-----------+---------------+ -Total database accesses: 86 +Total database accesses: 43 ---- ====== -[[query-plan-undirected-relationship-index-scan]] -== Undirected Relationship Index Scan -// UndirectedRelationshipIndexScan - -The `UndirectedRelationshipIndexScan` operator examines all values stored in an index, returning all relationships and their start and end nodes with a particular relationship type and a specified property. +[[query-plan-intersection-node-by-labels-scan]] +=== Intersection Node By Labels Scan +The `IntersectionNodeByLabelsScan` operator fetches all nodes that have all of the provided labels from the node label index. -.UndirectedRelationshipIndexScan ====== .Query -[source, cypher] +[source,cypher] ---- PROFILE -MATCH ()-[r: WORKS_IN]-() -WHERE r.title IS NOT NULL -RETURN r +MATCH (countryAndLocation:Country&Location) +RETURN countryAndLocation ---- .Query Plan @@ -293,43 +299,39 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+----------------------------------+---------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+----------------------------------+---------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | r | 30 | 30 | 0 | | | | | -| | +---------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +UndirectedRelationshipIndexScan | RANGE INDEX (anon_0)-[r:WORKS_IN(title)]-(anon_1) WHERE title IS NOT NULL | 30 | 30 | 16 | 120 | 3/1 | 1.266 | Fused in Pipeline 0 | -+----------------------------------+---------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 16, total allocated memory: 184 ++-------------------------------+----+-------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-------------------------------+----+-------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | countryAndLocation | 10 | 0 | 0 | | | | | +| | +----+-------------------------------------+----------------+------+---------+----------------+ | | | +| +IntersectionNodeByLabelsScan | 1 | countryAndLocation:Country&Location | 10 | 0 | 0 | 120 | 0/0 | 1.011 | Fused in Pipeline 0 | ++-------------------------------+----+-------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ + +Total database accesses: 13, total allocated memory: 184 ---- ====== +[[query-plan-partitioned-intersection-node-by-labels-scan]] +=== Partitioned Intersection Node By Labels Scan -[[query-plan-partitioned-undirected-relationship-index-scan]] -== Partitioned Undirected Relationship Index Scan -// PartitionedUndirectedRelationshipIndexScan - - -The `PartitionedUndirectedRelationshipIndexScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-undirected-relationship-index-scan[`UndirectedRelationshipIndexScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. +The `PartitionedIntersectionNodeByLabelsScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-intersection-node-by-labels-scan[`IntersectionNodeByLabelsScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. -.PartitionedUndirectedRelationshipIndexScan ====== .Query -[source, cypher] +[source,cypher] ---- CYPHER runtime=parallel PROFILE -MATCH ()-[r: WORKS_IN]-() -WHERE r.title IS NOT NULL -RETURN r +MATCH (countryAndLocation:Country&Location) +RETURN countryAndLocation ---- .Query Plan @@ -339,42 +341,39 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+---------------------------------------------+----+---------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | Time (ms) | Pipeline | -+---------------------------------------------+----+---------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -| +ProduceResults | 0 | r | 30 | 30 | 140 | 1/0 | 3.088 | In Pipeline 1 | -| | +----+---------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -| +PartitionedUndirectedRelationshipIndexScan | 1 | RANGE INDEX (anon_0)-[r:WORKS_IN(title)]-(anon_1) WHERE title IS NOT NULL | 30 | 30 | 16 | 2/0 | 0.572 | In Pipeline 0 | -+---------------------------------------------+----+---------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -Total database accesses: 156 +------------------------------------------+----+-------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | Time (ms) | Pipeline | ++------------------------------------------+----+-------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ +| +ProduceResults | 0 | countryAndLocation | 3 | 0 | 0 | 0/0 | 0.018 | In Pipeline 1 | +| | +----+-------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ +| +PartitionedIntersectionNodeByLabelsScan | 1 | countryAndLocation:Country&Location | 3 | 0 | 13 | 2/0 | 0.770 | In Pipeline 0 | ++------------------------------------------+----+-------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ + +Total database accesses: 13 ---- ====== -[[query-plan-directed-relationship-index-seek]] -== Directed Relationship Index Seek -// DirectedRelationshipIndexSeek - -The `DirectedRelationshipIndexSeek` operator finds relationships and their start and end nodes using an index seek. -The relationship variable and the index used are shown in the arguments of the operator. +[[query-plan-subtraction-node-by-labels-scan]] +=== Subtraction Node By Labels Scan +The `SubtractionNodeByLabelsScan` operator fetches all nodes that have all of the first set of provided labels and none of the second provided set of labels from the node label index. +In the example below, `SubtractionNodeByLabelsScan` retrieves all nodes that have the `Location` label but do not have the `Country` label. -.DirectedRelationshipIndexSeek ====== .Query -[source, cypher] +[source,cypher] ---- PROFILE -MATCH (candidate)-[r:WORKS_IN]->() -WHERE r.title = 'chief architect' -RETURN candidate +MATCH (locationNotCountry:Location&!Country) +RETURN locationNotCountry ---- .Query Plan @@ -384,43 +383,38 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+--------------------------------+-----------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+--------------------------------+-----------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | candidate | 2 | 1 | 0 | | | | | -| | +-----------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +DirectedRelationshipIndexSeek | RANGE INDEX (candidate)-[r:WORKS_IN(title)]->(anon_0) WHERE title = $autostring_0 | 2 | 1 | 2 | 120 | 3/1 | 0.591 | Fused in Pipeline 0 | -+--------------------------------+-----------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++------------------------------+----+--------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++------------------------------+----+--------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | locationNotCountry | 7 | 10 | 0 | 0 | | | | +| | +----+--------------------------------------+----------------+------+---------+----------------+ | | | +| +SubtractionNodeByLabelsScan | 1 | locationNotCountry:Location&!Country | 7 | 10 | 13 | 248 | 2/0 | 3.081 | Fused in Pipeline 0 | ++------------------------------+----+--------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 2, total allocated memory: 184 +Total database accesses: 13, total allocated memory: 312 ---- ====== +[[query-plan-partitioned-subtraction-node-by-labels-scan]] +=== Partitioned Subtraction Node By Labels Scan -[[query-plan-partitioned-directed-relationship-index-seek]] -== Partitioned Directed Relationship Index Seek -// PartitionedDirectedRelationshipIndexSeek - - -The `PartitionedDirectedRelationshipIndexSeek` is a variant of the the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-directed-relationship-index-seek[`DirectedRelationshipIndexSeek`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. +The `PartitionedSubtractionNodeByLabelsScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-subtraction-node-by-labels-scan[`SubtractionNodeByLabelsScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. -.PartitionedDirectedRelationshipIndexSeek ====== .Query -[source, cypher] +[source,cypher] ---- CYPHER runtime=parallel PROFILE -MATCH (candidate)-[r:WORKS_IN]->() -WHERE r.title = 'chief architect' -RETURN candidate +MATCH (locationNotCountry:Location&!Country) +RETURN locationNotCountry ---- .Query Plan @@ -430,42 +424,36 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+-------------------------------------------+----+-----------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-------------------------------------------+----+-----------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -| +ProduceResults | 0 | candidate | 2 | 1 | 2 | 2/0 | 0.284 | In Pipeline 1 | -| | +----+-----------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -| +PartitionedDirectedRelationshipIndexSeek | 1 | RANGE INDEX (candidate)-[r:WORKS_IN(title)]->(anon_0) WHERE title = $autostring_0 | 2 | 1 | 2 | 2/0 | 0.148 | In Pipeline 0 | -+-------------------------------------------+----+-----------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ ++-----------------------------------------+----+--------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-----------------------------------------+----+--------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ +| +ProduceResults | 0 | locationNotCountry | 7 | 10 | 0 | 136 | 0/0 | 0.614 | In Pipeline 1 | +| | +----+--------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ +| +PartitionedSubtractionNodeByLabelsScan | 1 | locationNotCountry:Location&!Country | 7 | 10 | 13 | 120 | 2/0 | 5.173 | In Pipeline 0 | ++-----------------------------------------+----+--------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ -Total database accesses: 4 +Total database accesses: 13, total allocated memory: 262144 ---- ====== +[[query-plan-union-node-by-labels-scan]] +=== Union Node By Labels Scan -[[query-plan-undirected-relationship-index-seek]] -== Undirected Relationship Index Seek -// UndirectedRelationshipIndexSeek - -The `UndirectedRelationshipIndexSeek` operator finds relationships and their start and end nodes using an index seek. -The relationship variable and the index used are shown in the arguments of the operator. - +The `UnionNodeByLabelsScan` operator fetches all nodes that have at least one of the provided labels from the node label index. -.UndirectedRelationshipIndexSeek ====== .Query -[source, cypher] +[source,cypher] ---- PROFILE -MATCH (candidate)-[r:WORKS_IN]-() -WHERE r.title = 'chief architect' -RETURN candidate +MATCH (countryOrLocation:Country|Location) +RETURN countryOrLocation ---- .Query Plan @@ -475,42 +463,38 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+----------------------------------+----------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+----------------------------------+----------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | candidate | 4 | 2 | 0 | | | | | -| | +----------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +UndirectedRelationshipIndexSeek | RANGE INDEX (candidate)-[r:WORKS_IN(title)]-(anon_0) WHERE title = $autostring_0 | 4 | 2 | 2 | 120 | 3/1 | 0.791 | Fused in Pipeline 0 | -+----------------------------------+----------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++------------------------+------------------------------------+----------------+------+---------+----------------+------------------------+-----------+-----------------------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Ordered by | Pipeline | ++------------------------+------------------------------------+----------------+------+---------+----------------+------------------------+-----------+-----------------------+---------------------+ +| +ProduceResults | countryOrLocation | 17 | 11 | 0 | | | | | | +| | +------------------------------------+----------------+------+---------+----------------+ | | | | +| +UnionNodeByLabelsScan | countryOrLocation:Country|Location | 17 | 11 | 13 | 120 | 3/1 | 0.660 | countryOrLocation ASC | Fused in Pipeline 0 | ++------------------------+------------------------------------+----------------+------+---------+----------------+------------------------+-----------+-----------------------+---------------------+ -Total database accesses: 2, total allocated memory: 184 +Total database accesses: 13, total allocated memory: 184 ---- ====== -[[query-plan-partitioned-undirected-relationship-index-seek]] -== Partitioned Undirected Relationship Index Seek -// PartitionedUndirectedRelationshipIndexSeek - -The `PartitionedUndirectedRelationshipIndexSeek` operator finds relationships and their start and end nodes using an index seek. -The relationship variable and the index used are shown in the arguments of the operator. +[[query-plan-partitioned-union-node-by-labels-scan]] +=== Partitioned Union Node By Labels Scan +The `PartitionedUnionNodeByLabelsScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-union-node-by-labels-scan[`UnionNodeByLabelsScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. +It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. -.PartitionedUndirectedRelationshipIndexSeek ====== .Query -[source, cypher] +[source,cypher] ---- CYPHER runtime=parallel PROFILE -MATCH (candidate)-[r:WORKS_IN]-() -WHERE r.title = 'chief architect' -RETURN candidate +MATCH (countryOrLocation:Country|Location) +RETURN countryOrLocation ---- .Query Plan @@ -520,41 +504,46 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+---------------------------------------------+----+----------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | Time (ms) | Pipeline | -+---------------------------------------------+----+----------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -| +ProduceResults | 0 | candidate | 4 | 2 | 4 | 2/0 | 0.333 | In Pipeline 1 | -| | +----+----------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -| +PartitionedUndirectedRelationshipIndexSeek | 1 | RANGE INDEX (candidate)-[r:WORKS_IN(title)]-(anon_0) WHERE title = $autostring_0 | 4 | 2 | 2 | 2/0 | 0.151 | In Pipeline 0 | -+---------------------------------------------+----+----------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ - -Total database accesses: 6 ----- ++-----------------------------------+----+------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-----------------------------------+----+------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ +| +ProduceResults | 0 | countryOrLocation | 17 | 11 | 22 | 2/0 | 1.548 | In Pipeline 1 | +| | +----+------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ +| +PartitionedUnionNodeByLabelsScan | 1 | countryOrLocation:Country|Location | 17 | 11 | 13 | 2/0 | 1.976 | In Pipeline 0 | ++-----------------------------------+----+------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -====== +Total database accesses: 35 +---- +====== -[[query-plan-directed-relationship-by-element-id-seek]] -== Directed Relationship By Element Id Seek -// DirectedRelationshipByElementIdSeek +[[query-plan-node-index-contains-scan]] +=== Node Index Contains Scan -The `DirectedRelationshipByElementIdSeek` operator reads one or more relationships by element id from the relationship store (specified via the function xref::functions/scalar.adoc#functions-elementid[elementId()]) and produces the relationship as well as the source and target node of the relationship. +//// +[source, cypher, role=test-setup] +---- +CREATE TEXT INDEX text_location_name FOR (l:Location) ON (l.name) +---- +//// +The `NodeIndexContainsScan` operator examines all values stored in an index, searching for entries containing a specific `STRING`; for example, in queries including `CONTAINS`. +Although this is slower than an index seek (since all entries need to be examined), it is still faster than the indirection resulting from a label scan using `NodeByLabelScan`, and a property store filter. -.DirectedRelationshipByElementIdSeek +.NodeIndexContainsScan ====== .Query [source, cypher] ---- PROFILE -MATCH (n1)-[r]->() -WHERE elementId(r) = 0 -RETURN r, n1 +MATCH (l:Location) +WHERE l.name CONTAINS 'al' +RETURN l ---- .Query Plan @@ -564,40 +553,41 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+--------------------------------------+----+----------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+--------------------------------------+----+----------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ -| +ProduceResults | 0 | r, n1 | 1 | 0 | 0 | 0 | 0/0 | 0.314 | | -| | +----+----------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | -| +DirectedRelationshipByElementIdSeek | 1 | (n1)-[r]->(anon_0) WHERE elementId(r) = $autoint_0 | 1 | 0 | 0 | 248 | 0/0 | 2.337 | In Pipeline 0 | -+--------------------------------------+----+----------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ ++------------------------+---------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++------------------------+---------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | l | 0 | 2 | 0 | | | | | +| | +---------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +NodeIndexContainsScan | TEXT INDEX l:Location(name) WHERE name CONTAINS $autostring_0 | 0 | 2 | 3 | 120 | 2/0 | 1.305 | Fused in Pipeline 0 | ++------------------------+---------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 0, total allocated memory: 312 +Total database accesses: 3, total allocated memory: 184 ---- ====== -[[query-plan-directed-relationship-by-id-seek]] -== Directed Relationship By Id Seek -// DirectedRelationshipByIdSeek -The `DirectedRelationshipByIdSeek` operator reads one or more relationships by id from the relationship store, and produces the relationship as well as the source and target node of the relationship. +[[query-plan-node-index-ends-with-scan]] +=== Node Index Ends With Scan + +The `NodeIndexEndsWithScan` operator examines all values stored in an index, searching for entries ending in a specific `STRING`; for example, in queries containing `ENDS WITH`. +Although this is slower than an index seek (since all entries need to be examined), it is still faster than the indirection resulting from a label scan using `NodeByLabelScan`, and a property store filter. -.DirectedRelationshipByIdSeek +.NodeIndexEndsWithScan ====== .Query [source, cypher] ---- PROFILE -MATCH (n1)-[r]->() -WHERE id(r) = 0 -RETURN r, n1 +MATCH (l:Location) +WHERE l.name ENDS WITH 'al' +RETURN l ---- .Query Plan @@ -607,41 +597,47 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+-------------------------------+----+---------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-------------------------------+----+---------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | 0 | r, n1 | 1 | 1 | 7 | 0 | | | | -| | +----+---------------------------------------------+----------------+------+---------+----------------+ | | | -| +DirectedRelationshipByIdSeek | 1 | (n1)-[r]->(anon_0) WHERE id(r) = $autoint_0 | 1 | 1 | 1 | 248 | 3/0 | 0.483 | Fused in Pipeline 0 | -+-------------------------------+----+---------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++------------------------+----------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++------------------------+----------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | l | 0 | 0 | 0 | | | | | +| | +----------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +NodeIndexEndsWithScan | TEXT INDEX l:Location(name) WHERE name ENDS WITH $autostring_0 | 0 | 0 | 1 | 120 | 0/0 | 4.409 | Fused in Pipeline 0 | ++------------------------+----------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 8, total allocated memory: 312 +Total database accesses: 1, total allocated memory: 184 ---- ====== -[[query-plan-undirected-relationship-by-element-id-seek]] -== Undirected Relationship By Element Id Seek -// UndirectedRelationshipByElementIdSeek -The `UndirectedRelationshipByElementIdSeek` operator reads one or more relationships by element id from the relationship store (specified via the function xref::functions/scalar.adoc#functions-elementid[elementId()]). -As the direction is unspecified, two rows are produced for each relationship as a result of alternating the combination of the start and end node. +[[query-plan-node-index-scan]] +=== Node Index Scan -.UndirectedRelationshipByElementIdSeek +The `NodeIndexScan` operator examines all values stored in an index, returning all nodes with a particular label and a specified property. + +//// +[source, cypher, role=test-setup] +---- +CREATE RANGE INDEX range_location_name FOR (l:Location) ON (l.name) +---- +//// + +.NodeIndexScan ====== .Query [source, cypher] ---- PROFILE -MATCH (n1)-[r]-() -WHERE elementId(r) = 1 -RETURN r, n1 +MATCH (l:Location) +WHERE l.name IS NOT NULL +RETURN l ---- .Query Plan @@ -651,41 +647,40 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+---------------------------------------+--------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+---------------------------------------+--------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | r, n1 | 2 | 2 | 0 | | | | | -| | +--------------------------------------------+----------------+------+---------+----------------+ | | | -| +UndirectedRelationshipByElementIdSeek| (n1)-[r]-(anon_0) WHERE elementId(r) = $autoint_0 | 2 | 2 | 1 | 120 | 4/0 | 0.332 | Fused in Pipeline 0 | -+---------------------------------+--------------------------------------------+-----+---------------+------+---------+----------------+------------------------+-----------+---------------------+ ++-----------------+-----------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-----------------+-----------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | l | 10 | 10 | 0 | | | | | +| | +-----------------------------------------------------+----------------+------+---------+----------------+ | | | +| +NodeIndexScan | RANGE INDEX l:Location(name) WHERE name IS NOT NULL | 10 | 10 | 11 | 120 | 2/1 | 0.557 | Fused in Pipeline 0 | ++-----------------+-----------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 1, total allocated memory: 184 +Total database accesses: 11, total allocated memory: 184 ---- ====== -[[query-plan-undirected-relationship-by-id-seek]] -== Undirected Relationship By Id Seek -// UndirectedRelationshipByIdSeek - -The `UndirectedRelationshipByIdSeek` operator reads one or more relationships by id from the relationship store (specified via the function xref::functions/scalar.adoc#functions-id[Id()]). -As the direction is unspecified, two rows are produced for each relationship as a result of alternating the combination of the start and end node. +[[query-plan-partitioned-node-index-scan]] +=== Partitioned Node Index Scan +The `PartitionedNodeIndexScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-node-index-scan[`NodeIndexScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. +It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. -.UndirectedRelationshipByIdSeek +.PartitionedNodeIndexScan ====== .Query [source, cypher] ---- +CYPHER runtime=parallel PROFILE -MATCH (n1)-[r]-() -WHERE id(r) = 1 -RETURN r, n1 +MATCH (l:Location) +WHERE l.name IS NOT NULL +RETURN l ---- .Query Plan @@ -693,51 +688,41 @@ RETURN r, n1 ---- Planner COST -Runtime PIPELINED +Runtime PARALLEL -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+---------------------------------+----+--------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+---------------------------------+----+--------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | 0 | r, n1 | 2 | 2 | 14 | 0 | | | | -| | +----+--------------------------------------------+----------------+------+---------+----------------+ | | | -| +UndirectedRelationshipByIdSeek | 1 | (n1)-[r]-(anon_0) WHERE id(r) = $autoint_0 | 2 | 2 | 1 | 248 | 3/0 | 1.005 | Fused in Pipeline 0 | -+---------------------------------+----+--------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++---------------------------+----+-----------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | Time (ms) | Pipeline | ++---------------------------+----+-----------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ +| +ProduceResults | 0 | l | 1 | 10 | 20 | 2/0 | 0.472 | In Pipeline 1 | +| | +----+-----------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ +| +PartitionedNodeIndexScan | 1 | RANGE INDEX l:Location(name) WHERE name IS NOT NULL | 1 | 10 | 11 | 1/0 | 0.187 | In Pipeline 0 | ++---------------------------+----+-----------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -Total database accesses: 15, total allocated memory: 312 +Total database accesses: 31 ---- ====== -[[query-plan-directed-relationship-index-contains-scan]] -== Directed Relationship Index Contains Scan -// DirectedRelationshipIndexContainsScan - -//// -[source, cypher, role=test-setup] ----- -CREATE TEXT INDEX text_worksin_title FOR ()-[r:WORKS_IN]->() ON (r.title) ----- -//// - -The `DirectedRelationshipIndexContainsScan` operator examines all values stored in an index, searching for entries containing a specific `STRING`; for example, in queries including `CONTAINS`. -Although this is slower than an index seek (since all entries need to be examined), it is still faster than the indirection resulting from a type scan using `DirectedRelationshipTypeScan`, and a property store filter. +[[query-plan-node-by-elementid-seek]] +=== Node By ElementId Seek +The `NodeByElementIdSeek` operator reads one or more nodes by ID from the node store, specified via the function xref::functions/scalar.adoc#functions-elementid[elementId()]. -.DirectedRelationshipIndexContainsScan +.NodeByElementIdSeek ====== .Query [source, cypher] ---- PROFILE -MATCH ()-[r: WORKS_IN]->() -WHERE r.title CONTAINS 'senior' -RETURN r +MATCH (n) +WHERE elementId(n) = 0 +RETURN n ---- .Query Plan @@ -747,42 +732,39 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+----------------------------------------+--------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+----------------------------------------+--------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | r | 0 | 4 | 0 | | | | | -| | +--------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +DirectedRelationshipIndexContainsScan | TEXT INDEX (anon_0)-[r:WORKS_IN(title)]->(anon_1) WHERE title CONTAINS $autostring_0 | 0 | 4 | 5 | 120 | 3/0 | 1.051 | Fused in Pipeline 0 | -+----------------------------------------+--------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++------------------------+-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++------------------------+-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | n | 1 | 1 | 0 | | | | | +| | +-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------- | | | +| +NodeByElementIdSeek | n WHERE elementId(n) = $autoint_0 | 1 | 1 | 1 | 120 | 3/0 | 2.108 | Fused in Pipeline 0 | ++------------------------+-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 5, total allocated memory: 184 +Total database accesses: 1, total allocated memory: 184 ---- ====== +[[query-plan-node-by-id-seek]] +=== Node By Id Seek -[[query-plan-undirected-relationship-index-contains-scan]] -== Undirected Relationship Index Contains Scan -// UndirectedRelationshipIndexContainsScan - -The `UndirectedRelationshipIndexContainsScan` operator examines all values stored in an index, searching for entries containing a specific `STRING`; for example, in queries including `CONTAINS`. -Although this is slower than an index seek (since all entries need to be examined), it is still faster than the indirection resulting from a type scan using `DirectedRelationshipTypeScan`, and a property store filter. +The `NodeByIdSeek` operator reads one or more nodes by id from the node store, specified via the function xref::functions/scalar.adoc#functions-id[id()]. -.UndirectedRelationshipIndexContainsScan +.NodeByIdSeek ====== .Query [source, cypher] ---- PROFILE -MATCH ()-[r: WORKS_IN]-() -WHERE r.title CONTAINS 'senior' -RETURN r +MATCH (n) +WHERE id(n) = 0 +RETURN n ---- .Query Plan @@ -792,42 +774,42 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+------------------------------------------+-------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+------------------------------------------+-------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | r | 0 | 8 | 0 | | | | | -| | +-------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +UndirectedRelationshipIndexContainsScan | TEXT INDEX (anon_0)-[r:WORKS_IN(title)]-(anon_1) WHERE title CONTAINS $autostring_0 | 0 | 8 | 5 | 120 | 3/0 | 2.684 | Fused in Pipeline 0 | -+------------------------------------------+-------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++-----------------+----+----------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-----------------+----+----------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | n | 1 | 1 | 2 | 0 | | | | +| | +----+----------------------------+----------------+------+---------+----------------+ | | | +| +NodeByIdSeek | 1 | n WHERE id(n) = $autoint_0 | 1 | 1 | 1 | 248 | 2/0 | 1.109 | Fused in Pipeline 0 | ++-----------------+----+----------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ + +Total database accesses: 3, total allocated memory: 312 -Total database accesses: 5, total allocated memory: 184 ---- ====== -[[query-plan-directed-relationship-index-ends-with-scan]] -== Directed Relationship Index Ends With Scan -// DirectedRelationshipIndexEndsWithScan +[[query-plan-node-index-seek]] +=== Node Index Seek -The `DirectedRelationshipIndexEndsWithScan` operator examines all values stored in an index, searching for entries ending in a specific `STRING`; for example, in queries containing `ENDS WITH`. -Although this is slower than an index seek (since all entries need to be examined), it is still faster than the indirection resulting from a label scan using `NodeByLabelScan`, and a property store filter. +The `NodeIndexSeek` operator finds nodes using an index seek. +The node variable and the index used are shown in the arguments of the operator. +If the index is backs up a xref:constraints/managing-constraints.adoc#create-property-uniqueness-constraints[property uniqueness constraint], the operator is instead called xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-node-unique-index-seek[NodeUniqueIndexSeek]. -.DirectedRelationshipIndexEndsWithScan +.NodeIndexSeek ====== .Query [source, cypher] ---- PROFILE -MATCH ()-[r: WORKS_IN]->() -WHERE r.title ENDS WITH 'developer' -RETURN r +MATCH (location:Location {name: 'Malmo'}) +RETURN location ---- .Query Plan @@ -841,38 +823,37 @@ Runtime version {neo4j-version} Batch size 128 -+----------------------------------------+---------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+----------------------------------------+---------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | r | 0 | 8 | 0 | | | | | -| | +---------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +DirectedRelationshipIndexEndsWithScan | TEXT INDEX (anon_0)-[r:WORKS_IN(title)]->(anon_1) WHERE title ENDS WITH $autostring_0 | 0 | 8 | 9 | 120 | 3/0 | 1.887 | Fused in Pipeline 0 | -+----------------------------------------+---------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++-----------------+----------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-----------------+----------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | location | 1 | 1 | 0 | | | | | +| | +----------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +NodeIndexSeek | RANGE INDEX location:Location(name) WHERE name = $autostring_0 | 1 | 1 | 2 | 120 | 2/1 | 0.401 | Fused in Pipeline 0 | ++-----------------+----------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 9, total allocated memory: 184 +Total database accesses: 2, total allocated memory: 184 ---- ====== -[[query-plan-undirected-relationship-index-ends-with-scan]] -== Undirected Relationship Index Ends With Scan -// UndirectedRelationshipIndexEndsWithScan +[[query-plan-partitioned-node-index-seek]] +=== Partitioned Node Index Seek -The `UndirectedRelationshipIndexEndsWithScan` operator examines all values stored in an index, searching for entries ending in a specific `STRING`; for example, in queries containing `ENDS WITH`. -Although this is slower than an index seek (since all entries need to be examined), it is still faster than the indirection resulting from a label scan using `NodeByLabelScan`, and a property store filter. +The `PartitionedNodeIndexSeek` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-node-index-seek[`NodeIndexSeek`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. +It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. -.UndirectedRelationshipIndexEndsWithScan +.PartitionedNodeIndexSeek ====== .Query [source, cypher] ---- +CYPHER runtime=parallel PROFILE -MATCH ()-[r: WORKS_IN]-() -WHERE r.title ENDS WITH 'developer' -RETURN r +MATCH (location:Location {name: 'Malmo'}) +RETURN location ---- .Query Plan @@ -880,51 +861,51 @@ RETURN r ---- Planner COST -Runtime PIPELINED +Runtime PARALLEL Runtime version {neo4j-version} Batch size 128 -+------------------------------------------+--------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+------------------------------------------+--------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | r | 0 | 16 | 0 | | | | | -| | +--------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +UndirectedRelationshipIndexEndsWithScan | TEXT INDEX (anon_0)-[r:WORKS_IN(title)]-(anon_1) WHERE title ENDS WITH $autostring_0 | 0 | 16 | 9 | 120 | 3/0 | 1.465 | Fused in Pipeline 0 | -+------------------------------------------+--------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++---------------------------+----+----------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | Time (ms) | Pipeline | ++---------------------------+----+----------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ +| +ProduceResults | 0 | location | 0 | 1 | 2 | 2/0 | 0.179 | In Pipeline 1 | +| | +----+----------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ +| +PartitionedNodeIndexSeek | 1 | RANGE INDEX location:Location(name) WHERE name = $autostring_0 | 0 | 1 | 2 | 1/0 | 0.167 | In Pipeline 0 | ++---------------------------+----+----------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -Total database accesses: 9, total allocated memory: 184 +Total database accesses: 4 ---- ====== - -[[query-plan-directed-relationship-index-seek-by-range]] -== Directed Relationship Index Seek By Range -// DirectedRelationshipIndexSeekByRange +[[query-plan-node-unique-index-seek]] +=== Node Unique Index Seek //// [source, cypher, role=test-setup] ---- -CREATE RANGE INDEX range_worksin_duration FOR ()-[r:WORKS_IN]->() ON (r.duration) +CREATE CONSTRAINT team_name IF NOT EXISTS FOR (t:Team) REQUIRE (t.name) IS UNIQUE ---- //// -The `DirectedRelationshipIndexSeekByRange` operator finds relationships and their start and end nodes using an index seek where the value of the property matches a given prefix `STRING`. -`DirectedRelationshipIndexSeekByRange` can be used for `STARTS WITH` and comparison operators such as `+<+`, `+>+`, `+<=+` and `+>=+`. +The `NodeUniqueIndexSeek` operator finds nodes using an index seek within an index backing up a xref:constraints/managing-constraints.adoc#create-property-uniqueness-constraints[property uniqueness constraint]. +The node variable and the index used are shown in the arguments of the operator. +If the index does not back up a property uniqueness constraint, the operator is instead called xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-node-index-seek[NodeIndexSeek]. +If the index seek is used to solve a xref::clauses/merge.adoc[MERGE] clause, it will also be marked with `(Locking)`. +This makes it clear that any nodes returned from the index will be locked in order to prevent concurrent conflicting updates. -.DirectedRelationshipIndexSeekByRange +.NodeUniqueIndexSeek ====== .Query [source, cypher] ---- PROFILE -MATCH (candidate: Person)-[r:WORKS_IN]->(location) -WHERE r.duration > 100 -RETURN candidate +MATCH (t:Team {name: 'Malmo'}) +RETURN t ---- .Query Plan @@ -938,41 +919,50 @@ Runtime version {neo4j-version} Batch size 128 -+---------------------------------------+----------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+---------------------------------------+----------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | candidate | 4 | 15 | 0 | | | | | -| | +----------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +Filter | candidate:Person | 4 | 15 | 30 | | | | | -| | +----------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +DirectedRelationshipIndexSeekByRange | RANGE INDEX (candidate)-[r:WORKS_IN(duration)]->(location) WHERE duration > $autoint_0 | 4 | 15 | 16 | 120 | 4/1 | 0.703 | Fused in Pipeline 0 | -+---------------------------------------+----------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++----------------------+------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++----------------------+------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | t | 1 | 0 | 0 | | | | | +| | +------------------------------------------------+----------------+------+---------+----------------+ | | | +| +NodeUniqueIndexSeek | UNIQUE t:Team(name) WHERE name = $autostring_0 | 1 | 0 | 1 | 120 | 0/1 | 0.280 | Fused in Pipeline 0 | ++----------------------+------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 46, total allocated memory: 184 +Total database accesses: 1, total allocated memory: 184 ---- ====== -[[query-plan-partitioned-directed-relationship-index-seek-by-range]] -== Partitioned Directed Relationship Index Seek By Range -// PartitionedDirectedRelationshipIndexSeekByRange +[[query-plan-multi-node-index-seek]] +=== Multi Node Index Seek + +//// +[source, cypher, role=test-setup] +---- +CREATE RANGE INDEX range_person_name FOR (p:Person) ON (p.name) +---- +//// + +The `MultiNodeIndexSeek` operator finds nodes using multiple index seeks. +It supports using multiple distinct indexes for different nodes in the query. +The node variables and the indexes used are shown in the arguments of the operator. +The operator yields a cartesian product of all index seeks. +For example, if the operator does two seeks and the first seek finds the nodes `a1, a2` and the second `b1, b2, b3`, the `MultiNodeIndexSeek` will yield the rows `(a1, b1), (a1, b2), (a1, b3), (a2, b1), (a2, b2), (a2, b3)`. -The `PartitionedDirectedRelationshipIndexSeekByRange` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-directed-relationship-index-seek-by-range[`DirectedRelationshipIndexSeekByRange`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. -It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. -.PartitionedDirectedRelationshipIndexSeekByRange +.MultiNodeIndexSeek ====== .Query [source, cypher] ---- -CYPHER runtime=parallel PROFILE -MATCH (candidate: Person)-[r:WORKS_IN]->(location) -WHERE r.duration > 100 -RETURN candidate +CYPHER runtime=pipelined +MATCH + (location:Location {name: 'Malmo'}), + (person:Person {name: 'Bob'}) +RETURN location, person ---- .Query Plan @@ -980,46 +970,50 @@ RETURN candidate ---- Planner COST -Runtime PARALLEL +Runtime PIPELINED Runtime version {neo4j-version} Batch size 128 -+--------------------------------------------------+----+----------------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | Time (ms) | Pipeline | -+--------------------------------------------------+----+----------------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------------+ -| +ProduceResults | 0 | candidate | 4 | 15 | 30 | 1/0 | 1.031 | In Pipeline 1 | -| | +----+----------------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------------+ -| +Filter | 1 | candidate:Person | 4 | 15 | 30 | | | | -| | +----+----------------------------------------------------------------------------------------+----------------+------+---------+ | | | -| +PartitionedDirectedRelationshipIndexSeekByRange | 2 | RANGE INDEX (candidate)-[r:WORKS_IN(duration)]->(location) WHERE duration > $autoint_0 | 4 | 15 | 16 | 3/0 | 0.203 | Fused in Pipeline 0 | -+--------------------------------------------------+----+----------------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------------+ ++---------------------+-----------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++---------------------+-----------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | location, person | 1 | 1 | 0 | | | | | +| | +-----------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +MultiNodeIndexSeek | RANGE INDEX location:Location(name) WHERE name = $autostring_0, | 1 | 0 | 0 | 120 | 2/2 | 1.910 | Fused in Pipeline 0 | +| | RANGE INDEX person:Person(name) WHERE name = $autostring_1 | | | | | | | | ++---------------------+-----------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 76 +Total database accesses: 0, total allocated memory: 184 ---- ====== -[[query-plan-undirected-relationship-index-seek-by-range]] -== Undirected Relationship Index Seek By Range -// UndirectedRelationshipIndexSeekByRange +[[query-plan-asserting-multi-node-index-seek]] +=== Asserting Multi Node Index Seek -The `UndirectedRelationshipIndexSeekByRange` operator finds relationships and their start and end nodes using an index seek where the value of the property matches a given prefix `STRING`. -`UndirectedRelationshipIndexSeekByRange` can be used for `STARTS WITH` and comparison operators such as `+<+`, `+>+`, `+<=+` and `+>=+`. +//// +[source, cypher, role=test-setup] +---- +CREATE CONSTRAINT team_id IF NOT EXISTS FOR (t:Team) REQUIRE (t.id) IS UNIQUE +---- +//// +The `AssertingMultiNodeIndexSeek` operator is used to ensure that no xref:constraints/managing-constraints.adoc#create-property-uniqueness-constraints[property uniqueness constraints] are violated. +The example looks for the presence of a team with the supplied name and id, and if one does not exist, it will be created. +Owing to the existence of two property uniqueness constraints on `:Team(name)` and `:Team(id)`, any node that would be found by the `UniqueIndexSeek` operator must be the very same node or the constraints would be violated. -.UndirectedRelationshipIndexSeekByRange + +.AssertingMultiNodeIndexSeek ====== .Query [source, cypher] ---- PROFILE -MATCH (candidate: Person)-[r:WORKS_IN]-(location) -WHERE r.duration > 100 -RETURN candidate +MERGE (t:Team {name: 'Engineering', id: 42}) ---- .Query Plan @@ -1033,41 +1027,42 @@ Runtime version {neo4j-version} Batch size 128 -+-----------------------------------------+---------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-----------------------------------------+---------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | candidate | 5 | 15 | 0 | | | | | -| | +---------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +Filter | candidate:Person | 5 | 15 | 60 | | | | | -| | +---------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +UndirectedRelationshipIndexSeekByRange | RANGE INDEX (candidate)-[r:WORKS_IN(duration)]-(location) WHERE duration > $autoint_0 | 8 | 30 | 16 | 120 | 4/1 | 1.214 | Fused in Pipeline 0 | -+-----------------------------------------+---------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++------------------------------+-----------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++------------------------------+-----------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | | 1 | 0 | 0 | | | | | +| | +-----------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +EmptyResult | | 1 | 0 | 0 | | | | | +| | +-----------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +Merge | CREATE (t:Team {name: $autostring_0, id: $autoint_1}) | 1 | 1 | 0 | | | | | +| | +-----------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +AssertingMultiNodeIndexSeek | UNIQUE t:Team(name) WHERE name = $autostring_0, UNIQUE t:Team(id) WHERE id = $autoint_1 | 0 | 2 | 4 | 120 | 0/2 | 1.584 | Fused in Pipeline 0 | ++------------------------------+-----------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 76, total allocated memory: 184 +Total database accesses: 4, total allocated memory: 184 ---- ====== -[[query-plan-partitioned-undirected-relationship-index-seek-by-range]] -== Partitioned Undirected Relationship Index Seek By Range -// PartitionedUndirectedRelationshipIndexSeekByRange +[[query-plan-node-index-seek-by-range]] +=== Node Index Seek By Range +The `NodeIndexSeekByRange` operator finds nodes using an index seek where the value of the property matches a given prefix `STRING`. +`NodeIndexSeekByRange` can be used for `STARTS WITH` and comparison operators such as `+<+`, `+>+`, `+<=+` and `+>=+`. +If the index is a unique index, the operator is instead called `NodeUniqueIndexSeekByRange`. -The `PartitionedUndirectedRelationshipIndexSeekByRange` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-undirected-relationship-index-seek-by-range[`UndirectedRelationshipIndexSeekByRange`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. -It allows the store to be partitioned into different segments where each segment can be scanned independently in parallel. -.PartitionedUndirectedRelationshipIndexSeekByRange +.NodeIndexSeekByRange ====== .Query [source, cypher] ---- -CYPHER runtime=parallel PROFILE -MATCH (candidate: Person)-[r:WORKS_IN]-(location) -WHERE r.duration > 100 -RETURN candidate +MATCH (l:Location) +WHERE l.name STARTS WITH 'Lon' +RETURN l ---- .Query Plan @@ -1075,42 +1070,44 @@ RETURN candidate ---- Planner COST -Runtime PARALLEL +Runtime PIPELINED Runtime version {neo4j-version} Batch size 128 -+----------------------------------------------------+----+---------------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | Time (ms) | Pipeline | -+----------------------------------------------------+----+---------------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------------+ -| +ProduceResults | 0 | candidate | 5 | 15 | 30 | 1/0 | 0.918 | In Pipeline 1 | -| | +----+---------------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------------+ -| +Filter | 1 | candidate:Person | 5 | 15 | 60 | | | | -| | +----+---------------------------------------------------------------------------------------+----------------+------+---------+ | | | -| +PartitionedUndirectedRelationshipIndexSeekByRange | 2 | RANGE INDEX (candidate)-[r:WORKS_IN(duration)]-(location) WHERE duration > $autoint_0 | 8 | 30 | 16 | 3/0 | 0.413 | Fused in Pipeline 0 | -+----------------------------------------------------+----+---------------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------------+ ++-----------------------+-------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-----------------------+-------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | l | 2 | 1 | 0 | | | | | +| | +-------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +NodeIndexSeekByRange | RANGE INDEX l:Location(name) WHERE name STARTS WITH $autostring_0 | 2 | 1 | 2 | 120 | 3/0 | 0.825 | Fused in Pipeline 0 | ++-----------------------+-------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 106 +Total database accesses: 2, total allocated memory: 184 ---- ====== -[[query-plan-union-node-by-labels-scan]] -== Union Node By Labels Scan -// UnionNodeByLabelsScan +[[query-plan-partitioned-node-index-seek-by-range]] +=== Partitioned Node Index Seek By Range +The `PartitionedNodeIndexSeekByRange` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-node-index-seek-by-range[`NodeIndexSeekByRange`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. +It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. -The `UnionNodeByLabelsScan` operator fetches all nodes that have at least one of the provided labels from the node label index. + +.PartitionedNodeIndexSeekByRange ====== .Query -[source,cypher] +[source, cypher] ---- +CYPHER runtime=parallel PROFILE -MATCH (countryOrLocation:Country|Location) -RETURN countryOrLocation +MATCH (l:Location) +WHERE l.name STARTS WITH 'Lon' +RETURN l ---- .Query Plan @@ -1118,42 +1115,44 @@ RETURN countryOrLocation ---- Planner COST -Runtime PIPELINED +Runtime PARALLEL Runtime version {neo4j-version} Batch size 128 -+------------------------+------------------------------------+----------------+------+---------+----------------+------------------------+-----------+-----------------------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Ordered by | Pipeline | -+------------------------+------------------------------------+----------------+------+---------+----------------+------------------------+-----------+-----------------------+---------------------+ -| +ProduceResults | countryOrLocation | 17 | 11 | 0 | | | | | | -| | +------------------------------------+----------------+------+---------+----------------+ | | | | -| +UnionNodeByLabelsScan | countryOrLocation:Country|Location | 17 | 11 | 13 | 120 | 3/1 | 0.660 | countryOrLocation ASC | Fused in Pipeline 0 | -+------------------------+------------------------------------+----------------+------+---------+----------------+------------------------+-----------+-----------------------+---------------------+ ++----------------------------------+----+-------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | Time (ms) | Pipeline | ++----------------------------------+----+-------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ +| +ProduceResults | 0 | l | 0 | 1 | 2 | 2/0 | 0.191 | In Pipeline 1 | +| | +----+-------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ +| +PartitionedNodeIndexSeekByRange | 1 | RANGE INDEX l:Location(name) WHERE name STARTS WITH $autostring_0 | 0 | 1 | 2 | 1/0 | 0.087 | In Pipeline 0 | ++----------------------------------+----+-------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -Total database accesses: 13, total allocated memory: 184 +Total database accesses: 4 ---- ====== -[[query-plan-partitioned-union-node-by-labels-scan]] -== Partitioned Union Node By Labels Scan -// PartitionedUnionNodeByLabelsScan +[[query-plan-node-unique-index-seek-by-range]] +=== Node Unique Index Seek By Range + +The `NodeUniqueIndexSeekByRange` operator finds nodes using an index seek within a unique index, where the value of the property matches a given prefix `STRING`. +`NodeUniqueIndexSeekByRange` is used by `STARTS WITH` and comparison operators such as `+<+`, `+>+`, `+<=+`, and `+>=+`. +If the index is not unique, the operator is instead called `NodeIndexSeekByRange`. -The `PartitionedUnionNodeByLabelsScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-union-node-by-labels-scan[`UnionNodeByLabelsScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. -It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. +.NodeUniqueIndexSeekByRange ====== .Query -[source,cypher] +[source, cypher] ---- -CYPHER runtime=parallel PROFILE -MATCH (countryOrLocation:Country|Location) -RETURN countryOrLocation +MATCH (t:Team) +WHERE t.name STARTS WITH 'Ma' +RETURN t ---- .Query Plan @@ -1161,199 +1160,27 @@ RETURN countryOrLocation ---- Planner COST -Runtime PARALLEL +Runtime PIPELINED Runtime version {neo4j-version} Batch size 128 -+-----------------------------------+----+------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-----------------------------------+----+------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -| +ProduceResults | 0 | countryOrLocation | 17 | 11 | 22 | 2/0 | 1.548 | In Pipeline 1 | -| | +----+------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -| +PartitionedUnionNodeByLabelsScan | 1 | countryOrLocation:Country|Location | 17 | 11 | 13 | 2/0 | 1.976 | In Pipeline 0 | -+-----------------------------------+----+------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ ++-----------------------------+----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-----------------------------+----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | t | 2 | 0 | 0 | | | | | +| | +----------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +NodeUniqueIndexSeekByRange | UNIQUE t:Team(name) WHERE name STARTS WITH $autostring_0 | 2 | 0 | 1 | 120 | 1/0 | 0.623 | Fused in Pipeline 0 | ++-----------------------------+----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 35 +Total database accesses: 1, total allocated memory: 184 ---- ====== - - -[[query-plan-intersection-node-by-labels-scan]] -== Intersection Node By Labels Scan -// IntersectionNodeByLabelsScan - -The `IntersectionNodeByLabelsScan` operator fetches all nodes that have all of the provided labels from the node label index. -====== - -.Query -[source,cypher] ----- -PROFILE -MATCH (countryAndLocation:Country&Location) -RETURN countryAndLocation ----- - -.Query Plan -[role="queryplan", subs="attributes+"] ----- -Planner COST - -Runtime PIPELINED - -Runtime version {neo4j-version} - -Batch size 128 - - -+-------------------------------+----+-------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-------------------------------+----+-------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | 0 | countryAndLocation | 10 | 0 | 0 | | | | | -| | +----+-------------------------------------+----------------+------+---------+----------------+ | | | -| +IntersectionNodeByLabelsScan | 1 | countryAndLocation:Country&Location | 10 | 0 | 0 | 120 | 0/0 | 1.011 | Fused in Pipeline 0 | -+-------------------------------+----+-------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ - -Total database accesses: 13, total allocated memory: 184 ----- - -====== - - -[[query-plan-partitioned-intersection-node-by-labels-scan]] -== Partitioned Intersection Node By Labels Scan -// PartitionedIntersectionNodeByLabelsScan - - -The `PartitionedIntersectionNodeByLabelsScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-intersection-node-by-labels-scan[`IntersectionNodeByLabelsScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. -It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. -====== - -.Query -[source,cypher] ----- -CYPHER runtime=parallel -PROFILE -MATCH (countryAndLocation:Country&Location) -RETURN countryAndLocation ----- - -.Query Plan -[role="queryplan", subs="attributes+"] ----- -Planner COST - -Runtime PARALLEL - -Runtime version {neo4j-version} - -Batch size 128 - - -------------------------------------------+----+-------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | Time (ms) | Pipeline | -+------------------------------------------+----+-------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -| +ProduceResults | 0 | countryAndLocation | 3 | 0 | 0 | 0/0 | 0.018 | In Pipeline 1 | -| | +----+-------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -| +PartitionedIntersectionNodeByLabelsScan | 1 | countryAndLocation:Country&Location | 3 | 0 | 13 | 2/0 | 0.770 | In Pipeline 0 | -+------------------------------------------+----+-------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ - -Total database accesses: 13 ----- - -====== - - -[[query-plan-subtraction-node-by-labels-scan]] -== Subtraction Node By Labels Scan -// SubtractionNodeByLabelsScan - - -The `SubtractionNodeByLabelsScan` operator fetches all nodes that have all of the first set of provided labels and none of the second provided set of labels from the node label index. -In the example below, `SubtractionNodeByLabelsScan` retrieves all nodes that have the `Location` label but do not have the `Country` label. -====== - -.Query -[source,cypher] ----- -PROFILE -MATCH (locationNotCountry:Location&!Country) -RETURN locationNotCountry ----- - -.Query Plan -[role="queryplan", subs="attributes+"] ----- -Planner COST - -Runtime PIPELINED - -Runtime version {neo4j-version} - -Batch size 128 - -+------------------------------+----+--------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+------------------------------+----+--------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | 0 | locationNotCountry | 7 | 10 | 0 | 0 | | | | -| | +----+--------------------------------------+----------------+------+---------+----------------+ | | | -| +SubtractionNodeByLabelsScan | 1 | locationNotCountry:Location&!Country | 7 | 10 | 13 | 248 | 2/0 | 3.081 | Fused in Pipeline 0 | -+------------------------------+----+--------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ - -Total database accesses: 13, total allocated memory: 312 ----- - -====== - - -[[query-plan-partitioned-subtraction-node-by-labels-scan]] -== Partitioned Subtraction Node By Labels Scan -// PartitionedSubtractionNodeByLabelsScan - - -The `PartitionedSubtractionNodeByLabelsScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-subtraction-node-by-labels-scan[`SubtractionNodeByLabelsScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. -It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. -====== - -.Query -[source,cypher] ----- -CYPHER runtime=parallel -PROFILE -MATCH (locationNotCountry:Location&!Country) -RETURN locationNotCountry ----- - -.Query Plan -[role="queryplan", subs="attributes+"] ----- -Planner COST - -Runtime PARALLEL - -Runtime version {neo4j-version} - -Batch size 128 - -+-----------------------------------------+----+--------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-----------------------------------------+----+--------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ -| +ProduceResults | 0 | locationNotCountry | 7 | 10 | 0 | 136 | 0/0 | 0.614 | In Pipeline 1 | -| | +----+--------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ -| +PartitionedSubtractionNodeByLabelsScan | 1 | locationNotCountry:Location&!Country | 7 | 10 | 13 | 120 | 2/0 | 5.173 | In Pipeline 0 | -+-----------------------------------------+----+--------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ - -Total database accesses: 13, total allocated memory: 262144 ----- - -====== - -[[query-plan-directed-all-relationships-scan]] -== Directed All Relationships Scan -//DirectedAllRelationshipsScan +[[query-plan-directed-all-relationships-scan]] +=== Directed All Relationships Scan The `DirectedAllRelationshipsScan` operator fetches all relationships and their start and end nodes in the database. @@ -1390,10 +1217,8 @@ Total database accesses: 28, total allocated memory: 184 ---- ====== - [[query-plan-partitioned-directed-all-relationships-scan]] -== Partitioned Directed All Relationships Scan - +=== Partitioned Directed All Relationships Scan The `PartitionedDirectedAllRelationshipsScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-directed-all-relationships-scan[`DirectedAllRelationshipsScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. It allows the store to be partitioned into different segments where each segment can be scanned independently in parallel. @@ -1432,8 +1257,8 @@ Total database accesses: 111 ====== [[query-plan-undirected-all-relationships-scan]] -== Undirected All Relationships Scan -//UndirectedAllRelationshipsScan +=== Undirected All Relationships Scan + The `UndirectedAllRelationshipsScan` operator fetches all relationships and their start and end nodes in the database. ====== @@ -1451,7 +1276,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 @@ -1468,10 +1293,8 @@ Total database accesses: 28, total allocated memory: 184 ---- ====== - [[query-plan-partitioned-undirected-all-relationships-scan]] -== Partitioned Undirected All Relationships Scan - +=== Partitioned Undirected All Relationships Scan The `PartitionedUndirectedAllRelationshipsScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-undirected-all-relationships-scan[`UndirectedAllRelationshipsScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. It allows the store to be partitioned into different segments where each segment can be scanned independently in parallel. @@ -1492,7 +1315,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 @@ -1510,7 +1333,7 @@ Total database accesses: 194 ====== [[query-plan-directed-relationship-type-scan]] -== Directed Relationship Type Scan +=== Directed Relationship Type Scan // DirectedRelationshipTypeScan The `DirectedRelationshipTypeScan` operator fetches all relationships and their start and end nodes with a specific type from the relationship type index. @@ -1534,7 +1357,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 @@ -1551,10 +1374,8 @@ Total database accesses: 13, total allocated memory: 184 ====== - [[query-plan-partitioned-directed-relationship-types-scan]] -== Partitioned Directed Relationship Type Scan -// PartitionedDirectedRelationshipTypeScan +=== Partitioned Directed Relationship Type Scan The `PartitionedDirectedRelationshipTypeScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-directed-relationship-type-scan[`DirectedRelationshipTypeScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. @@ -1579,7 +1400,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 @@ -1598,8 +1419,7 @@ Batch size 128 [[query-plan-undirected-relationship-type-scan]] -== Undirected Relationship Type Scan -// UndirectedRelationshipTypeScan +=== Undirected Relationship Type Scan The `UndirectedRelationshipTypeScan` operator fetches all relationships and their start and end nodes with a specific type from the relationship type index. @@ -1620,7 +1440,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 @@ -1637,10 +1457,8 @@ Total database accesses: 13, total allocated memory: 184 ====== - [[query-plan-partitioned-undirected-relationship-type-scan]] -== Partitioned Undirected Relationship Type Scan -// PartitionedUndirectedRelationshipTypeScan +=== Partitioned Undirected Relationship Type Scan The `PartitionedUndirectedRelationshipTypeScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-undirected-relationship-type-scan[`UndirectedRelationshipTypeScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. @@ -1664,7 +1482,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 @@ -1683,7 +1501,7 @@ Total database accesses: 37 [[query-plan-directed-union-relationship-types-scan]] -== Directed Union Relationship Types Scan +=== Directed Union Relationship Types Scan // DirectedUnionRelationshipTypesScan The `DirectedUnionRelationshipTypesScan` operator fetches all relationships and their start and end nodes with at least one of the provided types from the relationship type index. @@ -1709,7 +1527,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 @@ -1726,10 +1544,8 @@ Total database accesses: 14, total allocated memory: 184 ====== - [[query-plan-partitioned-directed-union-relationship-types-scan]] -== Partitioned Directed Union Relationship Types Scan -// PartitionedDirectedUnionRelationshipTypesScan +=== Partitioned Directed Union Relationship Types Scan The `PartitionedDirectedUnionRelationshipTypeScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-directed-union-relationship-types-scan[`DirectedUnionRelationshipTypesScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. @@ -1757,7 +1573,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 @@ -1776,7 +1592,7 @@ Total database accesses: 25 [[query-plan-undirected-union-relationship-types-scan]] -== Undirected Union Relationship Types Scan +=== Undirected Union Relationship Types Scan // UndirectedUnionRelationshipTypesScan The `UndirectedUnionRelationshipTypesScan` operator fetches all relationships and their start and end nodes with at least one of the provided types from the relationship type index. @@ -1802,7 +1618,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 @@ -1819,11 +1635,8 @@ Total database accesses: 14, total allocated memory: 184 ====== - [[query-plan-partitioned-undirected-union-relationship-types-scan]] -== Partitioned Undirected Union Relationship Types Scan -// PartitionedUndirectedUnionRelationshipTypesScan - +=== Partitioned Undirected Union Relationship Types Scan The `PartitionedUndirectedUnionRelationshipTypeScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-undirected-union-relationship-types-scan[`UndirectedUnionRelationshipTypesScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. @@ -1850,7 +1663,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 @@ -1867,22 +1680,30 @@ Total database accesses: 37 ====== -[[query-plan-node-by-elementid-seek]] -== Node By ElementId Seek -// NodeByElementIdSeek +[[query-plan-directed-relationship-index-scan]] +=== Directed Relationship Index Scan +// DirectedRelationshipIndexScan -The `NodeByElementIdSeek` operator reads one or more nodes by ID from the node store, specified via the function xref::functions/scalar.adoc#functions-elementid[elementId()]. +//// +[source, cypher, role=test-setup] +---- +CREATE RANGE INDEX range_worksin_title FOR ()-[r:WORKS_IN]->() ON (r.title) +---- +//// -.NodeByElementIdSeek +The `DirectedRelationshipIndexScan` operator examines all values stored in an index, returning all relationships and their start and end nodes with a particular relationship type and a specified property. + + +.DirectedRelationshipIndexScan ====== .Query [source, cypher] ---- PROFILE -MATCH (n) -WHERE elementId(n) = 0 -RETURN n +MATCH ()-[r: WORKS_IN]->() +WHERE r.title IS NOT NULL +RETURN r ---- .Query Plan @@ -1892,40 +1713,40 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+------------------------+-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+------------------------+-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | n | 1 | 1 | 0 | | | | | -| | +-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------- | | | -| +NodeByElementIdSeek | n WHERE elementId(n) = $autoint_0 | 1 | 1 | 1 | 120 | 3/0 | 2.108 | Fused in Pipeline 0 | -+------------------------+-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++--------------------------------+----------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++--------------------------------+----------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | r | 15 | 15 | 0 | | | | | +| | +----------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +DirectedRelationshipIndexScan | RANGE INDEX (anon_0)-[r:WORKS_IN(title)]->(anon_1) WHERE title IS NOT NULL | 15 | 15 | 16 | 120 | 3/1 | 2.464 | Fused in Pipeline 0 | ++--------------------------------+----------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 1, total allocated memory: 184 +Total database accesses: 16, total allocated memory: 184 ---- ====== -[[query-plan-node-by-id-seek]] -== Node By Id Seek -// NodeByIdSeek - -The `NodeByIdSeek` operator reads one or more nodes by id from the node store, specified via the function xref::functions/scalar.adoc#functions-id[id()]. +[[query-plan-partitioned-directed-relationship-index-scan]] +=== Partitioned Directed Relationship Index Scan +The `PartitionedDirectedRelationshipIndexScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-directed-relationship-index-scan[`DirectedRelationshipIndexScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. +It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. -.NodeByIdSeek +.PartitionedDirectedRelationshipIndexScan ====== .Query [source, cypher] ---- +CYPHER runtime=parallel PROFILE -MATCH (n) -WHERE id(n) = 0 -RETURN n +MATCH ()-[r: WORKS_IN]->() +WHERE r.title IS NOT NULL +RETURN r ---- .Query Plan @@ -1933,44 +1754,41 @@ RETURN n ---- Planner COST -Runtime PIPELINED +Runtime PARALLEL -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+-----------------+----+----------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-----------------+----+----------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | 0 | n | 1 | 1 | 2 | 0 | | | | -| | +----+----------------------------+----------------+------+---------+----------------+ | | | -| +NodeByIdSeek | 1 | n WHERE id(n) = $autoint_0 | 1 | 1 | 1 | 248 | 2/0 | 1.109 | Fused in Pipeline 0 | -+-----------------+----+----------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ - -Total database accesses: 3, total allocated memory: 312 ++-------------------------------------------+----+----------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-------------------------------------------+----+----------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ +| +ProduceResults | 0 | r | 15 | 15 | 70 | 1/0 | 2.865 | In Pipeline 1 | +| | +----+----------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ +| +PartitionedDirectedRelationshipIndexScan | 1 | RANGE INDEX (anon_0)-[r:WORKS_IN(title)]->(anon_1) WHERE title IS NOT NULL | 15 | 15 | 16 | 2/0 | 0.527 | In Pipeline 0 | ++-------------------------------------------+----+----------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -1 row +Total database accesses: 86 ---- ====== +[[query-plan-undirected-relationship-index-scan]] +=== Undirected Relationship Index Scan -[[query-plan-node-by-label-scan]] -== Node By Label Scan -// NodeByLabelScan - -The `NodeByLabelScan` operator fetches all nodes with a specific label from the node label index. +The `UndirectedRelationshipIndexScan` operator examines all values stored in an index, returning all relationships and their start and end nodes with a particular relationship type and a specified property. -.NodeByLabelScan +.UndirectedRelationshipIndexScan ====== .Query [source, cypher] ---- PROFILE -MATCH (person:Person) -RETURN person +MATCH ()-[r: WORKS_IN]-() +WHERE r.title IS NOT NULL +RETURN r ---- .Query Plan @@ -1980,34 +1798,30 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+------------------+---------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+------------------+---------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | person | 14 | 14 | 0 | | | | | -| | +---------------+----------------+------+---------+----------------+ | | | -| +NodeByLabelScan | person:Person | 14 | 14 | 15 | 120 | 2/1 | 0.522 | Fused in Pipeline 0 | -+------------------+---------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++----------------------------------+---------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++----------------------------------+---------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | r | 30 | 30 | 0 | | | | | +| | +---------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +UndirectedRelationshipIndexScan | RANGE INDEX (anon_0)-[r:WORKS_IN(title)]-(anon_1) WHERE title IS NOT NULL | 30 | 30 | 16 | 120 | 3/1 | 1.266 | Fused in Pipeline 0 | ++----------------------------------+---------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 15, total allocated memory: 184 +Total database accesses: 16, total allocated memory: 184 ---- ====== +[[query-plan-partitioned-undirected-relationship-index-scan]] +=== Partitioned Undirected Relationship Index Scan -[[query-plan-partitioned-node-by-label-scan]] -== Partitioned Node By Label Scan -// PartitionedNodeByLabelScan - - -The `PartitionedNodeByLabelScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-node-by-label-scan[`NodeByLabelScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. +The `PartitionedUndirectedRelationshipIndexScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-undirected-relationship-index-scan[`UndirectedRelationshipIndexScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. - -.PartitionedNodeByLabelScan +.PartitionedUndirectedRelationshipIndexScan ====== .Query @@ -2015,8 +1829,9 @@ It allows the index to be partitioned into different segments where each segment ---- CYPHER runtime=parallel PROFILE -MATCH (person:Person) -RETURN person +MATCH ()-[r: WORKS_IN]-() +WHERE r.title IS NOT NULL +RETURN r ---- .Query Plan @@ -2026,49 +1841,48 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+-----------------------------+----+---------------+----------------+------+---------+------------------------+-----------+---------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-----------------------------+----+---------------+----------------+------+---------+------------------------+-----------+---------------+ -| +ProduceResults | 0 | person | 14 | 14 | 28 | 2/0 | 0.623 | In Pipeline 1 | -| | +----+---------------+----------------+------+---------+------------------------+-----------+---------------+ -| +PartitionedNodeByLabelScan | 1 | person:Person | 14 | 14 | 15 | 1/0 | 0.094 | In Pipeline 0 | -+-----------------------------+----+---------------+----------------+------+---------+------------------------+-----------+---------------+ ++---------------------------------------------+----+---------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | Time (ms) | Pipeline | ++---------------------------------------------+----+---------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ +| +ProduceResults | 0 | r | 30 | 30 | 140 | 1/0 | 3.088 | In Pipeline 1 | +| | +----+---------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ +| +PartitionedUndirectedRelationshipIndexScan | 1 | RANGE INDEX (anon_0)-[r:WORKS_IN(title)]-(anon_1) WHERE title IS NOT NULL | 30 | 30 | 16 | 2/0 | 0.572 | In Pipeline 0 | ++---------------------------------------------+----+---------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -Total database accesses: 43 +Total database accesses: 156 ---- ====== -[[query-plan-node-index-seek]] -== Node Index Seek -// NodeIndexSeek +[[query-plan-directed-relationship-index-contains-scan]] +=== Directed Relationship Index Contains Scan //// [source, cypher, role=test-setup] ---- -CREATE RANGE INDEX range_location_name FOR (l:Location) ON (l.name) +CREATE TEXT INDEX text_worksin_title FOR ()-[r:WORKS_IN]->() ON (r.title) ---- //// -The `NodeIndexSeek` operator finds nodes using an index seek. -The node variable and the index used are shown in the arguments of the operator. -If the index is a unique index, the operator is instead called xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-node-unique-index-seek[NodeUniqueIndexSeek]. +The `DirectedRelationshipIndexContainsScan` operator examines all values stored in an index, searching for entries containing a specific `STRING`; for example, in queries including `CONTAINS`. +Although this is slower than an index seek (since all entries need to be examined), it is still faster than the indirection resulting from a type scan using `DirectedRelationshipTypeScan`, and a property store filter. -.NodeIndexSeek +.DirectedRelationshipIndexContainsScan ====== .Query [source, cypher] ---- PROFILE -MATCH (location:Location {name: 'Malmo'}) -RETURN location +MATCH ()-[r: WORKS_IN]->() +WHERE r.title CONTAINS 'senior' +RETURN r ---- .Query Plan @@ -2078,43 +1892,41 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+-----------------+----------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-----------------+----------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | location | 1 | 1 | 0 | | | | | -| | +----------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +NodeIndexSeek | RANGE INDEX location:Location(name) WHERE name = $autostring_0 | 1 | 1 | 2 | 120 | 2/1 | 0.401 | Fused in Pipeline 0 | -+-----------------+----------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++----------------------------------------+--------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++----------------------------------------+--------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | r | 0 | 4 | 0 | | | | | +| | +--------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +DirectedRelationshipIndexContainsScan | TEXT INDEX (anon_0)-[r:WORKS_IN(title)]->(anon_1) WHERE title CONTAINS $autostring_0 | 0 | 4 | 5 | 120 | 3/0 | 1.051 | Fused in Pipeline 0 | ++----------------------------------------+--------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 2, total allocated memory: 184 +Total database accesses: 5, total allocated memory: 184 ---- ====== -[[query-plan-partitioned-node-index-seek]] -== Partitioned Node Index Seek -// PartitionedNodeIndexSeek - +[[query-plan-undirected-relationship-index-contains-scan]] +=== Undirected Relationship Index Contains Scan -The `PartitionedNodeIndexSeek` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-node-index-seek[`NodeIndexSeek`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. -It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. +The `UndirectedRelationshipIndexContainsScan` operator examines all values stored in an index, searching for entries containing a specific `STRING`; for example, in queries including `CONTAINS`. +Although this is slower than an index seek (since all entries need to be examined), it is still faster than the indirection resulting from a type scan using `DirectedRelationshipTypeScan`, and a property store filter. -.PartitionedNodeIndexSeek +.UndirectedRelationshipIndexContainsScan ====== .Query [source, cypher] ---- -CYPHER runtime=parallel PROFILE -MATCH (location:Location {name: 'Malmo'}) -RETURN location +MATCH ()-[r: WORKS_IN]-() +WHERE r.title CONTAINS 'senior' +RETURN r ---- .Query Plan @@ -2122,53 +1934,43 @@ RETURN location ---- Planner COST -Runtime PARALLEL +Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+---------------------------+----+----------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | Time (ms) | Pipeline | -+---------------------------+----+----------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -| +ProduceResults | 0 | location | 0 | 1 | 2 | 2/0 | 0.179 | In Pipeline 1 | -| | +----+----------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -| +PartitionedNodeIndexSeek | 1 | RANGE INDEX location:Location(name) WHERE name = $autostring_0 | 0 | 1 | 2 | 1/0 | 0.167 | In Pipeline 0 | -+---------------------------+----+----------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ ++------------------------------------------+-------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++------------------------------------------+-------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | r | 0 | 8 | 0 | | | | | +| | +-------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +UndirectedRelationshipIndexContainsScan | TEXT INDEX (anon_0)-[r:WORKS_IN(title)]-(anon_1) WHERE title CONTAINS $autostring_0 | 0 | 8 | 5 | 120 | 3/0 | 2.684 | Fused in Pipeline 0 | ++------------------------------------------+-------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 4 +Total database accesses: 5, total allocated memory: 184 ---- ====== -[[query-plan-node-unique-index-seek]] -== Node Unique Index Seek -// NodeUniqueIndexSeek - -//// -[source, cypher, role=test-setup] ----- -CREATE CONSTRAINT team_name IF NOT EXISTS FOR (t:Team) REQUIRE (t.name) IS UNIQUE ----- -//// +[[query-plan-directed-relationship-index-ends-with-scan]] +=== Directed Relationship Index Ends With Scan -The `NodeUniqueIndexSeek` operator finds nodes using an index seek within a unique index. -The node variable and the index used are shown in the arguments of the operator. -If the index is not unique, the operator is instead called xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-node-index-seek[NodeIndexSeek]. -If the index seek is used to solve a xref::clauses/merge.adoc[MERGE] clause, it will also be marked with `(Locking)`. -This makes it clear that any nodes returned from the index will be locked in order to prevent concurrent conflicting updates. +The `DirectedRelationshipIndexEndsWithScan` operator examines all values stored in an index, searching for entries ending in a specific `STRING`; for example, in queries containing `ENDS WITH`. +Although this is slower than an index seek (since all entries need to be examined), it is still faster than the indirection resulting from a label scan using `NodeByLabelScan`, and a property store filter. -.NodeUniqueIndexSeek +.DirectedRelationshipIndexEndsWithScan ====== .Query [source, cypher] ---- PROFILE -MATCH (t:Team {name: 'Malmo'}) -RETURN t +MATCH ()-[r: WORKS_IN]->() +WHERE r.title ENDS WITH 'developer' +RETURN r ---- .Query Plan @@ -2178,55 +1980,41 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+----------------------+------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+----------------------+------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | t | 1 | 0 | 0 | | | | | -| | +------------------------------------------------+----------------+------+---------+----------------+ | | | -| +NodeUniqueIndexSeek | UNIQUE t:Team(name) WHERE name = $autostring_0 | 1 | 0 | 1 | 120 | 0/1 | 0.280 | Fused in Pipeline 0 | -+----------------------+------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++----------------------------------------+---------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++----------------------------------------+---------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | r | 0 | 8 | 0 | | | | | +| | +---------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +DirectedRelationshipIndexEndsWithScan | TEXT INDEX (anon_0)-[r:WORKS_IN(title)]->(anon_1) WHERE title ENDS WITH $autostring_0 | 0 | 8 | 9 | 120 | 3/0 | 1.887 | Fused in Pipeline 0 | ++----------------------------------------+---------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 1, total allocated memory: 184 +Total database accesses: 9, total allocated memory: 184 ---- ====== -[[query-plan-multi-node-index-seek]] -== Multi Node Index Seek -// MultiNodeIndexSeek - -//// -[source, cypher, role=test-setup] ----- -CREATE RANGE INDEX range_person_name FOR (p:Person) ON (p.name) ----- -//// - -The `MultiNodeIndexSeek` operator finds nodes using multiple index seeks. -It supports using multiple distinct indexes for different nodes in the query. -The node variables and the indexes used are shown in the arguments of the operator. +[[query-plan-undirected-relationship-index-ends-with-scan]] +=== Undirected Relationship Index Ends With Scan -The operator yields a cartesian product of all index seeks. -For example, if the operator does two seeks and the first seek finds the nodes `a1, a2` and the second `b1, b2, b3`, the `MultiNodeIndexSeek` will yield the rows `(a1, b1), (a1, b2), (a1, b3), (a2, b1), (a2, b2), (a2, b3)`. +The `UndirectedRelationshipIndexEndsWithScan` operator examines all values stored in an index, searching for entries ending in a specific `STRING`; for example, in queries containing `ENDS WITH`. +Although this is slower than an index seek (since all entries need to be examined), it is still faster than the indirection resulting from a label scan using `NodeByLabelScan`, and a property store filter. -.MultiNodeIndexSeek +.UndirectedRelationshipIndexEndsWithScan ====== .Query [source, cypher] ---- PROFILE -CYPHER runtime=pipelined -MATCH - (location:Location {name: 'Malmo'}), - (person:Person {name: 'Bob'}) -RETURN location, person +MATCH ()-[r: WORKS_IN]-() +WHERE r.title ENDS WITH 'developer' +RETURN r ---- .Query Plan @@ -2236,49 +2024,41 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+---------------------+-----------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+---------------------+-----------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | location, person | 1 | 1 | 0 | | | | | -| | +-----------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +MultiNodeIndexSeek | RANGE INDEX location:Location(name) WHERE name = $autostring_0, | 1 | 0 | 0 | 120 | 2/2 | 1.910 | Fused in Pipeline 0 | -| | RANGE INDEX person:Person(name) WHERE name = $autostring_1 | | | | | | | | -+---------------------+-----------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++------------------------------------------+--------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++------------------------------------------+--------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | r | 0 | 16 | 0 | | | | | +| | +--------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +UndirectedRelationshipIndexEndsWithScan | TEXT INDEX (anon_0)-[r:WORKS_IN(title)]-(anon_1) WHERE title ENDS WITH $autostring_0 | 0 | 16 | 9 | 120 | 3/0 | 1.465 | Fused in Pipeline 0 | ++------------------------------------------+--------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 0, total allocated memory: 184 +Total database accesses: 9, total allocated memory: 184 ---- ====== -[[query-plan-asserting-multi-node-index-seek]] -== Asserting Multi Node Index Seek -// AssertingMultiNodeIndexSeek - -//// -[source, cypher, role=test-setup] ----- -CREATE CONSTRAINT team_id IF NOT EXISTS FOR (t:Team) REQUIRE (t.id) IS UNIQUE ----- -//// +[[query-plan-directed-relationship-index-seek]] +=== Directed Relationship Index Seek -The `AssertingMultiNodeIndexSeek` operator is used to ensure that no property uniqueness constraints are violated. -The example looks for the presence of a team with the supplied name and id, and if one does not exist, it will be created. -Owing to the existence of two property uniqueness constraints on `:Team(name)` and `:Team(id)`, any node that would be found by the `UniqueIndexSeek` operator must be the very same node or the constraints would be violated. +The `DirectedRelationshipIndexSeek` operator finds relationships and their start and end nodes using an index seek. +The relationship variable and the index used are shown in the arguments of the operator. -.AssertingMultiNodeIndexSeek +.DirectedRelationshipIndexSeek ====== .Query [source, cypher] ---- PROFILE -MERGE (t:Team {name: 'Engineering', id: 42}) +MATCH (candidate)-[r:WORKS_IN]->() +WHERE r.title = 'chief architect' +RETURN candidate ---- .Query Plan @@ -2288,48 +2068,40 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+------------------------------+-----------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+------------------------------+-----------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | | 1 | 0 | 0 | | | | | -| | +-----------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +EmptyResult | | 1 | 0 | 0 | | | | | -| | +-----------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +Merge | CREATE (t:Team {name: $autostring_0, id: $autoint_1}) | 1 | 1 | 0 | | | | | -| | +-----------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +AssertingMultiNodeIndexSeek | UNIQUE t:Team(name) WHERE name = $autostring_0, UNIQUE t:Team(id) WHERE id = $autoint_1 | 0 | 2 | 4 | 120 | 0/2 | 1.584 | Fused in Pipeline 0 | -+------------------------------+-----------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++--------------------------------+-----------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++--------------------------------+-----------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | candidate | 2 | 1 | 0 | | | | | +| | +-----------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +DirectedRelationshipIndexSeek | RANGE INDEX (candidate)-[r:WORKS_IN(title)]->(anon_0) WHERE title = $autostring_0 | 2 | 1 | 2 | 120 | 3/1 | 0.591 | Fused in Pipeline 0 | ++--------------------------------+-----------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 4, total allocated memory: 184 +Total database accesses: 2, total allocated memory: 184 ---- ====== +[[query-plan-partitioned-directed-relationship-index-seek]] +=== Partitioned Directed Relationship Index Seek -[[query-plan-node-index-seek-by-range]] -== Node Index Seek By Range -// NodeIndexSeekByRange - +The `PartitionedDirectedRelationshipIndexSeek` is a variant of the the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-directed-relationship-index-seek[`DirectedRelationshipIndexSeek`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. +It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. -The `NodeIndexSeekByRange` operator finds nodes using an index seek where the value of the property matches a given prefix `STRING`. -`NodeIndexSeekByRange` can be used for `STARTS WITH` and comparison operators such as `+<+`, `+>+`, `+<=+` and `+>=+`. -If the index is a unique index, the operator is instead called `NodeUniqueIndexSeekByRange`. - - -.NodeIndexSeekByRange +.PartitionedDirectedRelationshipIndexSeek ====== .Query [source, cypher] ---- +CYPHER runtime=parallel PROFILE -MATCH (l:Location) -WHERE l.name STARTS WITH 'Lon' -RETURN l +MATCH (candidate)-[r:WORKS_IN]->() +WHERE r.title = 'chief architect' +RETURN candidate ---- .Query Plan @@ -2337,46 +2109,43 @@ RETURN l ---- Planner COST -Runtime PIPELINED +Runtime PARALLEL -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+-----------------------+-------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-----------------------+-------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | l | 2 | 1 | 0 | | | | | -| | +-------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +NodeIndexSeekByRange | RANGE INDEX l:Location(name) WHERE name STARTS WITH $autostring_0 | 2 | 1 | 2 | 120 | 3/0 | 0.825 | Fused in Pipeline 0 | -+-----------------------+-------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++-------------------------------------------+----+-----------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-------------------------------------------+----+-----------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ +| +ProduceResults | 0 | candidate | 2 | 1 | 2 | 2/0 | 0.284 | In Pipeline 1 | +| | +----+-----------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ +| +PartitionedDirectedRelationshipIndexSeek | 1 | RANGE INDEX (candidate)-[r:WORKS_IN(title)]->(anon_0) WHERE title = $autostring_0 | 2 | 1 | 2 | 2/0 | 0.148 | In Pipeline 0 | ++-------------------------------------------+----+-----------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -Total database accesses: 2, total allocated memory: 184 +Total database accesses: 4 ---- ====== -[[query-plan-partitioned-node-index-seek-by-range]] -== Partitioned Node Index Seek By Range -// PartitionedNodeIndexSeekByRange - +[[query-plan-undirected-relationship-index-seek]] +=== Undirected Relationship Index Seek -The `PartitionedNodeIndexSeekByRange` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-node-index-seek-by-range[`NodeIndexSeekByRange`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. -It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. +The `UndirectedRelationshipIndexSeek` operator finds relationships and their start and end nodes using an index seek. +The relationship variable and the index used are shown in the arguments of the operator. -.PartitionedNodeIndexSeekByRange +.UndirectedRelationshipIndexSeek ====== .Query [source, cypher] ---- -CYPHER runtime=parallel PROFILE -MATCH (l:Location) -WHERE l.name STARTS WITH 'Lon' -RETURN l +MATCH (candidate)-[r:WORKS_IN]-() +WHERE r.title = 'chief architect' +RETURN candidate ---- .Query Plan @@ -2384,45 +2153,43 @@ RETURN l ---- Planner COST -Runtime PARALLEL +Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+----------------------------------+----+-------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | Time (ms) | Pipeline | -+----------------------------------+----+-------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -| +ProduceResults | 0 | l | 0 | 1 | 2 | 2/0 | 0.191 | In Pipeline 1 | -| | +----+-------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -| +PartitionedNodeIndexSeekByRange | 1 | RANGE INDEX l:Location(name) WHERE name STARTS WITH $autostring_0 | 0 | 1 | 2 | 1/0 | 0.087 | In Pipeline 0 | -+----------------------------------+----+-------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ ++----------------------------------+----------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++----------------------------------+----------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | candidate | 4 | 2 | 0 | | | | | +| | +----------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +UndirectedRelationshipIndexSeek | RANGE INDEX (candidate)-[r:WORKS_IN(title)]-(anon_0) WHERE title = $autostring_0 | 4 | 2 | 2 | 120 | 3/1 | 0.791 | Fused in Pipeline 0 | ++----------------------------------+----------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 4 +Total database accesses: 2, total allocated memory: 184 ---- ====== +[[query-plan-partitioned-undirected-relationship-index-seek]] +=== Partitioned Undirected Relationship Index Seek -[[query-plan-node-unique-index-seek-by-range]] -== Node Unique Index Seek By Range -// NodeUniqueIndexSeekByRange - -The `NodeUniqueIndexSeekByRange` operator finds nodes using an index seek within a unique index, where the value of the property matches a given prefix `STRING`. -`NodeUniqueIndexSeekByRange` is used by `STARTS WITH` and comparison operators such as `+<+`, `+>+`, `+<=+`, and `+>=+`. -If the index is not unique, the operator is instead called `NodeIndexSeekByRange`. +The `PartitionedUndirectedRelationshipIndexSeek` operator finds relationships and their start and end nodes using an index seek. +The relationship variable and the index used are shown in the arguments of the operator. -.NodeUniqueIndexSeekByRange +.PartitionedUndirectedRelationshipIndexSeek ====== .Query [source, cypher] ---- +CYPHER runtime=parallel PROFILE -MATCH (t:Team) -WHERE t.name STARTS WITH 'Ma' -RETURN t +MATCH (candidate)-[r:WORKS_IN]-() +WHERE r.title = 'chief architect' +RETURN candidate ---- .Query Plan @@ -2430,51 +2197,42 @@ RETURN t ---- Planner COST -Runtime PIPELINED +Runtime PARALLEL -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+-----------------------------+----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-----------------------------+----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | t | 2 | 0 | 0 | | | | | -| | +----------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +NodeUniqueIndexSeekByRange | UNIQUE t:Team(name) WHERE name STARTS WITH $autostring_0 | 2 | 0 | 1 | 120 | 1/0 | 0.623 | Fused in Pipeline 0 | -+-----------------------------+----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++---------------------------------------------+----+----------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | Time (ms) | Pipeline | ++---------------------------------------------+----+----------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ +| +ProduceResults | 0 | candidate | 4 | 2 | 4 | 2/0 | 0.333 | In Pipeline 1 | +| | +----+----------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ +| +PartitionedUndirectedRelationshipIndexSeek | 1 | RANGE INDEX (candidate)-[r:WORKS_IN(title)]-(anon_0) WHERE title = $autostring_0 | 4 | 2 | 2 | 2/0 | 0.151 | In Pipeline 0 | ++---------------------------------------------+----+----------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -Total database accesses: 1, total allocated memory: 184 +Total database accesses: 6 ---- ====== -[[query-plan-node-index-contains-scan]] -== Node Index Contains Scan == -// NodeIndexContainsScan - -//// -[source, cypher, role=test-setup] ----- -CREATE TEXT INDEX text_location_name FOR (l:Location) ON (l.name) ----- -//// +[[query-plan-directed-relationship-by-element-id-seek]] +=== Directed Relationship By Element Id Seek -The `NodeIndexContainsScan` operator examines all values stored in an index, searching for entries containing a specific `STRING`; for example, in queries including `CONTAINS`. -Although this is slower than an index seek (since all entries need to be examined), it is still faster than the indirection resulting from a label scan using `NodeByLabelScan`, and a property store filter. +The `DirectedRelationshipByElementIdSeek` operator reads one or more relationships by element id from the relationship store (specified via the function xref::functions/scalar.adoc#functions-elementid[elementId()]) and produces the relationship as well as the source and target node of the relationship. -.NodeIndexContainsScan +.DirectedRelationshipByElementIdSeek ====== .Query [source, cypher] ---- PROFILE -MATCH (l:Location) -WHERE l.name CONTAINS 'al' -RETURN l +MATCH (n1)-[r]->() +WHERE elementId(r) = 0 +RETURN r, n1 ---- .Query Plan @@ -2484,42 +2242,39 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+------------------------+---------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+------------------------+---------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | l | 0 | 2 | 0 | | | | | -| | +---------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +NodeIndexContainsScan | TEXT INDEX l:Location(name) WHERE name CONTAINS $autostring_0 | 0 | 2 | 3 | 120 | 2/0 | 1.305 | Fused in Pipeline 0 | -+------------------------+---------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++--------------------------------------+----+----------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++--------------------------------------+----+----------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ +| +ProduceResults | 0 | r, n1 | 1 | 0 | 0 | 0 | 0/0 | 0.314 | | +| | +----+----------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | +| +DirectedRelationshipByElementIdSeek | 1 | (n1)-[r]->(anon_0) WHERE elementId(r) = $autoint_0 | 1 | 0 | 0 | 248 | 0/0 | 2.337 | In Pipeline 0 | ++--------------------------------------+----+----------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ -Total database accesses: 3, total allocated memory: 184 +Total database accesses: 0, total allocated memory: 312 ---- ====== +[[query-plan-directed-relationship-by-id-seek]] +=== Directed Relationship By Id Seek -[[query-plan-node-index-ends-with-scan]] -== Node Index Ends With Scan -// NodeIndexEndsWithScan - -The `NodeIndexEndsWithScan` operator examines all values stored in an index, searching for entries ending in a specific `STRING`; for example, in queries containing `ENDS WITH`. -Although this is slower than an index seek (since all entries need to be examined), it is still faster than the indirection resulting from a label scan using `NodeByLabelScan`, and a property store filter. +The `DirectedRelationshipByIdSeek` operator reads one or more relationships by id from the relationship store, and produces the relationship as well as the source and target node of the relationship. -.NodeIndexEndsWithScan +.DirectedRelationshipByIdSeek ====== .Query [source, cypher] ---- PROFILE -MATCH (l:Location) -WHERE l.name ENDS WITH 'al' -RETURN l +MATCH (n1)-[r]->() +WHERE id(r) = 0 +RETURN r, n1 ---- .Query Plan @@ -2529,41 +2284,40 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+------------------------+----------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+------------------------+----------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | l | 0 | 0 | 0 | | | | | -| | +----------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +NodeIndexEndsWithScan | TEXT INDEX l:Location(name) WHERE name ENDS WITH $autostring_0 | 0 | 0 | 1 | 120 | 0/0 | 4.409 | Fused in Pipeline 0 | -+------------------------+----------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++-------------------------------+----+---------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-------------------------------+----+---------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | r, n1 | 1 | 1 | 7 | 0 | | | | +| | +----+---------------------------------------------+----------------+------+---------+----------------+ | | | +| +DirectedRelationshipByIdSeek | 1 | (n1)-[r]->(anon_0) WHERE id(r) = $autoint_0 | 1 | 1 | 1 | 248 | 3/0 | 0.483 | Fused in Pipeline 0 | ++-------------------------------+----+---------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 1, total allocated memory: 184 +Total database accesses: 8, total allocated memory: 312 ---- ====== +[[query-plan-undirected-relationship-by-element-id-seek]] +=== Undirected Relationship By Element Id Seek -[[query-plan-node-index-scan]] -== Node Index Scan -// NodeIndexScan - -The `NodeIndexScan` operator examines all values stored in an index, returning all nodes with a particular label and a specified property. +The `UndirectedRelationshipByElementIdSeek` operator reads one or more relationships by element id from the relationship store (specified via the function xref::functions/scalar.adoc#functions-elementid[elementId()]). +As the direction is unspecified, two rows are produced for each relationship as a result of alternating the combination of the start and end node. -.NodeIndexScan +.UndirectedRelationshipByElementIdSeek ====== .Query [source, cypher] ---- PROFILE -MATCH (l:Location) -WHERE l.name IS NOT NULL -RETURN l +MATCH (n1)-[r]-() +WHERE elementId(r) = 1 +RETURN r, n1 ---- .Query Plan @@ -2573,44 +2327,40 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+-----------------+-----------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-----------------+-----------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | l | 10 | 10 | 0 | | | | | -| | +-----------------------------------------------------+----------------+------+---------+----------------+ | | | -| +NodeIndexScan | RANGE INDEX l:Location(name) WHERE name IS NOT NULL | 10 | 10 | 11 | 120 | 2/1 | 0.557 | Fused in Pipeline 0 | -+-----------------+-----------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++---------------------------------------+--------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++---------------------------------------+--------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | r, n1 | 2 | 2 | 0 | | | | | +| | +--------------------------------------------+----------------+------+---------+----------------+ | | | +| +UndirectedRelationshipByElementIdSeek| (n1)-[r]-(anon_0) WHERE elementId(r) = $autoint_0 | 2 | 2 | 1 | 120 | 4/0 | 0.332 | Fused in Pipeline 0 | ++---------------------------------+--------------------------------------------+-----+---------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 11, total allocated memory: 184 +Total database accesses: 1, total allocated memory: 184 ---- ====== +[[query-plan-undirected-relationship-by-id-seek]] +=== Undirected Relationship By Id Seek -[[query-plan-partitioned-node-index-scan]] -== Partitioned Node Index Scan -// PartitionedNodeIndexScan - - -The `PartitionedNodeIndexScan` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-node-index-scan[`NodeIndexScan`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. -It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. +The `UndirectedRelationshipByIdSeek` operator reads one or more relationships by id from the relationship store (specified via the function xref::functions/scalar.adoc#functions-id[Id()]). +As the direction is unspecified, two rows are produced for each relationship as a result of alternating the combination of the start and end node. -.PartitionedNodeIndexScan +.UndirectedRelationshipByIdSeek ====== .Query [source, cypher] ---- -CYPHER runtime=parallel PROFILE -MATCH (l:Location) -WHERE l.name IS NOT NULL -RETURN l +MATCH (n1)-[r]-() +WHERE id(r) = 1 +RETURN r, n1 ---- .Query Plan @@ -2618,46 +2368,238 @@ RETURN l ---- Planner COST -Runtime PARALLEL +Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+---------------------------+----+-----------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | Time (ms) | Pipeline | -+---------------------------+----+-----------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -| +ProduceResults | 0 | l | 1 | 10 | 20 | 2/0 | 0.472 | In Pipeline 1 | -| | +----+-----------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -| +PartitionedNodeIndexScan | 1 | RANGE INDEX l:Location(name) WHERE name IS NOT NULL | 1 | 10 | 11 | 1/0 | 0.187 | In Pipeline 0 | -+---------------------------+----+-----------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ ++---------------------------------+----+--------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++---------------------------------+----+--------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | r, n1 | 2 | 2 | 14 | 0 | | | | +| | +----+--------------------------------------------+----------------+------+---------+----------------+ | | | +| +UndirectedRelationshipByIdSeek | 1 | (n1)-[r]-(anon_0) WHERE id(r) = $autoint_0 | 2 | 2 | 1 | 248 | 3/0 | 1.005 | Fused in Pipeline 0 | ++---------------------------------+----+--------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 31 +Total database accesses: 15, total allocated memory: 312 ---- ====== -// --- apply operators --- +[[query-plan-directed-relationship-index-seek-by-range]] +=== Directed Relationship Index Seek By Range -[[query-plan-apply]] -== Apply -// Apply +//// +[source, cypher, role=test-setup] +---- +CREATE RANGE INDEX range_worksin_duration FOR ()-[r:WORKS_IN]->() ON (r.duration) +---- +//// -All the different `Apply` operators (listed below) share the same basic functionality: they perform a nested loop by taking a single row from the left-hand side, and using the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-argument[`Argument`] operator on the right-hand side, execute the operator tree on the right-hand side. -The versions of the `Apply` operators differ in how the results are managed. -The `Apply` operator (i.e. the standard version) takes the row produced by the right-hand side -- which at this point contains data from both the left-hand and right-hand sides -- and yields it. +The `DirectedRelationshipIndexSeekByRange` operator finds relationships and their start and end nodes using an index seek where the value of the property matches a given prefix `STRING`. +`DirectedRelationshipIndexSeekByRange` can be used for `STARTS WITH` and comparison operators such as `+<+`, `+>+`, `+<=+` and `+>=+`. -.Apply +.DirectedRelationshipIndexSeekByRange ====== .Query [source, cypher] ---- PROFILE -MATCH (p:Person {name: 'me'}) -MATCH (q:Person {name: p.secondName}) +MATCH (candidate: Person)-[r:WORKS_IN]->(location) +WHERE r.duration > 100 +RETURN candidate +---- + +.Query Plan +[role="queryplan", subs="attributes+"] +---- +Planner COST + +Runtime PIPELINED + +Runtime version {neo4j-version-minor} + +Batch size 128 + ++---------------------------------------+----------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++---------------------------------------+----------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | candidate | 4 | 15 | 0 | | | | | +| | +----------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +Filter | candidate:Person | 4 | 15 | 30 | | | | | +| | +----------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +DirectedRelationshipIndexSeekByRange | RANGE INDEX (candidate)-[r:WORKS_IN(duration)]->(location) WHERE duration > $autoint_0 | 4 | 15 | 16 | 120 | 4/1 | 0.703 | Fused in Pipeline 0 | ++---------------------------------------+----------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ + +Total database accesses: 46, total allocated memory: 184 +---- + +====== + +[[query-plan-partitioned-directed-relationship-index-seek-by-range]] +=== Partitioned Directed Relationship Index Seek By Range + +The `PartitionedDirectedRelationshipIndexSeekByRange` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-directed-relationship-index-seek-by-range[`DirectedRelationshipIndexSeekByRange`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. +It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. + +.PartitionedDirectedRelationshipIndexSeekByRange +====== + +.Query +[source, cypher] +---- +CYPHER runtime=parallel +PROFILE +MATCH (candidate: Person)-[r:WORKS_IN]->(location) +WHERE r.duration > 100 +RETURN candidate +---- + +.Query Plan +[role="queryplan", subs="attributes+"] +---- +Planner COST + +Runtime PARALLEL + +Runtime version {neo4j-version-minor} + +Batch size 128 + ++--------------------------------------------------+----+----------------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | Time (ms) | Pipeline | ++--------------------------------------------------+----+----------------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | candidate | 4 | 15 | 30 | 1/0 | 1.031 | In Pipeline 1 | +| | +----+----------------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------------+ +| +Filter | 1 | candidate:Person | 4 | 15 | 30 | | | | +| | +----+----------------------------------------------------------------------------------------+----------------+------+---------+ | | | +| +PartitionedDirectedRelationshipIndexSeekByRange | 2 | RANGE INDEX (candidate)-[r:WORKS_IN(duration)]->(location) WHERE duration > $autoint_0 | 4 | 15 | 16 | 3/0 | 0.203 | Fused in Pipeline 0 | ++--------------------------------------------------+----+----------------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------------+ + +Total database accesses: 76 +---- + +====== + + +[[query-plan-undirected-relationship-index-seek-by-range]] +=== Undirected Relationship Index Seek By Range + +The `UndirectedRelationshipIndexSeekByRange` operator finds relationships and their start and end nodes using an index seek where the value of the property matches a given prefix `STRING`. +`UndirectedRelationshipIndexSeekByRange` can be used for `STARTS WITH` and comparison operators such as `+<+`, `+>+`, `+<=+` and `+>=+`. + + +.UndirectedRelationshipIndexSeekByRange +====== + +.Query +[source, cypher] +---- +PROFILE +MATCH (candidate: Person)-[r:WORKS_IN]-(location) +WHERE r.duration > 100 +RETURN candidate +---- + +.Query Plan +[role="queryplan", subs="attributes+"] +---- +Planner COST + +Runtime PIPELINED + +Runtime version {neo4j-version-minor} + +Batch size 128 + ++-----------------------------------------+---------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-----------------------------------------+---------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | candidate | 5 | 15 | 0 | | | | | +| | +---------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +Filter | candidate:Person | 5 | 15 | 60 | | | | | +| | +---------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +UndirectedRelationshipIndexSeekByRange | RANGE INDEX (candidate)-[r:WORKS_IN(duration)]-(location) WHERE duration > $autoint_0 | 8 | 30 | 16 | 120 | 4/1 | 1.214 | Fused in Pipeline 0 | ++-----------------------------------------+---------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ + +Total database accesses: 76, total allocated memory: 184 +---- + +====== + +[[query-plan-partitioned-undirected-relationship-index-seek-by-range]] +=== Partitioned Undirected Relationship Index Seek By Range + +The `PartitionedUndirectedRelationshipIndexSeekByRange` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-undirected-relationship-index-seek-by-range[`UndirectedRelationshipIndexSeekByRange`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. +It allows the store to be partitioned into different segments where each segment can be scanned independently in parallel. + +.PartitionedUndirectedRelationshipIndexSeekByRange +====== + +.Query +[source, cypher] +---- +CYPHER runtime=parallel +PROFILE +MATCH (candidate: Person)-[r:WORKS_IN]-(location) +WHERE r.duration > 100 +RETURN candidate +---- + +.Query Plan +[role="queryplan", subs="attributes+"] +---- +Planner COST + +Runtime PARALLEL + +Runtime version {neo4j-version-minor} + +Batch size 128 + ++----------------------------------------------------+----+---------------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | Time (ms) | Pipeline | ++----------------------------------------------------+----+---------------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | candidate | 5 | 15 | 30 | 1/0 | 0.918 | In Pipeline 1 | +| | +----+---------------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------------+ +| +Filter | 1 | candidate:Person | 5 | 15 | 60 | | | | +| | +----+---------------------------------------------------------------------------------------+----------------+------+---------+ | | | +| +PartitionedUndirectedRelationshipIndexSeekByRange | 2 | RANGE INDEX (candidate)-[r:WORKS_IN(duration)]-(location) WHERE duration > $autoint_0 | 8 | 30 | 16 | 3/0 | 0.413 | Fused in Pipeline 0 | ++----------------------------------------------------+----+---------------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------------+ + +Total database accesses: 106 +---- + +====== + + +[[nested-loops-join-operators]] +== Nested loops and join operators + +Nested loop operators process data by iterating over the right-hand side (RHS) for each row from the left-hand side (LHS). +Each row from the LHS triggers the execution of the RHS, effectively creating a loop over the RHS for each LHS element. + +[[query-plan-apply]] +=== Apply + +All the different `Apply` operators (listed below) share the same basic functionality: they perform a nested loop by taking a single row from the left-hand side, and using the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-argument[`Argument`] operator on the right-hand side, execute the operator tree on the right-hand side. +The versions of the `Apply` operators differ in how the results are managed. +The `Apply` operator (i.e. the standard version) takes the row produced by the right-hand side -- which at this point contains data from both the left-hand and right-hand sides -- and yields it. + + +.Apply +====== + +.Query +[source, cypher] +---- +PROFILE +MATCH (p:Person {name: 'me'}) +MATCH (q:Person {name: p.secondName}) RETURN p, q ---- @@ -2691,8 +2633,7 @@ Total database accesses: 2, total allocated memory: 2216 [[query-plan-semi-apply]] -== Semi Apply -// SemiApply +=== Semi Apply The `SemiApply` operator tests for the presence of a pattern predicate, and is a variation of the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[`Apply`] operator. If the right-hand side operator yields at least one row, the row from the left-hand side operator is yielded by the `SemiApply` operator. @@ -2746,7 +2687,7 @@ Total database accesses: 142, total allocated memory: 64 [[query-plan-anti-semi-apply]] -== Anti Semi Apply +=== Anti Semi Apply // AntiSemiApply The `AntiSemiApply` operator tests for the absence of a pattern, and is a variation of the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[`Apply`] operator. @@ -2802,28 +2743,28 @@ Total database accesses: 166, total allocated memory: 976 ====== -[[query-plan-transaction-apply]] -== TransactionApply -// TransactionApply -`TransactionApply` works like the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[`Apply`] operator but will commit the current transaction after a specified number of rows. -.TransactionApply -====== +[[query-plan-let-semi-apply]] +=== Let Semi Apply -[NOTE] -The below query uses a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause] to import variables into the `CALL` subquery. +The `LetSemiApply` operator tests for the presence of a pattern predicate, and is a variation of the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[`Apply`] operator. +When a query contains multiple pattern predicates separated with `OR`, `LetSemiApply` will be used to evaluate the first of these. +It will record the result of evaluating the predicate but will leave any filtering to another operator. +In the example, `LetSemiApply` will be used to check for the presence of the `FRIENDS_WITH` relationship from each person. + + +.LetSemiApply +====== .Query [source, cypher] ---- PROFILE -LOAD CSV FROM 'https://neo4j.com/docs/cypher-refcard/3.3/csv/artists.csv' AS line -CALL (line) { - CREATE (a: Artist {name: line[0]}) - RETURN a -} IN TRANSACTIONS OF 100 ROWS -RETURN a; +CYPHER runtime=slotted +MATCH (other:Person) +WHERE (other)-[:FRIENDS_WITH]->(:Person) OR (other)-[:WORKS_IN]->(:Location) +RETURN other.name ---- .Query Plan @@ -2831,164 +2772,44 @@ RETURN a; ---- Planner COST -Runtime PIPELINED +Runtime SLOTTED Runtime version {neo4j-version} -Batch size 128 - -+-------------------+----+--------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-------------------+----+--------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | 0 | a | 10 | 4 | 8 | 0 | | | | -| | +----+--------------------------------------------------+----------------+------+---------+----------------+ | | | -| +TransactionApply | 1 | IN TRANSACTIONS OF $autoint_1 ROWS ON ERROR FAIL | 10 | 4 | 0 | 2152 | 0/0 | 2.036 | Fused in Pipeline 3 | -| |\ +----+--------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| | +Create | 2 | (a:Artist {name: line[$autoint_0]}) | 10 | 4 | 16 | | | | | -| | | +----+--------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +Argument | 3 | line | 10 | 4 | 0 | 3472 | 0/0 | 32.746 | Fused in Pipeline 2 | -| | +----+--------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +LoadCSV | 4 | line | 10 | 4 | 0 | 328 | | | In Pipeline 1 | -+-------------------+----+--------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++--------------------+-----------------------------------------+----------------+------+---------+------------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | ++--------------------+-----------------------------------------+----------------+------+---------+------------------------+ +| +ProduceResults | `other.name` | 13 | 14 | 0 | 0/0 | +| | +-----------------------------------------+----------------+------+---------+------------------------+ +| +Projection | other.name AS `other.name` | 13 | 14 | 14 | 1/0 | +| | +-----------------------------------------+----------------+------+---------+------------------------+ +| +SelectOrSemiApply | anon_9 | 14 | 14 | 0 | 0/0 | +| |\ +-----------------------------------------+----------------+------+---------+------------------------+ +| | +Filter | anon_7:Location | 14 | 0 | 4 | 0/0 | +| | | +-----------------------------------------+----------------+------+---------+------------------------+ +| | +Expand(All) | (other)-[anon_6:WORKS_IN]->(anon_7) | 14 | 4 | 15 | 8/0 | +| | | +-----------------------------------------+----------------+------+---------+------------------------+ +| | +Argument | other | 14 | 4 | 0 | 0/0 | +| | +-----------------------------------------+----------------+------+---------+------------------------+ +| +LetSemiApply | | 14 | 14 | 0 | 0/0 | +| |\ +-----------------------------------------+----------------+------+---------+------------------------+ +| | +Filter | anon_5:Person | 12 | 0 | 10 | 0/0 | +| | | +-----------------------------------------+----------------+------+---------+------------------------+ +| | +Expand(All) | (other)-[anon_4:FRIENDS_WITH]->(anon_5) | 12 | 10 | 51 | 28/0 | +| | | +-----------------------------------------+----------------+------+---------+------------------------+ +| | +Argument | other | 14 | 14 | 0 | 0/0 | +| | +-----------------------------------------+----------------+------+---------+------------------------+ +| +NodeByLabelScan | other:Person | 14 | 14 | 35 | 1/0 | ++--------------------+-----------------------------------------+----------------+------+---------+------------------------+ -Total database accesses: 24, total allocated memory: 5472 +Total database accesses: 165, total allocated memory: 64 ---- ====== -[[query-plan-anti]] -== Anti -// Anti - -The `Anti` operator tests for the absence of a pattern. -If there are incoming rows, the `Anti` operator will yield no rows. -If there are no incoming rows, the `Anti` operator will yield a single row. - - -.Anti -====== - -.Query -[source, cypher] ----- -PROFILE -CYPHER runtime=pipelined -MATCH - (me:Person {name: 'me'}), - (other:Person) -WHERE NOT (me)-[:FRIENDS_WITH]->(other) -RETURN other.name ----- - -.Query Plan -[role="queryplan", subs="attributes+"] ----- -Planner COST - -Runtime PIPELINED - -Runtime version {neo4j-version} - -Batch size 128 - -+-------------------+--------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-------------------+--------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | `other.name` | 4 | 12 | 0 | | 0/0 | 0.068 | | -| | +--------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | -| +Projection | other.name AS `other.name` | 4 | 12 | 24 | | 2/0 | 0.111 | In Pipeline 4 | -| | +--------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +Apply | | 4 | 12 | 0 | | 0/0 | | | -| |\ +--------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| | +Anti | | 4 | 12 | 0 | 1256 | 0/0 | 0.084 | In Pipeline 4 | -| | | +--------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| | +Limit | 1 | 11 | 2 | 0 | 752 | | | | -| | | +--------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +Expand(Into) | (me)-[anon_2:FRIENDS_WITH]->(other) | 1 | 2 | 81 | 2632 | | | | -| | | +--------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +Argument | me, other | 14 | 14 | 0 | 3192 | 1/0 | 0.904 | Fused in Pipeline 3 | -| | +--------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +CartesianProduct | | 14 | 14 | 0 | 3672 | | 1.466 | In Pipeline 2 | -| |\ +--------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| | +NodeByLabelScan| other:Person | 14 | 14 | 35 | | | | | -| | +--------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +NodeIndexSeek | RANGE INDEX me:Person(name) WHERE name = $autostring_0 | 1 | 1 | 2 | 120 | 0/1 | 0.493 | In Pipeline 0 | -+-------------------+--------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ - -Total database accesses: 178, total allocated memory: 6744 ----- - -====== - - -[[query-plan-let-semi-apply]] -== Let Semi Apply -// LetSemiApply - -The `LetSemiApply` operator tests for the presence of a pattern predicate, and is a variation of the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[`Apply`] operator. -When a query contains multiple pattern predicates separated with `OR`, `LetSemiApply` will be used to evaluate the first of these. -It will record the result of evaluating the predicate but will leave any filtering to another operator. -In the example, `LetSemiApply` will be used to check for the presence of the `FRIENDS_WITH` relationship from each person. - - -.LetSemiApply -====== - -.Query -[source, cypher] ----- -PROFILE -CYPHER runtime=slotted -MATCH (other:Person) -WHERE (other)-[:FRIENDS_WITH]->(:Person) OR (other)-[:WORKS_IN]->(:Location) -RETURN other.name ----- - -.Query Plan -[role="queryplan", subs="attributes+"] ----- -Planner COST - -Runtime SLOTTED - -Runtime version {neo4j-version} - -+--------------------+-----------------------------------------+----------------+------+---------+------------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | -+--------------------+-----------------------------------------+----------------+------+---------+------------------------+ -| +ProduceResults | `other.name` | 13 | 14 | 0 | 0/0 | -| | +-----------------------------------------+----------------+------+---------+------------------------+ -| +Projection | other.name AS `other.name` | 13 | 14 | 14 | 1/0 | -| | +-----------------------------------------+----------------+------+---------+------------------------+ -| +SelectOrSemiApply | anon_9 | 14 | 14 | 0 | 0/0 | -| |\ +-----------------------------------------+----------------+------+---------+------------------------+ -| | +Filter | anon_7:Location | 14 | 0 | 4 | 0/0 | -| | | +-----------------------------------------+----------------+------+---------+------------------------+ -| | +Expand(All) | (other)-[anon_6:WORKS_IN]->(anon_7) | 14 | 4 | 15 | 8/0 | -| | | +-----------------------------------------+----------------+------+---------+------------------------+ -| | +Argument | other | 14 | 4 | 0 | 0/0 | -| | +-----------------------------------------+----------------+------+---------+------------------------+ -| +LetSemiApply | | 14 | 14 | 0 | 0/0 | -| |\ +-----------------------------------------+----------------+------+---------+------------------------+ -| | +Filter | anon_5:Person | 12 | 0 | 10 | 0/0 | -| | | +-----------------------------------------+----------------+------+---------+------------------------+ -| | +Expand(All) | (other)-[anon_4:FRIENDS_WITH]->(anon_5) | 12 | 10 | 51 | 28/0 | -| | | +-----------------------------------------+----------------+------+---------+------------------------+ -| | +Argument | other | 14 | 14 | 0 | 0/0 | -| | +-----------------------------------------+----------------+------+---------+------------------------+ -| +NodeByLabelScan | other:Person | 14 | 14 | 35 | 1/0 | -+--------------------+-----------------------------------------+----------------+------+---------+------------------------+ - -Total database accesses: 165, total allocated memory: 64 ----- - -====== - - -[[query-plan-let-anti-semi-apply]] -== Let Anti Semi Apply -// LetAntiSemiApply +[[query-plan-let-anti-semi-apply]] +=== Let Anti Semi Apply The `LetAntiSemiApply` operator tests for the absence of a pattern, and is a variation of the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[`Apply`] operator. When a query contains multiple negated pattern predicates -- i.e. predicates separated with `OR`, where at least one predicate contains `NOT` -- `LetAntiSemiApply` will be used to evaluate the first of these. @@ -3050,8 +2871,7 @@ Total database accesses: 142, total allocated memory: 64 [[query-plan-select-or-semi-apply]] -== Select Or Semi Apply -// SelectOrSemiApply +=== Select Or Semi Apply The `SelectOrSemiApply` operator tests for the presence of a pattern predicate and evaluates a predicate, and is a variation of the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[`Apply`] operator. @@ -3109,8 +2929,7 @@ Total database accesses: 148, total allocated memory: 2952 [[query-plan-select-or-anti-semi-apply]] -== Select Or Anti Semi Apply -// SelectOrAntiSemiApply +=== Select Or Anti Semi Apply The `SelectOrAntiSemiApply` operator is used to evaluate `OR` between a predicate and a negative pattern predicate (i.e. a pattern predicate preceded with `NOT`), and is a variation of the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[`Apply`] operator. If the predicate returns `true`, the pattern predicate is not tested. @@ -3169,8 +2988,7 @@ Total database accesses: 136, total allocated memory: 4208 [[query-plan-let-select-or-semi-apply]] -== Let Select Or Semi Apply -// LetSelectOrSemiApply +=== Let Select Or Semi Apply The `LetSelectOrSemiApply` operator is planned for pattern predicates that are combined with other predicates using `OR`. This is a variation of the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[`Apply`] operator. @@ -3231,8 +3049,7 @@ Total database accesses: 179, total allocated memory: 64 [[query-plan-let-select-or-anti-semi-apply]] -== Let Select Or Anti Semi Apply -// LetSelectOrAntiSemiApply +=== Let Select Or Anti Semi Apply The `LetSelectOrAntiSemiApply` operator is planned for negated pattern predicates -- i.e. pattern predicates preceded with `NOT` -- that are combined with other predicates using `OR`. This operator is a variation of the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[`Apply`] operator. @@ -3291,29 +3108,80 @@ Total database accesses: 208, total allocated memory: 64 ====== +[[query-plan-roll-up-apply]] +=== Roll Up Apply -[[query-plan-merge]] -== Merge -// ConditionalApply -- changed in 4.3 to Merge. -// AntiConditionalApply -- removed in 4.3 (by Merge). -// Merge +The `RollUpApply` operator is used to execute an expression which takes as input a pattern, and returns a list with content from the matched pattern; for example, when using a pattern expression or pattern comprehension in a query. +This operator is a variation of the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[`Apply`] operator. -The `Merge` operator will either read or create nodes and/or relationships. -If matches are found it will execute the provided `ON MATCH` operations foreach incoming row. -If no matches are found instead nodes and relationships are created and all `ON CREATE` operations are run. +.RollUpApply +====== + +.Query +[source, cypher] +---- +PROFILE +CYPHER runtime=slotted +MATCH (p:Person) +RETURN p.name, [(p)-[:WORKS_IN]->(location) | location.name] AS cities +---- +.Query Plan +[role="queryplan", subs="attributes+"] +---- +Planner COST -.Merge +Runtime SLOTTED + +Runtime version {neo4j-version} + ++-----------------+-----------------------------------+----------------+------+---------+------------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | ++-----------------+-----------------------------------+----------------+------+---------+------------------------+ +| +ProduceResults | `p.name`, cities | 14 | 14 | 0 | 0/0 | +| | +-----------------------------------+----------------+------+---------+------------------------+ +| +Projection | p.name AS `p.name` | 14 | 14 | 14 | 0/0 | +| | +-----------------------------------+----------------+------+---------+------------------------+ +| +RollUpApply | cities, anon_0 | 14 | 14 | 0 | 0/0 | +| |\ +-----------------------------------+----------------+------+---------+------------------------+ +| | +Projection | location.name AS anon_0 | 15 | 15 | 15 | 1/0 | +| | | +-----------------------------------+----------------+------+---------+------------------------+ +| | +Expand(All) | (p)-[anon_2:WORKS_IN]->(location) | 15 | 15 | 53 | 28/0 | +| | | +-----------------------------------+----------------+------+---------+------------------------+ +| | +Argument | p | 14 | 14 | 0 | 0/0 | +| | +-----------------------------------+----------------+------+---------+------------------------+ +| +NodeByLabelScan| p:Person | 14 | 14 | 35 | 1/0 | ++-----------------+-----------------------------------+----------------+------+---------+------------------------+ + +Total database accesses: 153, total allocated memory: 64 +---- + +====== + + + +[[query-plan-transaction-apply]] +=== TransactionApply + +`TransactionApply` works like the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[`Apply`] operator but will commit the current transaction after a specified number of rows. + +.TransactionApply ====== +[NOTE] +The below query uses a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause] to import variables into the `CALL` subquery. + .Query [source, cypher] ---- PROFILE -MERGE (p:Person {name: 'Andy'}) -ON MATCH SET p.existed = true -ON CREATE SET p.existed = false +LOAD CSV FROM 'https://neo4j.com/docs/cypher-refcard/3.3/csv/artists.csv' AS line +CALL (line) { + CREATE (a: Artist {name: line[0]}) + RETURN a +} IN TRANSACTIONS OF 100 ROWS +RETURN a; ---- .Query Plan @@ -3323,37 +3191,37 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+-----------------+-------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-----------------+-------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | | 1 | 0 | 0 | | | | | -| | +-------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +EmptyResult | | 1 | 0 | 0 | | | | | -| | +-------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +Merge | CREATE (p:Person {name: $autostring_0}), ON MATCH SET p.existed = true, | 1 | 1 | 2 | | | | | -| | | ON CREATE SET p.existed = false | | | | | | | | -| | +-------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +NodeIndexSeek | RANGE INDEX p:Person(name) WHERE name = $autostring_0 | 1 | 1 | 2 | 120 | 2/1 | 0.749 | Fused in Pipeline 0 | -+-----------------+-------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++-------------------+----+--------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-------------------+----+--------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | a | 10 | 4 | 8 | 0 | | | | +| | +----+--------------------------------------------------+----------------+------+---------+----------------+ | | | +| +TransactionApply | 1 | IN TRANSACTIONS OF $autoint_1 ROWS ON ERROR FAIL | 10 | 4 | 0 | 2152 | 0/0 | 2.036 | Fused in Pipeline 3 | +| |\ +----+--------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| | +Create | 2 | (a:Artist {name: line[$autoint_0]}) | 10 | 4 | 16 | | | | | +| | | +----+--------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Argument | 3 | line | 10 | 4 | 0 | 3472 | 0/0 | 32.746 | Fused in Pipeline 2 | +| | +----+--------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +LoadCSV | 4 | line | 10 | 4 | 0 | 328 | | | In Pipeline 1 | ++-------------------+----+--------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 4, total allocated memory: 184 +Total database accesses: 24, total allocated memory: 5472 ---- ====== -[[query-plan-locking-merge]] -== Locking Merge -// LockingMerge +[[query-plan-argument]] +=== Argument -The `LockingMerge` operator is similar to the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-merge[`Merge`] operator but will lock the start and end node when creating a relationship if necessary. +The `Argument` operator indicates the variable to be used as an argument to the right-hand side of an xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[`Apply`] operator. -.LockingMerge +.Argument ====== .Query @@ -3398,25 +3266,28 @@ Total database accesses: 15, total allocated memory: 2232 ====== +[[query-plan-argument-tracker]] +=== Argument Tracker -[[query-plan-roll-up-apply]] -== Roll Up Apply -// RollUpApply - -The `RollUpApply` operator is used to execute an expression which takes as input a pattern, and returns a list with content from the matched pattern; for example, when using a pattern expression or pattern comprehension in a query. -This operator is a variation of the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[`Apply`] operator. - +The `ArgumentTracker` operator is used to ensure row-by-row semantics. +This restricts the xref:planning-and-tuning/runtimes/index.adoc[Cypher runtime] to not batch operations in larger chunks. -.RollUpApply +.ArgumentTracker ====== +[NOTE] +The below query uses a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause] to import variables into the `CALL` subquery. + .Query [source, cypher] ---- PROFILE -CYPHER runtime=slotted -MATCH (p:Person) -RETURN p.name, [(p)-[:WORKS_IN]->(location) | location.name] AS cities +MATCH (s:Person {name: 'me'}) +CALL (s) { + SET s.seen = coalesce(s.seen + 1,1) + RETURN s.seen AS result +} +RETURN result; ---- .Query Plan @@ -3424,50 +3295,54 @@ RETURN p.name, [(p)-[:WORKS_IN]->(location) | location.name] AS cities ---- Planner COST -Runtime SLOTTED +Runtime PIPELINED Runtime version {neo4j-version} -+-----------------+-----------------------------------+----------------+------+---------+------------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | -+-----------------+-----------------------------------+----------------+------+---------+------------------------+ -| +ProduceResults | `p.name`, cities | 14 | 14 | 0 | 0/0 | -| | +-----------------------------------+----------------+------+---------+------------------------+ -| +Projection | p.name AS `p.name` | 14 | 14 | 14 | 0/0 | -| | +-----------------------------------+----------------+------+---------+------------------------+ -| +RollUpApply | cities, anon_0 | 14 | 14 | 0 | 0/0 | -| |\ +-----------------------------------+----------------+------+---------+------------------------+ -| | +Projection | location.name AS anon_0 | 15 | 15 | 15 | 1/0 | -| | | +-----------------------------------+----------------+------+---------+------------------------+ -| | +Expand(All) | (p)-[anon_2:WORKS_IN]->(location) | 15 | 15 | 53 | 28/0 | -| | | +-----------------------------------+----------------+------+---------+------------------------+ -| | +Argument | p | 14 | 14 | 0 | 0/0 | -| | +-----------------------------------+----------------+------+---------+------------------------+ -| +NodeByLabelScan| p:Person | 14 | 14 | 35 | 1/0 | -+-----------------+-----------------------------------+----------------+------+---------+------------------------+ ++--------------------+----+---------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++--------------------+----+---------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | result | 1 | 1 | 0 | 0 | | | | +| | +----+---------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +Apply | 1 | | 1 | 0 | 0 | | | | | +| |\ +----+---------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +ArgumentTracker | 7 | | 1 | 0 | 0 | 736 | | | | +| | | +----+---------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Projection | 2 | s.seen AS result | 1 | 1 | 2 | | | | | +| | | +----+---------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Eager | 3 | read/set conflict for property: seen (Operator: 4 vs 2) | 1 | 1 | 0 | 976 | 0/0 | 0.298 | Fused in Pipeline 2 | +| | | +----+---------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| | +SetProperty | 4 | s.seen = coalesce(s.seen + $autoint_1, $autoint_2) | 1 | 1 | 2 | | | | | +| | | +----+---------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Argument | 5 | s | 1 | 1 | 0 | 2408 | 2/0 | 1.734 | Fused in Pipeline 1 | +| | +----+---------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +NodeIndexSeek | 6 | RANGE INDEX s:Person(name) WHERE name = $autostring_0 | 1 | 1 | 2 | 368 | 1/0 | 0.183 | In Pipeline 0 | ++--------------------+----+---------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 153, total allocated memory: 64 +Total database accesses: 6, total allocated memory: 4136 ---- ====== -[[query-plan-argument]] -== Argument -// Argument +[[query-plan-cartesian-product]] +=== Cartesian Product -The `Argument` operator indicates the variable to be used as an argument to the right-hand side of an xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[`Apply`] operator. +The `CartesianProduct` operator produces a cartesian product of the two inputs -- each row coming from the left child operator will be combined with all the rows from the right child operator. +`CartesianProduct` generally exhibits bad performance and ought to be avoided if possible. -.Argument +.CartesianProduct ====== .Query [source, cypher] ---- PROFILE -MATCH (s:Person {name: 'me'}) -MERGE (s)-[:FRIENDS_WITH]->(s) +MATCH + (p:Person), + (t:Team) +RETURN p, t ---- .Query Plan @@ -3477,111 +3352,55 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+-----------------+----+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-----------------+----+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | 0 | | 1 | 0 | 0 | | | | | -| | +----+-------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +EmptyResult | 1 | | 1 | 0 | 0 | | | | | -| | +----+-------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +Apply | 2 | | 1 | 1 | 0 | | | | | -| |\ +----+-------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +LockingMerge | 3 | CREATE (s)-[anon_0:FRIENDS_WITH]->(s), LOCK(s) | 1 | 1 | 1 | | | | | -| | | +----+-------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +Expand(Into) | 4 | (s)-[anon_0:FRIENDS_WITH]->(s) | 0 | 0 | 10 | 904 | | | | -| | | +----+-------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +Argument | 5 | s | 1 | 3 | 0 | 2280 | 2/0 | 0.460 | Fused in Pipeline 1 | -| | +----+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +NodeIndexSeek | 6 | RANGE INDEX s:Person(name) WHERE name = $autostring_0 | 1 | 1 | 2 | 376 | 1/0 | 0.211 | In Pipeline 0 | -+-----------------+----+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++--------------------+----------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++--------------------+----------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | p, t | 140 | 140 | 0 | | 2/0 | 1.917 | | +| | +----------+----------------+------+---------+----------------+------------------------+-----------+ | +| +CartesianProduct | | 140 | 140 | 0 | 1736 | | 1.209 | In Pipeline 2 | +| |\ +----------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| | +NodeByLabelScan | t:Team | 10 | 10 | 11 | 136 | 1/0 | 1,145 | In Pipeline 1 | +| | +----------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +NodeByLabelScan | p:Person | 15 | 15 | 16 | 120 | 1/0 | 0,409 | In Pipeline 0 | ++--------------------+----------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 15, total allocated memory: 2232 +Total database accesses: 142, total allocated memory: 1816 ---- ====== -[[query-plan-argument-tracker]] -== Argument Tracker -// ArgumentTracker - -The `ArgumentTracker` operator is used to ensure row-by-row semantics. -This restricts the xref:planning-and-tuning/runtimes/index.adoc[Cypher runtime] to not batch operations in larger chunks. - -.ArgumentTracker -====== - -[NOTE] -The below query uses a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause] to import variables into the `CALL` subquery. - -.Query -[source, cypher] ----- -PROFILE -MATCH (s:Person {name: 'me'}) -CALL (s) { - SET s.seen = coalesce(s.seen + 1,1) - RETURN s.seen AS result -} -RETURN result; ----- - -.Query Plan -[role="queryplan", subs="attributes+"] ----- -Planner COST - -Runtime PIPELINED - -Runtime version {neo4j-version} - -+--------------------+----+---------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+--------------------+----+---------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | 0 | result | 1 | 1 | 0 | 0 | | | | -| | +----+---------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +Apply | 1 | | 1 | 0 | 0 | | | | | -| |\ +----+---------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +ArgumentTracker | 7 | | 1 | 0 | 0 | 736 | | | | -| | | +----+---------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +Projection | 2 | s.seen AS result | 1 | 1 | 2 | | | | | -| | | +----+---------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +Eager | 3 | read/set conflict for property: seen (Operator: 4 vs 2) | 1 | 1 | 0 | 976 | 0/0 | 0.298 | Fused in Pipeline 2 | -| | | +----+---------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| | +SetProperty | 4 | s.seen = coalesce(s.seen + $autoint_1, $autoint_2) | 1 | 1 | 2 | | | | | -| | | +----+---------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +Argument | 5 | s | 1 | 1 | 0 | 2408 | 2/0 | 1.734 | Fused in Pipeline 1 | -| | +----+---------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +NodeIndexSeek | 6 | RANGE INDEX s:Person(name) WHERE name = $autostring_0 | 1 | 1 | 2 | 368 | 1/0 | 0.183 | In Pipeline 0 | -+--------------------+----+---------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ - -Total database accesses: 6, total allocated memory: 4136 ----- -====== +[[execution-plans-operators-hash-join-general]] +=== Hash joins in general +Hash joins have two inputs: the build input and probe input. +The query planner assigns these roles so that the smaller of the two inputs is the build input. +The build input is pulled in eagerly, and is used to build a probe table. +Once this is complete, the probe table is checked for each row coming from the probe input side. -// --- expand operators --- +In query plans, the build input is always the left operator, and the probe input the right operator. -[[query-plan-expand-all]] -== Expand All -// Expand(All) +[[query-plan-node-hash-join]] +=== Node Hash Join -Given a start node, and depending on the pattern relationship, the `Expand(All)` operator will traverse incoming or outgoing relationships. +The `NodeHashJoin` operator is a variation of the xref::planning-and-tuning/operators/operators-detail.adoc#execution-plans-operators-hash-join-general[hash join]. +`NodeHashJoin` executes the hash join on node ids. +As primitive types and arrays can be used, it can be done very efficiently. -.Expand(All) +.NodeHashJoin ====== - .Query [source, cypher] ---- PROFILE -MATCH (p:Person {name: 'me'})-[:FRIENDS_WITH]->(fof) -RETURN fof +MATCH (bob:Person {name: 'Bob'})-[:WORKS_IN]->(loc)<-[:WORKS_IN]-(matt:Person {name: 'Mattias'}) +USING JOIN ON loc +RETURN loc.name ---- .Query Plan @@ -3591,44 +3410,56 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+-----------------+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-----------------+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | fof | 1 | 2 | 0 | | | | | -| | +-------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +Expand(All) | (p)-[anon_0:FRIENDS_WITH]->(fof) | 1 | 2 | 5 | | | | | -| | +-------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +NodeIndexSeek | RANGE INDEX p:Person(name) WHERE name = $autostring_0 | 1 | 1 | 2 | 120 | 4/1 | 1.137 | Fused in Pipeline 0 | -+-----------------+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++------------------+----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++------------------+----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | `loc.name` | 10 | 0 | 0 | | 0/0 | 0.000 | | +| | +----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | +| +Projection | loc.name AS `loc.name` | 10 | 0 | 0 | | 0/0 | 0.000 | | +| | +----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | +| +Filter | not anon_0 = anon_1 | 10 | 0 | 0 | | 0/0 | 0.000 | | +| | +----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | +| +NodeHashJoin | loc | 10 | 0 | 0 | 3688 | | 0.053 | In Pipeline 2 | +| |\ +----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| | +Expand(All) | (matt)-[anon_1:WORKS_IN]->(loc) | 19 | 0 | 0 | | | | | +| | | +----------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +NodeIndexSeek | RANGE INDEX matt:Person(name) WHERE name = $autostring_1 | 1 | 0 | 1 | 120 | 1/0 | 0.288 | Fused in Pipeline 1 | +| | +----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +Expand(All) | (bob)-[anon_0:WORKS_IN]->(loc) | 19 | 1 | 4 | | | | | +| | +----------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +NodeIndexSeek | RANGE INDEX bob:Person(name) WHERE name = $autostring_0 | 1 | 1 | 2 | 120 | 3/0 | 0.556 | Fused in Pipeline 0 | ++------------------+----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 7, total allocated memory: 184 +Total database accesses: 7, total allocated memory: 3888 ---- ====== -[[query-plan-expand-into]] -== Expand Into -// Expand(Into) +[[query-plan-value-hash-join]] +=== Value Hash Join -When both the start and end node have already been found, the `Expand(Into)` operator is used to find all relationships connecting the two nodes. -As both the start and end node of the relationship are already in scope, the node with the smallest degree will be used. -This can make a noticeable difference when dense nodes appear as end points. +The `ValueHashJoin` operator is a variation of the xref::planning-and-tuning/operators/operators-detail.adoc#execution-plans-operators-hash-join-general[hash join]. +This operator allows for arbitrary values to be used as the join key. +It is most frequently used to solve predicates of the form: `n.prop1 = m.prop2` (i.e. equality predicates between two property columns). -.Expand(Into) +.ValueHashJoin ====== .Query [source, cypher] ---- PROFILE -MATCH (p:Person {name: 'me'})-[:FRIENDS_WITH]->(fof)-->(p) -RETURN fof +MATCH + (p:Person), + (q:Person) +WHERE p.age = q.age +RETURN p, q ---- .Query Plan @@ -3638,49 +3469,50 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+-----------------+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-----------------+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | fof | 0 | 0 | 0 | | | | | -| | +-------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +Filter | not anon_1 = anon_0 | 0 | 0 | 0 | | | | | -| | +-------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +Expand(Into) | (p)-[anon_0:FRIENDS_WITH]->(fof) | 0 | 0 | 6 | 896 | | | | -| | +-------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +Expand(All) | (p)<-[anon_1]-(fof) | 1 | 1 | 5 | | | | | -| | +-------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +NodeIndexSeek | RANGE INDEX p:Person(name) WHERE name = $autostring_0 | 1 | 1 | 2 | 120 | 4/1 | 0.546 | Fused in Pipeline 0 | -+-----------------+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++-------------------+---------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-------------------+---------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | p, q | 10 | 0 | 0 | | 0/0 | 0.000 | | +| | +---------------+----------------+------+---------+----------------+------------------------+-----------+ | +| +ValueHashJoin | p.age = q.age| 10 | 0 | 0 | 344 | | | In Pipeline 2 | +| |\ +---------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| | +NodeByLabelScan| q:Person | 15 | 0 | 0 | 120 | 0/0 | 0,000 | In Pipeline 1 | +| | +---------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +NodeByLabelScan | p:Person | 15 | 15 | 16 | 120 | 1/0 | 0,211 | In Pipeline 0 | ++-------------------+---------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 13, total allocated memory: 976 +Total database accesses: 71, total allocated memory: 664 ---- ====== -[[query-plan-optional-expand-all]] -== Optional Expand All -// OptionalExpand(All) +[[query-plan-node-left-right-outer-hash-join]] +=== Node Left/Right Outer Hash Join -The `OptionalExpand(All)` operator is analogous to xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-expand-all[Expand(All)], apart from when no relationships match the direction, type and property predicates. -In this situation, `OptionalExpand(all)` will return a single row with the relationship and end node set to `null`. + +The `NodeLeftOuterHashJoin` and `NodeRightOuterHashJoin` operators are variations of the xref::planning-and-tuning/operators/operators-detail.adoc#execution-plans-operators-hash-join-general[hash join]. +The query below can be planned with either a left or a right outer join. +The decision depends on the cardinalities of the left-hand and right-hand sides; i.e. how many rows would be returned, respectively, for `(a:Person)` and `(a)-->(b:Person)`. +If `(a:Person)` returns fewer results than `(a)-->(b:Person)`, a left outer join -- indicated by `NodeLeftOuterHashJoin` -- is planned. +On the other hand, if `(a:Person)` returns more results than `(a)-->(b:Person)`, a right outer join -- indicated by `NodeRightOuterHashJoin` -- is planned instead. -.OptionalExpand(All) +.NodeRightOuterHashJoin ====== .Query [source, cypher] ---- PROFILE -MATCH (p:Person) -OPTIONAL MATCH (p)-[works_in:WORKS_IN]->(l) - WHERE works_in.duration > 180 -RETURN p, l +MATCH (a:Person) +OPTIONAL MATCH (a)-->(b:Person) +USING JOIN ON a +RETURN a.name, b.name ---- .Query Plan @@ -3690,46 +3522,62 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+----------------------+-------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+----------------------+-------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | p, l | 14 | 15 | 1 | | | | | -| | +-------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +OptionalExpand(All) | (p)-[works_in:WORKS_IN]->(l) WHERE works_in.duration > $autoint_0 | 14 | 15 | 53 | | | | | -| | +-------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +NodeByLabelScan | p:Person | 14 | 14 | 15 | 120 | 5/0 | 1,233 | Fused in Pipeline 0 | -+----------------------+-------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++-------------------------+------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-------------------------+------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | `a.name`, `b.name` | 14 | 16 | 0 | | 0/0 | 0.102 | | +| | +------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | +| +Projection | cache[a.name] AS `a.name`, cache[b.name] AS `b.name` | 14 | 16 | 8 | | 0/0 | 0.055 | | +| | +------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | +| +NodeRightOuterHashJoin | a | 14 | 16 | 0 | 4232 | | 0.269 | In Pipeline 2 | +| |\ +------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| | +NodeByLabelScan | a:Person | 15 | 15 | 16 | 120 | 1/0 | 0,049 | In Pipeline 1 | +| | +------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +CacheProperties | cache[b.name], cache[a.name] | 13 | 13 | 39 | | | | | +| | +------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +Expand(All) | (b)<-[anon_0]-(a) | 13 | 13 | 55 | | | | | +| | +------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +NodeByLabelScan | b:Person | 15 | 15 | 16 | 120 | 5/0 | 1,150 | Fused in Pipeline 0 | ++-------------------------+------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 125, total allocated memory: 184 +Total database accesses: 211, total allocated memory: 4312 ---- ====== -[[query-plan-optional-expand-into]] -== Optional Expand Into -// OptionalExpand(Into) +[[traversal-operators]] +== Traversal operators -The `OptionalExpand(Into)` operator is analogous to xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-expand-into[Expand(Into)], apart from when no matching relationships are found. -In this situation, `OptionalExpand(Into)` will return a single row with the relationship and end node set to `null`. -As both the start and end node of the relationship are already in scope, the node with the smallest degree will be used. -This can make a noticeable difference when dense nodes appear as end points. +Traversal operators enable complex graph traversals by defining how nodes and relationships are connected in a given pattern. +They allow Cypher to express and match various pattern types, such as xref:patterns/fixed-length-patterns.adoc[fixed-length patterns], xref:patterns/variable-length-patterns.adoc[variable-length patterns], xref:patterns/shortest-paths.adoc[shortest paths], and xref:patterns/non-linear-patterns.adoc[non-linear patterns]. -.OptionalExpand(Into) +[[query-plan-anti]] +=== Anti + +The `Anti` operator tests for the absence of a pattern. +If there are incoming rows, the `Anti` operator will yield no rows. +If there are no incoming rows, the `Anti` operator will yield a single row. + + +.Anti ====== .Query [source, cypher] ---- PROFILE -MATCH (p:Person)-[works_in:WORKS_IN]->(l) -OPTIONAL MATCH (l)-->(p) -RETURN p +CYPHER runtime=pipelined +MATCH + (me:Person {name: 'me'}), + (other:Person) +WHERE NOT (me)-[:FRIENDS_WITH]->(other) +RETURN other.name ---- .Query Plan @@ -3739,43 +3587,57 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+-----------------------+------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-----------------------+------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | p | 15 | 15 | 0 | | | | | -| | +------------------------------+----------------+------+---------+----------------+ | | | -| +OptionalExpand(Into) | (l)-[anon_0]->(p) | 15 | 15 | 105 | 3360 | | | | -| | +------------------------------+----------------+------+---------+----------------+ | | | -| +Expand(All) | (p)-[works_in:WORKS_IN]->(l) | 15 | 15 | 39 | | | | | -| | +------------------------------+----------------+------+---------+----------------+ | | | -| +NodeByLabelScan | p:Person | 14 | 14 | 15 | 120 | 7/0 | 3,925 | Fused in Pipeline 0 | -+-----------------------+--- --------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++-------------------+--------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-------------------+--------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | `other.name` | 4 | 12 | 0 | | 0/0 | 0.068 | | +| | +--------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | +| +Projection | other.name AS `other.name` | 4 | 12 | 24 | | 2/0 | 0.111 | In Pipeline 4 | +| | +--------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +Apply | | 4 | 12 | 0 | | 0/0 | | | +| |\ +--------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| | +Anti | | 4 | 12 | 0 | 1256 | 0/0 | 0.084 | In Pipeline 4 | +| | | +--------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| | +Limit | 1 | 11 | 2 | 0 | 752 | | | | +| | | +--------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Expand(Into) | (me)-[anon_2:FRIENDS_WITH]->(other) | 1 | 2 | 81 | 2632 | | | | +| | | +--------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Argument | me, other | 14 | 14 | 0 | 3192 | 1/0 | 0.904 | Fused in Pipeline 3 | +| | +--------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +CartesianProduct | | 14 | 14 | 0 | 3672 | | 1.466 | In Pipeline 2 | +| |\ +--------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| | +NodeByLabelScan| other:Person | 14 | 14 | 35 | | | | | +| | +--------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +NodeIndexSeek | RANGE INDEX me:Person(name) WHERE name = $autostring_0 | 1 | 1 | 2 | 120 | 0/1 | 0.493 | In Pipeline 0 | ++-------------------+--------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 215, total allocated memory: 3440 +Total database accesses: 178, total allocated memory: 6744 ---- ====== -[[query-plan-varlength-expand-all]] -== VarLength Expand All -// VarLengthExpand(All) +[[query-plan-optional]] +=== Optional -Given a start node, the `VarLengthExpand(All)` operator will traverse variable-length and quantified relationships. +The `Optional` operator is used to solve some xref::clauses/optional-match.adoc[OPTIONAL MATCH] queries. +It will pull data from its source, simply passing it through if any data exists. +However, if no data is returned by its source, `Optional` will yield a single row with all columns set to `null`. -.VarLengthExpand(All) +.Optional ====== .Query [source, cypher] ---- PROFILE -MATCH (p:Person)-[:FRIENDS_WITH *1..2]-(q:Person) +MATCH (p:Person {name: 'me'}) +OPTIONAL MATCH (q:Person {name: 'Lulu'}) RETURN p, q ---- @@ -3786,44 +3648,44 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+-----------------------+-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-----------------------+-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | p, q | 40 | 48 | 0 | | | | | -| | +-----------------------------------+----------------+------+---------+----------------+ | | | -| +Filter | q:Person | 40 | 48 | 96 | | | | | -| | +-----------------------------------+----------------+------+---------+----------------+ | | | -| +VarLengthExpand(All) | (p)-[anon_0:FRIENDS_WITH*..2]-(q) | 40 | 48 | 151 | 128 | | | | -| | +-----------------------------------+----------------+------+---------+----------------+ | | | -| +NodeByLabelScan | p:Person | 14 | 14 | 15 | 120 | 6/0 | 10,457 | Fused in Pipeline 0 | -+-----------------------+-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++------------------+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++------------------+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ +| +ProduceResults | p, q | 1 | 1 | 0 | | 2/0 | 0.079 | In Pipeline 2 | +| | +-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ +| +Apply | | 1 | 1 | 0 | | 0/0 | 0.096 | | +| |\ +-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ +| | +Optional | p | 1 | 1 | 0 | 768 | 0/0 | 0.043 | In Pipeline 2 | +| | | +-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ +| | +NodeIndexSeek | RANGE INDEX q:Person(name) WHERE name = $autostring_1 | 1 | 0 | 1 | 2152 | 1/0 | 0.098 | In Pipeline 1 | +| | +-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ +| +NodeIndexSeek | RANGE INDEX p:Person(name) WHERE name = $autostring_0 | 1 | 1 | 2 | 120 | 0/1 | 0.364 | In Pipeline 0 | ++------------------+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ -Total database accesses: 318, total allocated memory: 208 +Total database accesses: 3, total allocated memory: 3000 ---- ====== +[[query-plan-expand-all]] +=== Expand All -[[query-plan-varlength-expand-into]] -== VarLength Expand Into -// VarLengthExpand(Into) - -When both the start and end node have already been found, the `VarLengthExpand(Into)` operator is used to find all variable-length and quantified relationships connecting the two nodes. +Given a start node, and depending on the pattern relationship, the `Expand(All)` operator will traverse incoming or outgoing relationships. -.VarLengthExpand(Into) +.Expand(All) ====== .Query [source, cypher] ---- PROFILE -MATCH (p:Person)-[:FRIENDS_WITH *1..2]-(p:Person) -RETURN p +MATCH (p:Person {name: 'me'})-[:FRIENDS_WITH]->(fof) +RETURN fof ---- .Query Plan @@ -3837,46 +3699,39 @@ Runtime version {neo4j-version} Batch size 128 -+------------------------+-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+------------------------+-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | p | 3 | 4 | 0 | | | | | -| | +-----------------------------------+----------------+------+---------+----------------+ | | | -| +VarLengthExpand(Into) | (p)-[anon_0:FRIENDS_WITH*..2]-(p) | 3 | 4 | 151 | 128 | | | | -| | +-----------------------------------+----------------+------+---------+----------------+ | | | -| +NodeByLabelScan | p:Person | 14 | 14 | 15 | 120 | 6/0 | 0,797 | Fused in Pipeline 0 | -+------------------------+-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ - ++-----------------+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-----------------+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | fof | 1 | 2 | 0 | | | | | +| | +-------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +Expand(All) | (p)-[anon_0:FRIENDS_WITH]->(fof) | 1 | 2 | 5 | | | | | +| | +-------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +NodeIndexSeek | RANGE INDEX p:Person(name) WHERE name = $autostring_0 | 1 | 1 | 2 | 120 | 4/1 | 1.137 | Fused in Pipeline 0 | ++-----------------+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 222, total allocated memory: 192 +Total database accesses: 7, total allocated memory: 184 ---- ====== -[[query-plan-varlength-expand-pruning]] -== VarLength Expand Pruning -// VarLengthExpand(Pruning) - -Given a start node, the `VarLengthExpand(Pruning)` operator will traverse variable-length and quantified relationships much like the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-varlength-expand-all[`VarLengthExpand(All)`] operator. -However, as an optimization, some paths will not be explored if they are guaranteed to produce an end node that has already been found (by means of a previous path traversal). - -This kind of expand is only planned when: - -* The individual paths are not of interest. -* The relationships have an upper bound. +[[query-plan-expand-into]] +=== Expand Into -The `VarLengthExpand(Pruning)` operator guarantees that all the end nodes produced will be unique. +When both the start and end node have already been found, the `Expand(Into)` operator is used to find all relationships connecting the two nodes. +As both the start and end node of the relationship are already in scope, the node with the smallest degree will be used. +This can make a noticeable difference when dense nodes appear as end points. -.VarLengthExpand(Pruning) +.Expand(Into) ====== + .Query [source, cypher] ---- PROFILE -MATCH (p:Person)-[:FRIENDS_WITH *3..4]-(q:Person) -RETURN DISTINCT p, q +MATCH (p:Person {name: 'me'})-[:FRIENDS_WITH]->(fof)-->(p) +RETURN fof ---- .Query Plan @@ -3890,48 +3745,44 @@ Runtime version {neo4j-version} Batch size 128 -+---------------------------+----+------------------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Ordered by | Pipeline | -+---------------------------+----+------------------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------+ -| +ProduceResults | 0 | p, q | 0 | 0 | 0 | | 0/0 | 0.005 | | | -| | +----+------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | | -| +OrderedDistinct | 1 | p, q | 0 | 0 | 0 | 40 | 0/0 | 0.014 | | | -| | +----+------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | | -| +Filter | 2 | q:Person | 0 | 0 | 0 | | 0/0 | 0.014 | | | -| | +----+------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | | -| +VarLengthExpand(Pruning) | 3 | (p)-[:FRIENDS_WITH*3..4]-(q) | 1 | 0 | 15 | 400 | | | | In Pipeline 1 | -| | +----+------------------------------+----------------+------+---------+----------------+------------------------+-----------+ +---------------+ -| +NodeByLabelScan | 4 | p:Person | 14 | 14 | 15 | 120 | 1/0 | 0.020 | p ASC | In Pipeline 0 | -+---------------------------+----+------------------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------+ ++-----------------+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-----------------+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | fof | 0 | 0 | 0 | | | | | +| | +-------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +Filter | not anon_1 = anon_0 | 0 | 0 | 0 | | | | | +| | +-------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +Expand(Into) | (p)-[anon_0:FRIENDS_WITH]->(fof) | 0 | 0 | 6 | 896 | | | | +| | +-------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +Expand(All) | (p)<-[anon_1]-(fof) | 1 | 1 | 5 | | | | | +| | +-------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +NodeIndexSeek | RANGE INDEX p:Person(name) WHERE name = $autostring_0 | 1 | 1 | 2 | 120 | 4/1 | 0.546 | Fused in Pipeline 0 | ++-----------------+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 30, total allocated memory: 480 +Total database accesses: 13, total allocated memory: 976 ---- ====== -[[query-plan-breadth-first-varlength-expand-pruning-bfs-all]] -== Breadth First VarLength Expand Pruning -// VarLengthExpand(Pruning,BFS) - - -Given a start node, the `VarLengthExpand(Pruning,BFS,All)` operator traverses variable-length and quantified relationships much like the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-varlength-expand-all[`VarLengthExpand(All)`] operator. -However, as an optimization, it instead performs a breadth-first search (BFS) and while expanding, some paths are not explored if they are guaranteed to produce an end node that has already been found (by means of a previous path traversal). -This is only used in cases where the individual paths are not of interest. +[[query-plan-optional-expand-all]] +=== Optional Expand All -This kind of expand is only planned when: +The `OptionalExpand(All)` operator is analogous to xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-expand-all[Expand(All)], apart from when no relationships match the direction, type and property predicates. +In this situation, `OptionalExpand(all)` will return a single row with the relationship and end node set to `null`. -* The individual paths are not of interest. -* The lower bound is either `0` or `1` (default). -This operator guarantees that all the end nodes produced are unique. +.OptionalExpand(All) +====== .Query [source, cypher] ---- PROFILE -MATCH (p:Person)-[:FRIENDS_WITH *..4]-(q:Person) -RETURN DISTINCT p, q +MATCH (p:Person) +OPTIONAL MATCH (p)-[works_in:WORKS_IN]->(l) + WHERE works_in.duration > 180 +RETURN p, l ---- .Query Plan @@ -3945,42 +3796,41 @@ Runtime version {neo4j-version} Batch size 128 -+-----------------------------------+----+------------------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Ordered by | Pipeline | -+-----------------------------------+----+------------------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ -| +ProduceResults | 0 | p, q | 12 | 0 | 0 | 0 | | | | | -| | +----+------------------------------+----------------+------+---------+----------------+ | | | | -| +OrderedDistinct | 1 | p, q | 12 | 0 | 0 | 40 | | | | | -| | +----+------------------------------+----------------+------+---------+----------------+ | | | | -| +Filter | 2 | q:Person | 13 | 0 | 0 | | | | | | -| | +----+------------------------------+----------------+------+---------+----------------+ | | | | -| +VarLengthExpand(Pruning,BFS,All) | 3 | (p)-[:FRIENDS_WITH*..4]-(q) | 13 | 0 | 38 | 952 | | | | | -| | +----+------------------------------+----------------+------+---------+----------------+ | | | | -| +NodeByLabelScan | 4 | p:Person | 10 | 10 | 11 | 248 | 3/0 | 4.662 | p ASC | Fused in Pipeline 0 | -+-----------------------------------+----+------------------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ ++----------------------+-------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++----------------------+-------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | p, l | 14 | 15 | 1 | | | | | +| | +-------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +OptionalExpand(All) | (p)-[works_in:WORKS_IN]->(l) WHERE works_in.duration > $autoint_0 | 14 | 15 | 53 | | | | | +| | +-------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +NodeByLabelScan | p:Person | 14 | 14 | 15 | 120 | 5/0 | 1,233 | Fused in Pipeline 0 | ++----------------------+-------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 49, total allocated memory: 1200 +Total database accesses: 125, total allocated memory: 184 ---- +====== -[[query-plan-repeat]] -== Repeat (Trail) -// Repeat(Trail) -Given a start node, the `Repeat(Trail)` operator will traverse xref::patterns/variable-length-patterns.adoc#quantified-path-patterns[quantified path patterns] that cannot be solved (or solved efficiently) with the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-varlength-expand-all[`VarLengthExpand(All)`] operator. -Similar to an xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[`Apply`] operator, it takes a single row from the left-hand side and applies the operators on the right-hand side. -In contrast to `Apply`, however, it repeatedly applies these operators in accordance with the quantifiers on the quantified path pattern. -In the following example, the operator will repeat twice and produce rows for both repetitions. +[[query-plan-optional-expand-into]] +=== Optional Expand Into + +The `OptionalExpand(Into)` operator is analogous to xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-expand-into[Expand(Into)], apart from when no matching relationships are found. +In this situation, `OptionalExpand(Into)` will return a single row with the relationship and end node set to `null`. +As both the start and end node of the relationship are already in scope, the node with the smallest degree will be used. +This can make a noticeable difference when dense nodes appear as end points. + -.Repeat(Trail) +.OptionalExpand(Into) ====== .Query [source, cypher] ---- PROFILE -MATCH (me:Person) ((a)-[:FRIENDS_WITH]-(b)-[:FRIENDS_WITH]-(c) WHERE a.name <> b.name AND a.name <> c.name AND b.name <> c.name){1,2} (friend:Person) -RETURN me, friend +MATCH (p:Person)-[works_in:WORKS_IN]->(l) +OPTIONAL MATCH (l)-->(p) +RETURN p ---- .Query Plan @@ -3994,53 +3844,39 @@ Runtime version {neo4j-version} Batch size 128 -+------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | 0 | me, friend | 2 | 34 | 136 | 0 | | | | -| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +Filter | 1 | friend:Person | 2 | 34 | 68 | | | | | -| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +NullifyMetadata | 9 | | 2 | 34 | 0 | | | | | -| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +Repeat(Trail) | 2 | (me) (...){1, 2} (friend) | 2 | 34 | 0 | 29792 | 0/0 | 1.696 | Fused in Pipeline 2 | -| |\ +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| | +Filter | 3 | NOT anon_5 = anon_3 AND (NOT cache[a.name] = cache[c.name] AND NOT cache[b.name] = cache[c.name]) AN | 1 | 34 | 92 | | | | | -| | | | | D isRepeatTrailUnique(anon_5) | | | | | | | | -| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +Expand(All) | 4 | (b)-[anon_5:FRIENDS_WITH]-(c) | 3 | 92 | 138 | | | | | -| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +Filter | 5 | NOT cache[a.name] = cache[b.name] AND isRepeatTrailUnique(anon_3) | 5 | 46 | 198 | | | | | -| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +Expand(All) | 6 | (a)-[anon_3:FRIENDS_WITH]-(b) | 10 | 66 | 100 | | | | | -| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +Argument | 7 | a | 15 | 34 | 0 | 15672 | 2/0 | 3.245 | Fused in Pipeline 1 | -| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +NodeByLabelScan | 8 | me:Person | 14 | 14 | 15 | 376 | 1/0 | 0.107 | In Pipeline 0 | -+------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++-----------------------+------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-----------------------+------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | p | 15 | 15 | 0 | | | | | +| | +------------------------------+----------------+------+---------+----------------+ | | | +| +OptionalExpand(Into) | (l)-[anon_0]->(p) | 15 | 15 | 105 | 3360 | | | | +| | +------------------------------+----------------+------+---------+----------------+ | | | +| +Expand(All) | (p)-[works_in:WORKS_IN]->(l) | 15 | 15 | 39 | | | | | +| | +------------------------------+----------------+------+---------+----------------+ | | | +| +NodeByLabelScan | p:Person | 14 | 14 | 15 | 120 | 7/0 | 3,925 | Fused in Pipeline 0 | ++-----------------------+--- --------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 747, total allocated memory: 45832 +Total database accesses: 215, total allocated memory: 3440 ---- ====== -[[query-plan-nullify-metadata]] -== Nullify Metadata -// NullifyMetadata +[[query-plan-varlength-expand-all]] +=== VarLength Expand All -`NullifyMetadata` is responsible for cleaning up the state produced by xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-repeat[`Repeat(Trail)`]. -It is only planned directly after `Repeat(Trail)`. +Given a start node, the `VarLengthExpand(All)` operator will traverse variable-length and quantified relationships. -.NullifyMetadata + +.VarLengthExpand(All) ====== .Query [source, cypher] ---- PROFILE -MATCH (me:Person) ((a)-[:FRIENDS_WITH]-(b)-[:FRIENDS_WITH]-(c) WHERE a.name <> b.name AND a.name <> c.name AND b.name <> c.name){1,2} (friend:Person) -RETURN me, friend +MATCH (p:Person)-[:FRIENDS_WITH *1..2]-(q:Person) +RETURN p, q ---- .Query Plan @@ -4054,54 +3890,39 @@ Runtime version {neo4j-version} Batch size 128 -+------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | 0 | me, friend | 2 | 34 | 136 | 0 | | | | -| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +Filter | 1 | friend:Person | 2 | 34 | 68 | | | | | -| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +NullifyMetadata | 9 | | 2 | 34 | 0 | | | | | -| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +Repeat(Trail) | 2 | (me) (...){1, 2} (friend) | 2 | 34 | 0 | 29792 | 0/0 | 1.696 | Fused in Pipeline 2 | -| |\ +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| | +Filter | 3 | NOT anon_5 = anon_3 AND (NOT cache[a.name] = cache[c.name] AND NOT cache[b.name] = cache[c.name]) AN | 1 | 34 | 92 | | | | | -| | | | | D isRepeatTrailUnique(anon_5) | | | | | | | | -| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +Expand(All) | 4 | (b)-[anon_5:FRIENDS_WITH]-(c) | 3 | 92 | 138 | | | | | -| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +Filter | 5 | NOT cache[a.name] = cache[b.name] AND isRepeatTrailUnique(anon_3) | 5 | 46 | 198 | | | | | -| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +Expand(All) | 6 | (a)-[anon_3:FRIENDS_WITH]-(b) | 10 | 66 | 100 | | | | | -| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +Argument | 7 | a | 15 | 34 | 0 | 15672 | 2/0 | 3.245 | Fused in Pipeline 1 | -| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +NodeByLabelScan | 8 | me:Person | 14 | 14 | 15 | 376 | 1/0 | 0.107 | In Pipeline 0 | -+------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++-----------------------+-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-----------------------+-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | p, q | 40 | 48 | 0 | | | | | +| | +-----------------------------------+----------------+------+---------+----------------+ | | | +| +Filter | q:Person | 40 | 48 | 96 | | | | | +| | +-----------------------------------+----------------+------+---------+----------------+ | | | +| +VarLengthExpand(All) | (p)-[anon_0:FRIENDS_WITH*..2]-(q) | 40 | 48 | 151 | 128 | | | | +| | +-----------------------------------+----------------+------+---------+----------------+ | | | +| +NodeByLabelScan | p:Person | 14 | 14 | 15 | 120 | 6/0 | 10,457 | Fused in Pipeline 0 | ++-----------------------+-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 747, total allocated memory: 45832 +Total database accesses: 318, total allocated memory: 208 ---- ====== -[[query-plan-assert-same-node]] -== Assert Same Node -// AssertSameNode -The `AssertSameNode` operator is used to ensure that no node property uniqueness constraints are violated in the slotted and interpreted runtime. -The example looks for the presence of a team node with the supplied name and id, and if one does not exist, it will be created. -Owing to the existence of two node property uniqueness constraints on `:Team(name)` and `:Team(id)`, any node that would be found by the `UniqueIndexSeek` operator must be the very same node or the constraints would be violated. +[[query-plan-varlength-expand-into]] +=== VarLength Expand Into +When both the start and end node have already been found, the `VarLengthExpand(Into)` operator is used to find all variable-length and quantified relationships connecting the two nodes. -.AssertSameNode + +.VarLengthExpand(Into) ====== .Query [source, cypher] ---- PROFILE -CYPHER runtime=slotted -MERGE (t:Team {name: 'Engineering', id: 42}) +MATCH (p:Person)-[:FRIENDS_WITH *1..2]-(p:Person) +RETURN p ---- .Query Plan @@ -4109,52 +3930,52 @@ MERGE (t:Team {name: 'Engineering', id: 42}) ---- Planner COST -Runtime SLOTTED +Runtime PIPELINED Runtime version {neo4j-version} -+---------------------------------+-------------------------------------------------------+----------------+------+---------+------------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | -+---------------------------------+-------------------------------------------------------+----------------+------+---------+------------------------+ -| +ProduceResults | | 1 | 0 | 0 | 0/0 | -| | +-------------------------------------------------------+----------------+------+---------+------------------------+ -| +EmptyResult | | 1 | 0 | 0 | 0/0 | -| | +-------------------------------------------------------+----------------+------+---------+------------------------+ -| +Merge | CREATE (t:Team {name: $autostring_0, id: $autoint_1}) | 1 | 1 | 0 | 0/0 | -| | +-------------------------------------------------------+----------------+------+---------+------------------------+ -| +AssertSameNode | t | 0 | 1 | 0 | 0/0 | -| |\ +-------------------------------------------------------+----------------+------+---------+------------------------+ -| | +NodeUniqueIndexSeek(Locking) | UNIQUE t:Team(id) WHERE id = $autoint_1 | 1 | 1 | 1 | 0/1 | -| | +-------------------------------------------------------+----------------+------+---------+------------------------+ -| +NodeUniqueIndexSeek(Locking) | UNIQUE t:Team(name) WHERE name = $autostring_0 | 1 | 1 | 1 | 0/1 | -+---------------------------------+-------------------------------------------------------+----------------+------+---------+------------------------+ +Batch size 128 -Total database accesses: 2, total allocated memory: 64 ++------------------------+-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++------------------------+-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | p | 3 | 4 | 0 | | | | | +| | +-----------------------------------+----------------+------+---------+----------------+ | | | +| +VarLengthExpand(Into) | (p)-[anon_0:FRIENDS_WITH*..2]-(p) | 3 | 4 | 151 | 128 | | | | +| | +-----------------------------------+----------------+------+---------+----------------+ | | | +| +NodeByLabelScan | p:Person | 14 | 14 | 15 | 120 | 6/0 | 0,797 | Fused in Pipeline 0 | ++------------------------+-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ + + +Total database accesses: 222, total allocated memory: 192 ---- ====== +[[query-plan-varlength-expand-pruning]] +=== VarLength Expand Pruning +// VarLengthExpand(Pruning) -[[query-plan-assert-same-relationship]] -== Assert Same Relationship -// AssertSameRelationship +Given a start node, the `VarLengthExpand(Pruning)` operator will traverse variable-length and quantified relationships much like the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-varlength-expand-all[`VarLengthExpand(All)`] operator. +However, as an optimization, some paths will not be explored if they are guaranteed to produce an end node that has already been found (by means of a previous path traversal). -The `AssertSameRelationship` operator is used to ensure that no relationship property uniqueness constraints are violated in the slotted and interpreted runtime. -The example looks for the presence of a `WORKS_IN` relationship with the supplied `id` and `badgeNumber`. -If it can't be found, then it will be created. -Owing to the existence of two property uniqueness constraints on `:WORKS_IN(id)` and `:WORKS_IN(badgeNumber)`, any relationship that would be found by the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-directed-relationship-unique-index-seek[`DirectedRelationshipUniqueIndexSeek`] operator must be the very same relationship or the constraints would be violated. +This kind of expand is only planned when: + +* The individual paths are not of interest. +* The relationships have an upper bound. +The `VarLengthExpand(Pruning)` operator guarantees that all the end nodes produced will be unique. -.AssertSameRelationship -====== +.VarLengthExpand(Pruning) +====== .Query [source, cypher] ---- PROFILE -CYPHER runtime=slotted -MERGE (person)-[work:WORKS_IN {id: 0, badgeNumber: 4332}]->(location) +MATCH (p:Person)-[:FRIENDS_WITH *3..4]-(q:Person) +RETURN DISTINCT p, q ---- .Query Plan @@ -4162,51 +3983,54 @@ MERGE (person)-[work:WORKS_IN {id: 0, badgeNumber: 4332}]->(location) ---- Planner COST -Runtime SLOTTED +Runtime PIPELINED Runtime version {neo4j-version} -+-------------------------------------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+------------------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | -+-------------------------------------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+------------------------+ -| +ProduceResults | 0 | | 1 | 0 | 0 | 0/0 | -| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+------------------------+ -| +EmptyResult | 1 | | 1 | 0 | 0 | 0/0 | -| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+------------------------+ -| +Merge | 2 | CREATE (person), (location), (person)-[work:WORKS_IN {id: $autoint_0, badgeNumber: $autoint_1}]->(lo | 1 | 1 | 0 | 0/0 | -| | | | cation) | | | | | -| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+------------------------+ -| +AssertSameRelationship | 3 | work | 0 | 1 | 0 | 0/0 | -| |\ +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+------------------------+ -| | +DirectedRelationshipUniqueIndexSeek(Locking) | 4 | RANGE INDEX (person)-[work:WORKS_IN(badgeNumber)]->(location) WHERE badgeNumber = $autoint_1 | 1 | 1 | 1 | 0/1 | -| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+------------------------+ -| +DirectedRelationshipUniqueIndexSeek(Locking) | 5 | RANGE INDEX (person)-[work:WORKS_IN(id)]->(location) WHERE id = $autoint_0 | 1 | 1 | 1 | 1/1 | -+-------------------------------------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+------------------------+ +Batch size 128 -Total database accesses: 2, total allocated memory: 64 ++---------------------------+----+------------------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Ordered by | Pipeline | ++---------------------------+----+------------------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------+ +| +ProduceResults | 0 | p, q | 0 | 0 | 0 | | 0/0 | 0.005 | | | +| | +----+------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | | +| +OrderedDistinct | 1 | p, q | 0 | 0 | 0 | 40 | 0/0 | 0.014 | | | +| | +----+------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | | +| +Filter | 2 | q:Person | 0 | 0 | 0 | | 0/0 | 0.014 | | | +| | +----+------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | | +| +VarLengthExpand(Pruning) | 3 | (p)-[:FRIENDS_WITH*3..4]-(q) | 1 | 0 | 15 | 400 | | | | In Pipeline 1 | +| | +----+------------------------------+----------------+------+---------+----------------+------------------------+-----------+ +---------------+ +| +NodeByLabelScan | 4 | p:Person | 14 | 14 | 15 | 120 | 1/0 | 0.020 | p ASC | In Pipeline 0 | ++---------------------------+----+------------------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------+ + +Total database accesses: 30, total allocated memory: 480 ---- ====== -// DropResult -- removed in 4.3 +[[query-plan-breadth-first-varlength-expand-pruning-bfs-all]] +=== Breadth First VarLength Expand Pruning +// VarLengthExpand(Pruning,BFS) -[[query-plan-empty-result]] -== Empty Result -// EmptyResult +Given a start node, the `VarLengthExpand(Pruning,BFS,All)` operator traverses variable-length and quantified relationships much like the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-varlength-expand-all[`VarLengthExpand(All)`] operator. +However, as an optimization, it instead performs a breadth-first search (BFS) and while expanding, some paths are not explored if they are guaranteed to produce an end node that has already been found (by means of a previous path traversal). +This is only used in cases where the individual paths are not of interest. -The `EmptyResult` operator eagerly loads all incoming data and discards it. +This kind of expand is only planned when: +* The individual paths are not of interest. +* The lower bound is either `0` or `1` (default). -.EmptyResult -====== +This operator guarantees that all the end nodes produced are unique. .Query [source, cypher] ---- PROFILE -CREATE (:Person) +MATCH (p:Person)-[:FRIENDS_WITH *..4]-(q:Person) +RETURN DISTINCT p, q ---- .Query Plan @@ -4220,39 +4044,42 @@ Runtime version {neo4j-version} Batch size 128 -+-----------------+-----------------+----------------+------+---------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-----------------+-----------------+----------------+------+---------+------------------------+-----------+---------------------+ -| +ProduceResults | | 1 | 0 | 0 | | | | -| | +-----------------+----------------+------+---------+ | | | -| +EmptyResult | | 1 | 0 | 0 | | | | -| | +-----------------+----------------+------+---------+ | | | -| +Create | (anon_0:Person) | 1 | 1 | 1 | 0/0 | 0.000 | Fused in Pipeline 0 | -+-----------------+-----------------+----------------+------+---------+------------------------+-----------+---------------------+ ++-----------------------------------+----+------------------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Ordered by | Pipeline | ++-----------------------------------+----+------------------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ +| +ProduceResults | 0 | p, q | 12 | 0 | 0 | 0 | | | | | +| | +----+------------------------------+----------------+------+---------+----------------+ | | | | +| +OrderedDistinct | 1 | p, q | 12 | 0 | 0 | 40 | | | | | +| | +----+------------------------------+----------------+------+---------+----------------+ | | | | +| +Filter | 2 | q:Person | 13 | 0 | 0 | | | | | | +| | +----+------------------------------+----------------+------+---------+----------------+ | | | | +| +VarLengthExpand(Pruning,BFS,All) | 3 | (p)-[:FRIENDS_WITH*..4]-(q) | 13 | 0 | 38 | 952 | | | | | +| | +----+------------------------------+----------------+------+---------+----------------+ | | | | +| +NodeByLabelScan | 4 | p:Person | 10 | 10 | 11 | 248 | 3/0 | 4.662 | p ASC | Fused in Pipeline 0 | ++-----------------------------------+----+------------------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ -Total database accesses: 1, total allocated memory: 184 +Total database accesses: 49, total allocated memory: 1200 ---- -====== - -[[query-plan-produce-results]] -== Produce Results -// ProduceResults - -The `ProduceResults` operator prepares the result so that it is consumable by the user, such as transforming internal values to user values. -It is present in every single query that returns data to the user, and has little bearing on performance optimisation. +[[query-plan-repeat]] +=== Repeat (Trail) +// Repeat(Trail) +Given a start node, the `Repeat(Trail)` operator will traverse xref::patterns/variable-length-patterns.adoc#quantified-path-patterns[quantified path patterns] that cannot be solved (or solved efficiently) with the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-varlength-expand-all[`VarLengthExpand(All)`] operator. +Similar to an xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[`Apply`] operator, it takes a single row from the left-hand side and applies the operators on the right-hand side. +In contrast to `Apply`, however, it repeatedly applies these operators in accordance with the quantifiers on the quantified path pattern. +In the following example, the operator will repeat twice and produce rows for both repetitions. -.ProduceResults +.Repeat(Trail) ====== .Query [source, cypher] ---- PROFILE -MATCH (n) -RETURN n +MATCH (me:Person) ((a)-[:FRIENDS_WITH]-(b)-[:FRIENDS_WITH]-(c) WHERE a.name <> b.name AND a.name <> c.name AND b.name <> c.name){1,2} (friend:Person) +RETURN me, friend ---- .Query Plan @@ -4266,37 +4093,52 @@ Runtime version {neo4j-version} Batch size 128 -+-----------------+---------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-----------------+---------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | n | 35 | 35 | 0 | | | | | -| | +---------+----------------+------+---------+----------------+ | | | -| +AllNodesScan | n | 35 | 35 | 36 | 120 | 3/0 | 0.508 | Fused in Pipeline 0 | -+-----------------+---------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | me, friend | 2 | 34 | 136 | 0 | | | | +| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +Filter | 1 | friend:Person | 2 | 34 | 68 | | | | | +| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +NullifyMetadata | 9 | | 2 | 34 | 0 | | | | | +| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +Repeat(Trail) | 2 | (me) (...){1, 2} (friend) | 2 | 34 | 0 | 29792 | 0/0 | 1.696 | Fused in Pipeline 2 | +| |\ +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| | +Filter | 3 | NOT anon_5 = anon_3 AND (NOT cache[a.name] = cache[c.name] AND NOT cache[b.name] = cache[c.name]) AN | 1 | 34 | 92 | | | | | +| | | | | D isRepeatTrailUnique(anon_5) | | | | | | | | +| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Expand(All) | 4 | (b)-[anon_5:FRIENDS_WITH]-(c) | 3 | 92 | 138 | | | | | +| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Filter | 5 | NOT cache[a.name] = cache[b.name] AND isRepeatTrailUnique(anon_3) | 5 | 46 | 198 | | | | | +| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Expand(All) | 6 | (a)-[anon_3:FRIENDS_WITH]-(b) | 10 | 66 | 100 | | | | | +| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Argument | 7 | a | 15 | 34 | 0 | 15672 | 2/0 | 3.245 | Fused in Pipeline 1 | +| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +NodeByLabelScan | 8 | me:Person | 14 | 14 | 15 | 376 | 1/0 | 0.107 | In Pipeline 0 | ++------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 36, total allocated memory: 184 +Total database accesses: 747, total allocated memory: 45832 ---- ====== -[[query-plan-load-csv]] -== Load CSV -// LoadCSV - -The `LoadCSV` operator loads data from a CSV source into the query. -It is used whenever the xref::clauses/load-csv.adoc[LOAD CSV] clause is used in a query. +[[query-plan-nullify-metadata]] +=== Nullify Metadata +`NullifyMetadata` is responsible for cleaning up the state produced by xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-repeat[`Repeat(Trail)`]. +It is only planned directly after `Repeat(Trail)`. -.LoadCSV +.NullifyMetadata ====== .Query [source, cypher] ---- PROFILE -LOAD CSV FROM 'https://neo4j.com/docs/cypher-refcard/3.3/csv/artists.csv' AS line -RETURN line +MATCH (me:Person) ((a)-[:FRIENDS_WITH]-(b)-[:FRIENDS_WITH]-(c) WHERE a.name <> b.name AND a.name <> c.name AND b.name <> c.name){1,2} (friend:Person) +RETURN me, friend ---- .Query Plan @@ -4310,56 +4152,55 @@ Runtime version {neo4j-version} Batch size 128 -+-----------------+---------+----------------+------+---------+----------------+------------------------+-----------+---------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-----------------+---------+----------------+------+---------+----------------+------------------------+-----------+---------------+ -| +ProduceResults | line | 10 | 4 | 0 | | 0/0 | 0.210 | | -| | +---------+----------------+------+---------+----------------+------------------------+-----------+ | -| +LoadCSV | line | 10 | 4 | 0 | 72 | | | In Pipeline 1 | -+-----------------+---------+----------------+------+---------+----------------+------------------------+-----------+---------------+ ++------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | me, friend | 2 | 34 | 136 | 0 | | | | +| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +Filter | 1 | friend:Person | 2 | 34 | 68 | | | | | +| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +NullifyMetadata | 9 | | 2 | 34 | 0 | | | | | +| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +Repeat(Trail) | 2 | (me) (...){1, 2} (friend) | 2 | 34 | 0 | 29792 | 0/0 | 1.696 | Fused in Pipeline 2 | +| |\ +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| | +Filter | 3 | NOT anon_5 = anon_3 AND (NOT cache[a.name] = cache[c.name] AND NOT cache[b.name] = cache[c.name]) AN | 1 | 34 | 92 | | | | | +| | | | | D isRepeatTrailUnique(anon_5) | | | | | | | | +| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Expand(All) | 4 | (b)-[anon_5:FRIENDS_WITH]-(c) | 3 | 92 | 138 | | | | | +| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Filter | 5 | NOT cache[a.name] = cache[b.name] AND isRepeatTrailUnique(anon_3) | 5 | 46 | 198 | | | | | +| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Expand(All) | 6 | (a)-[anon_3:FRIENDS_WITH]-(b) | 10 | 66 | 100 | | | | | +| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Argument | 7 | a | 15 | 34 | 0 | 15672 | 2/0 | 3.245 | Fused in Pipeline 1 | +| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +NodeByLabelScan | 8 | me:Person | 14 | 14 | 15 | 376 | 1/0 | 0.107 | In Pipeline 0 | ++------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 0, total allocated memory: 184 +Total database accesses: 747, total allocated memory: 45832 ---- ====== +[[query-plan-shortest-path]] +=== Shortest path +// ShortestPath -[[execution-plans-operators-hash-join-general]] -== Hash joins in general - -Hash joins have two inputs: the build input and probe input. -The query planner assigns these roles so that the smaller of the two inputs is the build input. -The build input is pulled in eagerly, and is used to build a probe table. -Once this is complete, the probe table is checked for each row coming from the probe input side. - -In query plans, the build input is always the left operator, and the probe input the right operator. - -There are four hash join operators: - -* xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-node-hash-join[NodeHashJoin] -* xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-value-hash-join[ValueHashJoin] -* xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-node-left-right-outer-hash-join[NodeLeftOuterHashJoin] -* xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-node-left-right-outer-hash-join[NodeRightOuterHashJoin] - - -[[query-plan-node-hash-join]] -== Node Hash Join -// NodeHashJoin - -The `NodeHashJoin` operator is a variation of the xref::planning-and-tuning/operators/operators-detail.adoc#execution-plans-operators-hash-join-general[hash join]. -`NodeHashJoin` executes the hash join on node ids. -As primitive types and arrays can be used, it can be done very efficiently. - +The `ShortestPath` operator finds one or all shortest paths between two previously matched node variables. +This operator is used for the xref:patterns/reference.adoc#shortest-functions[`shortestPath()` and `allShortestPaths`] functions. -.NodeHashJoin +.ShortestPath ====== + .Query [source, cypher] ---- PROFILE -MATCH (bob:Person {name: 'Bob'})-[:WORKS_IN]->(loc)<-[:WORKS_IN]-(matt:Person {name: 'Mattias'}) -USING JOIN ON loc -RETURN loc.name +MATCH + (andy:Person {name: 'Andy'}), + (mattias:Person {name: 'Mattias'}), + p = shortestPath((andy)-[*]-(mattias)) +RETURN p ---- .Query Plan @@ -4373,42 +4214,40 @@ Runtime version {neo4j-version} Batch size 128 -+------------------+----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+------------------+----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | `loc.name` | 10 | 0 | 0 | | 0/0 | 0.000 | | -| | +----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | -| +Projection | loc.name AS `loc.name` | 10 | 0 | 0 | | 0/0 | 0.000 | | -| | +----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | -| +Filter | not anon_0 = anon_1 | 10 | 0 | 0 | | 0/0 | 0.000 | | -| | +----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | -| +NodeHashJoin | loc | 10 | 0 | 0 | 3688 | | 0.053 | In Pipeline 2 | -| |\ +----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| | +Expand(All) | (matt)-[anon_1:WORKS_IN]->(loc) | 19 | 0 | 0 | | | | | -| | | +----------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +NodeIndexSeek | RANGE INDEX matt:Person(name) WHERE name = $autostring_1 | 1 | 0 | 1 | 120 | 1/0 | 0.288 | Fused in Pipeline 1 | -| | +----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +Expand(All) | (bob)-[anon_0:WORKS_IN]->(loc) | 19 | 1 | 4 | | | | | -| | +----------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +NodeIndexSeek | RANGE INDEX bob:Person(name) WHERE name = $autostring_0 | 1 | 1 | 2 | 120 | 3/0 | 0.556 | Fused in Pipeline 0 | -+------------------+----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++---------------------+-------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++---------------------+-------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ +| +ProduceResults | p | 1 | 1 | 0 | | 1/0 | 0.241 | | +| | +-------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | +| +ShortestPath | p = (andy)-[anon_0*]-(mattias) | 1 | 1 | 1 | 1424 | | | In Pipeline 1 | +| | +-------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ +| +MultiNodeIndexSeek | RANGE INDEX andy:Person(name) WHERE name = $autostring_0, | 1 | 1 | 4 | 120 | 1/1 | 0.308 | In Pipeline 0 | +| | RANGE INDEX mattias:Person(name) WHERE name = $autostring_1 | | | | | | | | ++---------------------+-------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ -Total database accesses: 7, total allocated memory: 3888 +Total database accesses: 5, total allocated memory: 1488 ---- ====== +[[query-plan-stateful-shortest-path-into]] +=== StatefulShortestPath(Into) +// StatefulShortestPath(Into) -[[query-plan-value-hash-join]] -== Value Hash Join -// ValueHashJoin - -The `ValueHashJoin` operator is a variation of the xref::planning-and-tuning/operators/operators-detail.adoc#execution-plans-operators-hash-join-general[hash join]. -This operator allows for arbitrary values to be used as the join key. -It is most frequently used to solve predicates of the form: `n.prop1 = m.prop2` (i.e. equality predicates between two property columns). +//// +[source, cypher, role=test-setup] +---- +DROP INDEX range_person_name IF EXISTS; +CREATE CONSTRAINT person_name_unique IF NOT EXISTS FOR (p:Person) REQUIRE (p.name) IS UNIQUE; +---- +//// +The `StatefulShortestPath(Into)` operator finds shortest paths between a start node and a single target node. +It uses a bidirectional breadth-first search (BFS) algorithm, which performs two BFS invocations at the same time, one from the left boundary node and one from the right boundary node. +Once a node is found by both BFS invocations, which indicates that it can be reached from both boundary nodes, the algorithm successfully terminates. +If one of the BFS invocations exhausts its search before intersecting, either because no further nodes can be reached or because the maximum number of hops has been reached, then there is no valid path between the boundary nodes and the algorithm terminates. -.ValueHashJoin +.StatefulShortestPath(Into) ====== .Query @@ -4416,10 +4255,8 @@ It is most frequently used to solve predicates of the form: `n.prop1 = m.prop2` ---- PROFILE MATCH - (p:Person), - (q:Person) -WHERE p.age = q.age -RETURN p, q + p = ALL SHORTEST (chris:Person {name: 'Chris'})(()-[]-()-[]-()){1,}(stefan:Person {name: 'Stefan'}) +RETURN p ---- .Query Plan @@ -4433,47 +4270,43 @@ Runtime version {neo4j-version} Batch size 128 -+-------------------+---------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-------------------+---------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | p, q | 10 | 0 | 0 | | 0/0 | 0.000 | | -| | +---------------+----------------+------+---------+----------------+------------------------+-----------+ | -| +ValueHashJoin | p.age = q.age| 10 | 0 | 0 | 344 | | | In Pipeline 2 | -| |\ +---------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| | +NodeByLabelScan| q:Person | 15 | 0 | 0 | 120 | 0/0 | 0,000 | In Pipeline 1 | -| | +---------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +NodeByLabelScan | p:Person | 15 | 15 | 16 | 120 | 1/0 | 0,211 | In Pipeline 0 | -+-------------------+---------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++-----------------------------+----+--------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-----------------------------+----+--------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ +| +ProduceResults | 0 | p | 2 | 2 | 0 | 0 | 0/0 | 0.039 | | +| | +----+--------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | +| +Projection | 1 | (chris) ((anon_12)-[anon_14]-(anon_13)-[anon_11]-())* (stefan) AS p | 2 | 2 | 0 | | 0/0 | 1.365 | | +| | +----+--------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | +| +StatefulShortestPath(Into) | 2 | SHORTEST 1 GROUPS (chris) ((`anon_5`)-[`anon_6`]-(`anon_7`)-[`anon_8`]-(`anon_9`)){1, } (stefan) | 2 | 2 | 39 | 22237 | 1/0 | 37.376 | In Pipeline 1 | +| | +----+--------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ +| +MultiNodeIndexSeek | 3 | UNIQUE chris:Person(name) WHERE name = $autostring_0, | 1 | 1 | 4 | 376 | 1/1 | 10.245 | In Pipeline 0 | +| | | UNIQUE stefan:Person(name) WHERE name = $autostring_1 | | | | | | | | ++-----------------------------+----+--------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ + +Total database accesses: 43, total allocated memory: 22557 -Total database accesses: 71, total allocated memory: 664 ---- ====== +[[query-plan-stateful-shortest-path-all]] +=== StatefulShortestPath(All) +// StatefulShortestPath(All) -[[query-plan-node-left-right-outer-hash-join]] -== Node Left/Right Outer Hash Join -// NodeLeftOuterHashJoin -// NodeRightOuterHashJoin - -The `NodeLeftOuterHashJoin` and `NodeRightOuterHashJoin` operators are variations of the xref::planning-and-tuning/operators/operators-detail.adoc#execution-plans-operators-hash-join-general[hash join]. -The query below can be planned with either a left or a right outer join. -The decision depends on the cardinalities of the left-hand and right-hand sides; i.e. how many rows would be returned, respectively, for `(a:Person)` and `(a)-->(b:Person)`. -If `(a:Person)` returns fewer results than `(a)-->(b:Person)`, a left outer join -- indicated by `NodeLeftOuterHashJoin` -- is planned. -On the other hand, if `(a:Person)` returns more results than `(a)-->(b:Person)`, a right outer join -- indicated by `NodeRightOuterHashJoin` -- is planned instead. +The `StatefulShortestPath(All)` operator finds shortest paths from a single node to multiple target nodes. +It uses a breadth-first search algorithm. -.NodeRightOuterHashJoin +.StatefulShortestPath(All) ====== .Query [source, cypher] ---- PROFILE -MATCH (a:Person) -OPTIONAL MATCH (a)-->(b:Person) -USING JOIN ON a -RETURN a.name, b.name +MATCH + p = ALL SHORTEST (chris:Person {name:'Chris'})(()-[]-()-[]-()){1,}(location:Location) +RETURN length(p) AS pathLength, location.name AS locationName ---- .Query Plan @@ -4483,37 +4316,41 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+-------------------------+------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-------------------------+------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | `a.name`, `b.name` | 14 | 16 | 0 | | 0/0 | 0.102 | | -| | +------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | -| +Projection | cache[a.name] AS `a.name`, cache[b.name] AS `b.name` | 14 | 16 | 8 | | 0/0 | 0.055 | | -| | +------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | -| +NodeRightOuterHashJoin | a | 14 | 16 | 0 | 4232 | | 0.269 | In Pipeline 2 | -| |\ +------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| | +NodeByLabelScan | a:Person | 15 | 15 | 16 | 120 | 1/0 | 0,049 | In Pipeline 1 | -| | +------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +CacheProperties | cache[b.name], cache[a.name] | 13 | 13 | 39 | | | | | -| | +------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +Expand(All) | (b)<-[anon_0]-(a) | 13 | 13 | 55 | | | | | -| | +------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +NodeByLabelScan | b:Person | 15 | 15 | 16 | 120 | 5/0 | 1,150 | Fused in Pipeline 0 | -+-------------------------+------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++----------------------------+----+----------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++----------------------------+----+----------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ +| +ProduceResults | 0 | pathLength, locationName | 14 | 20 | 0 | 0 | 0/0 | 0.074 | | +| | +----+----------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | +| +Projection | 1 | length((chris) ((anon_12)-[anon_14]-(anon_13)-[anon_11]-())* (location)) AS pathLength, | 14 | 20 | 40 | | 1/0 | 6.828 | | +| | | | location.name AS locationName | | | | | | | | +| | +----+----------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | +| +StatefulShortestPath(All) | 2 | SHORTEST 1 GROUPS (chris) ((`anon_5`)-[`anon_6`]-(`anon_7`)-[`anon_8`]-(`anon_9`)){1, } (location) | 14 | 20 | 179 | 37663 | 1/0 | 52.849 | In Pipeline 1 | +| | | | expanding from: chris | | | | | | | | +| | | | inlined predicates: location:Location | | | | | | | | +| | +----+----------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ +| +NodeUniqueIndexSeek | 3 | UNIQUE chris:Person(name) WHERE name = $autostring_0 | 1 | 1 | 2 | 376 | 0/1 | 9.078 | In Pipeline 0 | ++----------------------------+----+----------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ + +Total database accesses: 221, total allocated memory: 37983 -Total database accesses: 211, total allocated memory: 4312 ---- +//// +[source, cypher, role=test-setup] +---- +DROP CONSTRAINT person_name_unique IF EXISTS; +CREATE RANGE INDEX range_person_name FOR (p:Person) ON (p.name); +---- +//// ====== [[query-plan-triadic-selection]] -== Triadic Selection -// TriadicSelection +=== Triadic Selection The `TriadicSelection` operator is used to solve triangular queries, such as the very common 'find my friends-of-friends that are not already my friend'. It does so by putting all the friends into a set, and uses the set to check if the friends-of-friends are already connected to me. @@ -4570,8 +4407,7 @@ Total database accesses: 246, total allocated memory: 64 [[query-plan-triadic-build]] -== Triadic Build -// TriadicBuild +=== Triadic Build The `TriadicBuild` operator is used in conjunction with xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-triadic-filter[`TriadicFilter`] to solve triangular queries, such as the very common 'find my friend-of-friends that are not already my friend'. These two operators are specific to Pipelined runtime and together perform the same logic as xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-triadic-selection[`TriadicSelection`] does for other runtimes. @@ -4635,8 +4471,7 @@ Total database accesses: 256, total allocated memory: 7376 [[query-plan-triadic-filter]] -== Triadic Filter -// TriadicFilter +=== Triadic Filter The `TriadicFilter` operator is used in conjunction with xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-triadic-build[`TriadicBuild`] to solve triangular queries, such as the very common 'find my friend-of-friends that are not already my friend'. These two operators are specific to Pipelined runtime and together perform the same logic as xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-triadic-selection[`TriadicSelection`] does for other runtimes. @@ -4699,235 +4534,30 @@ Total database accesses: 256, total allocated memory: 7376 ====== -[[query-plan-cartesian-product]] -== Cartesian Product -// CartesianProduct - -The `CartesianProduct` operator produces a cartesian product of the two inputs -- each row coming from the left child operator will be combined with all the rows from the right child operator. -`CartesianProduct` generally exhibits bad performance and ought to be avoided if possible. - - -.CartesianProduct -====== - -.Query -[source, cypher] ----- -PROFILE -MATCH - (p:Person), - (t:Team) -RETURN p, t ----- - -.Query Plan -[role="queryplan", subs="attributes+"] ----- -Planner COST - -Runtime PIPELINED - -Runtime version {neo4j-version} - -Batch size 128 - -+--------------------+----------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+--------------------+----------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | p, t | 140 | 140 | 0 | | 2/0 | 1.917 | | -| | +----------+----------------+------+---------+----------------+------------------------+-----------+ | -| +CartesianProduct | | 140 | 140 | 0 | 1736 | | 1.209 | In Pipeline 2 | -| |\ +----------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| | +NodeByLabelScan | t:Team | 10 | 10 | 11 | 136 | 1/0 | 1,145 | In Pipeline 1 | -| | +----------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +NodeByLabelScan | p:Person | 15 | 15 | 16 | 120 | 1/0 | 0,409 | In Pipeline 0 | -+--------------------+----------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ - -Total database accesses: 142, total allocated memory: 1816 ----- - -====== - - -[[query-plan-foreach]] -== Foreach -// Foreach - -The `Foreach` operator executes a nested loop between the left child operator and the right child operator. -In an analogous manner to the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[Apply] operator, it takes a row from the left-hand side and, using the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-argument[Argument] operator, provides it to the operator tree on the right-hand side. -`Foreach` will yield all the rows coming in from the left-hand side; all results from the right-hand side are pulled in and discarded. - - -.Foreach -====== - -.Query -[source, cypher] ----- -PROFILE -FOREACH (value IN [1,2,3] | CREATE (:Person {age: value})) ----- - -.Query Plan -[role="queryplan", subs="attributes+"] ----- -Planner COST - -Runtime SLOTTED - -Runtime version {neo4j-version} - -+-----------------+---------------------------------------------------------+----------------+------+---------+------------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | -+-----------------+---------------------------------------------------------+----------------+------+---------+------------------------+ -| +ProduceResults | | 1 | 0 | 0 | 0/0 | -| | +---------------------------------------------------------+----------------+------+---------+------------------------+ -| +EmptyResult | | 1 | 0 | 0 | 0/0 | -| | +---------------------------------------------------------+----------------+------+---------+------------------------+ -| +Foreach | value IN [1, 2, 3], CREATE (anon_0:Person {age: value}) | 1 | 1 | 9 | 0/0 | -+-----------------+---------------------------------------------------------+----------------+------+---------+------------------------+ - -Total database accesses: 9, total allocated memory: 64 ----- - -====== - -[[query-plan-transaction-foreach]] -== TransactionForeach -// TransactionForeach - -`TransactionForeach` works like the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-foreach[`Foreach`] operator but will commit the current transaction after a specified number of rows. - -.TransactionForeach -====== - -[NOTE] -The below query uses a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause] to import variables into the `CALL` subquery. - -.Query -[source, cypher] ----- -PROFILE -LOAD CSV FROM 'https://neo4j.com/docs/cypher-refcard/3.3/csv/artists.csv' AS line -CALL (line) { - CREATE (a: Artist {name: line[0]}) -} IN TRANSACTIONS OF 100 ROWS ----- - -.Query Plan -[role="queryplan", subs="attributes+"] ----- -Planner COST - -Runtime PIPELINED - -Runtime version {neo4j-version} - -Batch size 128 - -++---------------------+----+--------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ - | Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | - +---------------------+----+--------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ - | +ProduceResults | 0 | | 10 | 0 | 0 | 0 | | | | - | | +----+--------------------------------------------------+----------------+------+---------+----------------+ | | | - | +EmptyResult | 1 | | 10 | 0 | 0 | | 0/0 | 0.000 | Fused in Pipeline 3 | - | | +----+--------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ - | +TransactionForeach | 2 | IN TRANSACTIONS OF $autoint_1 ROWS ON ERROR FAIL | 10 | 4 | 0 | 4856 | | | | - | |\ +----+--------------------------------------------------+----------------+------+---------+----------------+ | | | - | | +Create | 3 | (a:Artist {name: line[$autoint_0]}) | 10 | 4 | 12 | | | | | - | | | +----+--------------------------------------------------+----------------+------+---------+----------------+ | | | - | | +Argument | 4 | line | 10 | 4 | 0 | 3472 | 0/0 | 0.712 | Fused in Pipeline 2 | - | | +----+--------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ - | +LoadCSV | 5 | line | 10 | 4 | 0 | 328 | | | In Pipeline 1 | - +---------------------+----+--------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ - - Total database accesses: 12, total allocated memory: 5704 ----- - -====== - -[[query-plan-subquery-foreach]] -== SubqueryForeach -// SubqueryForeach - -`SubqueryForeach` works like the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-foreach[`Foreach`]operator but it is only used for executing subqueries. - -.SubqueryForeach -====== - -[NOTE] -The below query uses a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause] to import variables into the `CALL` subquery. - -.Query -[source, cypher] ----- -PROFILE -LOAD CSV FROM 'https://neo4j.com/docs/cypher-refcard/3.3/csv/artists.csv' AS line -CALL (line) { - CREATE (a: Artist {name: line[0]}) -} ----- - -.Query Plan -[role="queryplan", subs="attributes+"] ----- -Planner COST - -Runtime PIPELINED - -Runtime version {neo4j-version} - -Batch size 128 - -+------------------+----+-------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+------------------+----+-------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | 0 | | 10 | 0 | 0 | 0 | | | | -| | +----+-------------------------------------+----------------+------+---------+----------------+ | | | -| +EmptyResult | 1 | | 10 | 0 | 0 | | 0/0 | 0.000 | Fused in Pipeline 3 | -| | +----+-------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +SubqueryForeach | 2 | | 10 | 4 | 0 | 4080 | | | | -| |\ +----+-------------------------------------+----------------+------+---------+----------------+ | | | -| | +Create | 3 | (a:Artist {name: line[$autoint_0]}) | 10 | 4 | 12 | | | | | -| | | +----+-------------------------------------+----------------+------+---------+----------------+ | | | -| | +Argument | 4 | line | 10 | 4 | 0 | 3472 | 0/0 | 0.852 | Fused in Pipeline 2 | -| | +----+-------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +LoadCSV | 5 | line | 10 | 4 | 0 | 328 | | | In Pipeline 1 | -+------------------+----+-------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ - -Total database accesses: 12, total allocated memory: 4928 ----- - -====== - +[[union-operators]] +== Union operators -[[query-plan-eager]] -== Eager -// Eager +Union operators in Cypher combine the results from multiple query parts by merging their rows. +For more information, see the page about the xref:clauses/union.adoc[`UNION`] clause. -The `Eager` operator causes all preceding operators to execute fully, for the whole dataset, before continuing execution. -This is done to ensure isolation between parts of the query plan that might otherwise affect each other. -Values from the graph are fetched in a lazy manner; i.e. a pattern matching might not be fully exhausted before updates are applied. -To maintain correct semantics, the query planner will insert `Eager` operators into the query plan to prevent updates from influencing pattern matching, or other read operations. -This scenario is exemplified by the query below, where the `DELETE` clause would otherwise influence both the `MATCH` clause and the `MERGE` clause. -For more information on how the `Eager` operator can ensure correct semantics, see the section on xref::clauses/clause-composition.adoc[Clause composition]. +[[query-plan-union]] +=== Union -The `Eager` operator can cause high memory usage when importing data or migrating graph structures. -In such cases, the operations should be split into simpler steps; e.g. importing nodes and relationships separately. -Alternatively, the records to be updated can be returned, followed by an update statement. +The `Union` operator concatenates the results from the right child operator with the results from the left child operator. -.Eager +.Union ====== - .Query [source, cypher] ---- PROFILE -MATCH (a:Person {name: 'me'}), (b:Person {name: 'Bob'}) -DETACH DELETE a, b -MERGE (:Person {name: 'me'}) +MATCH (p:Location) + RETURN p.name +UNION ALL +MATCH (p:Country) + RETURN p.name ---- .Query Plan @@ -4941,42 +4571,39 @@ Runtime version {neo4j-version} Batch size 128 -+---------------------+----+------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+---------------------+----+------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | 0 | | 0 | 0 | 0 | 0 | | | | -| | +----+------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +EmptyResult | 1 | | 0 | 0 | 0 | | | | | -| | +----+------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +Apply | 2 | | 0 | 1 | 0 | | | | | -| |\ +----+------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +Merge | 3 | CREATE (anon_0:Person {name: $autostring_2}) | 0 | 1 | 3 | | | | | -| | | +----+------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +NodeIndexSeek | 4 | RANGE INDEX anon_0:Person(name) WHERE name = $autostring_2 | 0 | 0 | 1 | 3304 | 1/0 | 0.663 | Fused in Pipeline 3 | -| | +----+------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +Eager | 5 | read/delete conflict for variable: anon_0 (Operator: 6 vs 4, and 1 more conflicting operators) | 0 | 1 | 0 | 360 | 0/0 | 0.008 | In Pipeline 2 | -| | +----+------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +DetachDelete | 6 | b | 0 | 1 | 4 | | | | | -| | +----+------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +DetachDelete | 7 | a | 0 | 1 | 5 | | | | | -| | +----+------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +Eager | 8 | read/delete conflict for variable: b (Operator: 6 vs 10, and 1 more conflicting operators), | 0 | 1 | 0 | 360 | 1/0 | 0.226 | Fused in Pipeline 1 | -| | | | read/set conflict for label: Person (Operator: 3 vs 10), | | | | | | | | -| | | | read/set conflict for property: name (Operator: 3 vs 10) | | | | | | | | -| | +----+------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +MultiNodeIndexSeek | 9 | RANGE INDEX a:Person(name) WHERE name = $autostring_0, | 0 | 1 | 4 | 376 | 2/0 | 0.218 | In Pipeline 0 | -| | | RANGE INDEX b:Person(name) WHERE name = $autostring_1 | | | | | | | | -+---------------------+----+------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++--------------------+----+--------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++--------------------+----+--------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | `p.name` | 20 | 0 | 0 | | | | | +| | +----+--------------------+----------------+------+---------+----------------+ | | | +| +Union | 1 | | 20 | 0 | 0 | 0 | 0/0 | 0.000 | Fused in Pipeline 2 | +| |\ +----+--------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| | +Projection | 2 | `p.name` | 10 | 0 | 0 | | | | | +| | | +----+--------------------+----------------+------+---------+----------------+ | | | +| | +Projection | 3 | p.name AS `p.name` | 10 | 0 | 0 | | | | | +| | | +----+--------------------+----------------+------+---------+----------------+ | | | +| | +NodeByLabelScan | 4 | p:Country | 10 | 0 | 0 | 120 | 0/0 | 0.049 | Fused in Pipeline 1 | +| | +----+--------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +Projection | 5 | `p.name` | 10 | 0 | 0 | | | | | +| | +----+--------------------+----------------+------+---------+----------------+ | | | +| +Projection | 6 | p.name AS `p.name` | 10 | 0 | 0 | | | | | +| | +----+--------------------+----------------+------+---------+----------------+ | | | +| +NodeByLabelScan | 7 | p:Location | 10 | 0 | 0 | 120 | 0/0 | 0.077 | Fused in Pipeline 0 | ++--------------------+----+--------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 17, total allocated memory: 4184 +Total database accesses: 0, total allocated memory: 320 ---- ====== +[[aggregation-operators]] +== Aggregation operators + +Aggregation operators are used to compute summary statistics over groups of graph data, enabling operations such as counting nodes, relationships or properties. + [[query-plan-eager-aggregation]] -== Eager Aggregation -// EagerAggregation +=== Eager Aggregation The `EagerAggregation` operator evaluates a grouping expression and uses the result to group rows into different groupings. For each of these groupings, `EagerAggregation` will then evaluate all aggregation functions and return the result. @@ -5002,7 +4629,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 @@ -5029,8 +4656,7 @@ Total database accesses: 117, total allocated memory: 2664 [[query-plan-ordered-aggregation]] -== Ordered Aggregation -// OrderedAggregation +=== Ordered Aggregation The `OrderedAggregation` operator is an optimization of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-eager-aggregation[`EagerAggregation`] operator that takes advantage of the ordering of the incoming rows. This operator uses lazy evaluation and has a lower memory pressure in the system than the `EagerAggregation` operator. @@ -5055,7 +4681,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 @@ -5076,8 +4702,7 @@ Total database accesses: 3, total allocated memory: 352 [[query-plan-node-count-from-count-store]] -== Node Count From Count Store -// NodeCountFromCountStore +=== Node Count From Count Store The `NodeCountFromCountStore` operator uses the count store to answer questions about node counts. This is much faster than the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-eager-aggregation[`EagerAggregation`] operator which achieves the same result by actually counting. @@ -5103,7 +4728,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 @@ -5122,8 +4747,7 @@ Total database accesses: 1, total allocated memory: 184 [[query-plan-relationship-count-from-count-store]] -== Relationship Count From Count Store -// RelationshipCountFromCountStore +=== Relationship Count From Count Store The `RelationshipCountFromCountStore` operator uses the count store to answer questions about relationship counts. This is much faster than the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-eager-aggregation[`EagerAggregation`] operator which achieves the same result by actually counting. @@ -5149,7 +4773,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 @@ -5166,24 +4790,25 @@ Total database accesses: 1, total allocated memory: 184 ====== +[[filter-order-projection-operators]] +== Filter, order, and projection operators -[[query-plan-distinct]] -== Distinct -// Distinct +The operators in this group handle how rows of data are transformed, filtered, and finalized for query results. +They are responsible for crafting the structure of the returned data, -The `Distinct` operator removes duplicate rows from the incoming stream of rows. -To ensure only distinct elements are returned, `Distinct` will pull in data lazily from its source and build up state. -This may lead to increased memory pressure in the system. +[[query-plan-empty-result]] +=== Empty Result +The `EmptyResult` operator eagerly loads all incoming data and discards it. -.Distinct +.EmptyResult ====== + .Query [source, cypher] ---- PROFILE -MATCH (l:Location)<-[:WORKS_IN]-(p:Person) -RETURN DISTINCT p +CREATE (:Person) ---- .Query Plan @@ -5193,47 +4818,41 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+------------------+----+-----------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+------------------+----+-----------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | 0 | p | 14 | 14 | 28 | | | | | -| | +----+-----------------------+----------------+------+---------+----------------+ | | | -| +Distinct | 1 | p | 14 | 14 | 0 | 352 | | | | -| | +----+-----------------------+----------------+------+---------+----------------+ | | | -| +Filter | 2 | p:Person | 15 | 15 | 30 | | | | | -| | +----+-----------------------+----------------+------+---------+----------------+ | | | -| +Expand(All) | 3 | (l)<-[r:WORKS_IN]-(p) | 15 | 15 | 26 | | | | | -| | +----+-----------------------+----------------+------+---------+----------------+ | | | -| +NodeByLabelScan | 4 | l:Location | 10 | 10 | 11 | 120 | 4/0 | 0.287 | Fused in Pipeline 0 | -+------------------+----+-----------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++-----------------+-----------------+----------------+------+---------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-----------------+-----------------+----------------+------+---------+------------------------+-----------+---------------------+ +| +ProduceResults | | 1 | 0 | 0 | | | | +| | +-----------------+----------------+------+---------+ | | | +| +EmptyResult | | 1 | 0 | 0 | | | | +| | +-----------------+----------------+------+---------+ | | | +| +Create | (anon_0:Person) | 1 | 1 | 1 | 0/0 | 0.000 | Fused in Pipeline 0 | ++-----------------+-----------------+----------------+------+---------+------------------------+-----------+---------------------+ -Total database accesses: 95, total allocated memory: 432 +Total database accesses: 1, total allocated memory: 184 ---- ====== -[[query-plan-ordered-distinct]] -== Ordered Distinct -// OrderedDistinct -The `OrderedDistinct` operator is an optimization of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-distinct[`Distinct`] operator that takes advantage of the ordering of the incoming rows. -This operator has a lower memory pressure in the system than the `Distinct` operator. +[[query-plan-produce-results]] +=== Produce Results +The `ProduceResults` operator prepares the result so that it is consumable by the user, such as transforming internal values to user values. +It is present in every single query that returns data to the user, and has little bearing on performance optimisation. -.OrderedDistinct +.ProduceResults ====== .Query [source, cypher] ---- PROFILE -MATCH (p:Person) -WHERE p.name STARTS WITH 'P' -RETURN DISTINCT p.name +MATCH (n) +RETURN n ---- .Query Plan @@ -5243,33 +4862,29 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+-----------------------+--------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+--------------+---------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Ordered by | Pipeline | -+-----------------------+--------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+--------------+---------------+ -| +ProduceResults | `p.name` | 0 | 2 | 0 | | 0/0 | 0.046 | | | -| | +--------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | | -| +OrderedDistinct | cache[p.name] AS `p.name` | 0 | 2 | 0 | 32 | 0/0 | 0.090 | `p.name` ASC | | -| | +--------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+--------------+ | -| +NodeIndexSeekByRange | RANGE INDEX p:Person(name) WHERE name STARTS WITH $autostring_0, cache[p.name] | 0 | 2 | 3 | 120 | 0/1 | 0.493 | p.name ASC | In Pipeline 0 | -+-----------------------+--------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+--------------+---------------+ ++-----------------+---------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-----------------+---------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | n | 35 | 35 | 0 | | | | | +| | +---------+----------------+------+---------+----------------+ | | | +| +AllNodesScan | n | 35 | 35 | 36 | 120 | 3/0 | 0.508 | Fused in Pipeline 0 | ++-----------------+---------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 3, total allocated memory: 184 +Total database accesses: 36, total allocated memory: 184 ---- ====== [[query-plan-filter]] -== Filter -// Filter +=== Filter The `Filter` operator filters each row coming from the child operator, only passing through rows that evaluate the predicates to `true`. - .Filter ====== @@ -5289,7 +4904,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 @@ -5308,24 +4923,20 @@ Total database accesses: 15, total allocated memory: 184 ====== +[[query-plan-empty-row]] +=== Empty Row -[[query-plan-limit]] -== Limit -// Limit - -The `Limit` operator returns the first `+n+` rows from the incoming input. - +The `EmptyRow` operator returns a single row with no columns. -.Limit +.EmptyRow ====== .Query [source, cypher] ---- PROFILE -MATCH (p:Person) -RETURN p -LIMIT 3 +CYPHER runtime=slotted +FOREACH (value IN [1,2,3] | MERGE (:Person {age: value})) ---- .Query Plan @@ -5333,46 +4944,52 @@ LIMIT 3 ---- Planner COST -Runtime PIPELINED - -Runtime version {neo4j-version} +Runtime SLOTTED -Batch size 128 +Runtime version {neo4j-version-minor} -+-----------------+----------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-----------------+----------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | p | 3 | 3 | 0 | | | | | -| | +----------+----------------+------+---------+----------------+ | | | -| +Limit | 3 | 3 | 3 | 0 | 32 | | | | -| | +----------+----------------+------+---------+----------------+ | | | -| +NodeByLabelScan| p:Person | 3 | 4 | 5 | 120 | 3/0 | 0,540 | Fused in Pipeline 0 | -+-----------------+----------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++-----------------+--------------------------------------+----------------+------+---------+------------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | ++--------------------+--------------------------------------+----------------+------+---------+------------------------+ +| +ProduceResults | | 1 | 0 | 0 | 0/0 | +| | +--------------------------------------+----------------+------+---------+------------------------+ +| +EmptyResult | | 1 | 0 | 0 | 0/0 | +| | +--------------------------------------+----------------+------+---------+------------------------+ +| +Foreach | value IN [1, 2, 3] | 1 | 1 | 0 | 0/0 | +| |\ +--------------------------------------+----------------+------+---------+------------------------+ +| | +Merge | CREATE (anon_0:Person {age: value}) | 1 | 3 | 9 | 0/0 | +| | | +--------------------------------------+----------------+------+---------+------------------------+ +| | +Filter | anon_0.age = value | 1 | 0 | 184 | 2/0 | +| | | +--------------------------------------+----------------+------+---------+------------------------+ +| | +NodeByLabelScan | anon_0:Person | 35 | 108 | 111 | 3/0 | +| | +--------------------------------------+----------------+------+---------+------------------------+ +| +EmptyRow | | 1 | 1 | 0 | 0/0 | ++--------------------+--------------------------------------+----------------+------+---------+------------------------+ -Total database accesses: 8, total allocated memory: 184 +Total database accesses: 304, total allocated memory: 64 ---- ====== -[[query-plan-skip]] -== Skip -// Skip +[[query-plan-cache-properties]] +=== Cache Properties -The `Skip` operator skips `+n+` rows from the incoming rows. +The `CacheProperties` operator reads nodes and relationship properties and caches them in the current row. +Future accesses to these properties can avoid reading from the store which will speed up the query. +In the plan below we will cache `l.name` before `Expand(All)` where there are fewer rows. -.Skip +.CacheProperties ====== - .Query [source, cypher] ---- PROFILE -MATCH (p:Person) -RETURN p -ORDER BY p.id -SKIP 1 +MATCH (l:Location)<-[:WORKS_IN]-(p:Person) +RETURN + l.name AS location, + p.name AS name ---- .Query Plan @@ -5382,48 +4999,46 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+------------------+----------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Ordered by | Pipeline | -+------------------+----------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ -| +ProduceResults | p | 13 | 13 | 0 | | 2/0 | 0.165 | | | -| | +----------------+----------------+------+---------+----------------+------------------------+-----------+ | | -| +Skip | $autoint_0 | 13 | 13 | 0 | 32 | 0/0 | 0.043 | | | -| | +----------------+----------------+------+---------+----------------+------------------------+-----------+ | | -| +Sort | `p.id` ASC | 14 | 14 | 0 | 400 | 0/0 | 0.155 | p.id ASC | In Pipeline 1 | -| | +----------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ -| +Projection | p.id AS `p.id` | 14 | 14 | 0 | | | | | | -| | +----------------+----------------+------+---------+----------------+ | +------------+ | -| +NodeByLabelScan | p:Person | 18 | 18 | 19 | 120 | 3/0 | 0,157 | | Fused in Pipeline 0 | -+------------------+----------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ ++------------------+----+-------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++------------------+----+-------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | location, name | 13 | 13 | 0 | | | | | +| | +----+-------------------------------------------+----------------+------+---------+----------------+ | | | +| +Projection | 1 | cache[l.name] AS location, p.name AS name | 13 | 13 | 26 | | | | | +| | +----+-------------------------------------------+----------------+------+---------+----------------+ | | | +| +Filter | 2 | p:Person | 13 | 13 | 26 | | | | | +| | +----+-------------------------------------------+----------------+------+---------+----------------+ | | | +| +Expand(All) | 3 | (l)<-[anon_0:WORKS_IN]-(p) | 13 | 13 | 24 | | | | | +| | +----+-------------------------------------------+----------------+------+---------+----------------+ | | | +| +CacheProperties | 4 | cache[l.name] | 10 | 10 | 20 | | | | | +| | +----+-------------------------------------------+----------------+------+---------+----------------+ | | | +| +NodeByLabelScan | 5 | l:Location | 10 | 10 | 11 | 120 | 4/0 | 0.344 | Fused in Pipeline 0 | ++------------------+----+-------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 71, total allocated memory: 512 +Total database accesses: 107, total allocated memory: 200 ---- ====== -[[query-plan-sort]] -== Sort -// Sort +[[query-plan-projection]] +=== Projection -The `Sort` operator sorts rows by a provided key. -In order to sort the data, all data from the source operator needs to be pulled in eagerly and kept in the query state, which will lead to increased memory pressure in the system. +For each incoming row, the `Projection` operator evaluates a set of expressions and produces a row with the results of the expressions. -.Sort +.Projection ====== .Query [source, cypher] ---- PROFILE -MATCH (p:Person) -RETURN p -ORDER BY p.name +RETURN 'hello' AS greeting ---- .Query Plan @@ -5433,48 +5048,40 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+------------------+--------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Ordered by | Pipeline | -+------------------+--------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ -| +ProduceResults | p | 14 | 14 | 0 | | 2/0 | 0.178 | | | -| | +--------------------+----------------+------+---------+----------------+------------------------+-----------+ | | -| +Sort | `p.name` ASC | 14 | 14 | 0 | 1192 | 0/0 | 0.107 | p.name ASC | In Pipeline 1 | -| | +--------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ -| +Projection | p.name AS `p.name` | 14 | 14 | 14 | | | | | | -| | +--------------------+----------------+------+---------+----------------+ | +------------+ | -| +NodeByLabelScan |p:Person | 14 | 14 | 35 | 120 | 3/0 | 0,221 | | Fused in Pipeline 0 | -+------------------+--------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ ++-----------------+---------------------------+----------------+------+---------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-----------------+---------------------------+----------------+------+---------+------------------------+-----------+---------------------+ +| +ProduceResults | greeting | 1 | 1 | 0 | | | | +| | +---------------------------+----------------+------+---------+ | | | +| +Projection | $autostring_0 AS greeting | 1 | 1 | 0 | 0/0 | 0.000 | Fused in Pipeline 0 | ++-----------------+---------------------------+----------------+------+---------+------------------------+-----------+---------------------+ -Total database accesses: 85, total allocated memory: 1272 +Total database accesses: 0, total allocated memory: 184 ---- ====== -[[query-plan-partial-sort]] -== Partial Sort -// PartialSort - -The `PartialSort` operator is an optimization of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-sort[`Sort`] operator that takes advantage of the ordering of the incoming rows. -This operator uses lazy evaluation and has a lower memory pressure in the system than the `Sort` operator. -Partial sort is only applicable when sorting on multiple columns. +[[query-plan-project-endpoints]] +=== Project Endpoints +The `ProjectEndpoints` operator projects the start and end node of a relationship. -.PartialSort +.ProjectEndpoints ====== .Query [source, cypher] ---- PROFILE -MATCH (p:Person) -WHERE p.name STARTS WITH 'P' -RETURN p -ORDER BY p.name, p.age +CREATE (n)-[p:KNOWS]->(m) +WITH p AS r +MATCH (u)-[r]->(v) +RETURN u, v ---- .Query Plan @@ -5484,47 +5091,50 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+-----------------------+--------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+-----------------------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Ordered by | Pipeline | -+-----------------------+--------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+-----------------------+---------------------+ -| +ProduceResults | p | 0 | 2 | 0 | | 2/0 | 0.087 | | | -| | +--------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | | -| +PartialSort | `p.name` ASC, `p.age` ASC | 0 | 2 | 0 | 544 | 0/0 | 0.184 | p.name ASC, p.age ASC | In Pipeline 1 | -| | +--------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+-----------------------+---------------------+ -| +Projection | cache[p.name] AS `p.name`, p.age AS `p.age` | 0 | 2 | 0 | | | | `p.name` ASC | | -| | +--------------------------------------------------------------------------------+----------------+------+---------+----------------+ | +-----------------------+ | -| +NodeIndexSeekByRange | RANGE INDEX p:Person(name) WHERE name STARTS WITH $autostring_0, cache[p.name] | 0 | 2 | 3 | 120 | 0/1 | 0.362 | p.name ASC | Fused in Pipeline 0 | -+-----------------------+--------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+-----------------------+---------------------+ ++---------------------+----+-----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++---------------------+----+-----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | u, v | 1 | 1 | 2 | 0 | | | | +| | +----+-----------------------------------------+----------------+------+---------+----------------+ | | | +| +Apply | 1 | | 1 | 1 | 0 | | | | | +| |\ +----+-----------------------------------------+----------------+------+---------+----------------+ | | | +| | +ProjectEndpoints | 2 | (u)-[r]->(v) | 1 | 1 | 0 | | | | | +| | | +----+-----------------------------------------+----------------+------+---------+----------------+ | | | +| | +Argument | 3 | r | 1 | 1 | 0 | 4328 | 0/0 | 0.194 | Fused in Pipeline 2 | +| | +----+-----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +Eager | 4 | read/create conflict (Operator: 6 vs 2) | 1 | 1 | 0 | 368 | 0/0 | 0.025 | In Pipeline 1 | +| | +----+-----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +Projection | 5 | p AS r | 1 | 1 | 0 | | | | | +| | +----+-----------------------------------------+----------------+------+---------+----------------+ | | | +| +Create | 6 | (n), (m), (n)-[p:KNOWS]->(m) | 1 | 1 | 3 | | 0/0 | 0.000 | Fused in Pipeline 0 | ++---------------------+----+-----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 3, total allocated memory: 608 +Total database accesses: 5, total allocated memory: 4920 ---- ====== -[[query-plan-top]] -== Top -// Top +[[query-plan-distinct]] +=== Distinct -The `Top` operator returns the first `+n+` rows sorted by a provided key. -Instead of sorting the entire input, only the top `+n+` rows are retained. +The `Distinct` operator removes duplicate rows from the incoming stream of rows. +To ensure only distinct elements are returned, `Distinct` will pull in data lazily from its source and build up state. +This may lead to increased memory pressure in the system. -.Top +.Distinct ====== - .Query [source, cypher] ---- PROFILE -MATCH (p:Person) -RETURN p -ORDER BY p.name -LIMIT 2 +MATCH (l:Location)<-[:WORKS_IN]-(p:Person) +RETURN DISTINCT p ---- .Query Plan @@ -5534,38 +5144,38 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+------------------+----------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Ordered by | Pipeline | -+------------------+----------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ -| +ProduceResults | p | 2 | 2 | 0 | | 2/0 | 0.093 | | | -| | +----------------------+----------------+------+---------+----------------+------------------------+-----------+ | | -| +Top | `p.name` ASC LIMIT 2 | 2 | 2 | 0 | 1184 | 0/0 | 0.295 | p.name ASC | In Pipeline 1 | -| | +----------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ -| +Projection | p.name AS `p.name` | 14 | 14 | 14 | | | | | | -| | +----------------------+----------------+------+---------+----------------+ | +------------+ | -| +NodeByLabelScan | p:Person | 14 | 14 | 35 | 120 | 3/0 | 0,166 | | Fused in Pipeline 0 | -+------------------+----------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ ++------------------+----+----------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++------------------+----+----------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | p | 14 | 14 | 29 | 0 | | | | +| | +----+----------------------------+----------------+------+---------+----------------+ | | | +| +Distinct | 1 | p | 14 | 14 | 0 | 352 | | | | +| | +----+----------------------------+----------------+------+---------+----------------+ | | | +| +Filter | 2 | p:Person | 15 | 15 | 30 | | | | | +| | +----+----------------------------+----------------+------+---------+----------------+ | | | +| +Expand(All) | 3 | (l)<-[anon_0:WORKS_IN]-(p) | 15 | 15 | 25 | | | | | +| | +----+----------------------------+----------------+------+---------+----------------+ | | | +| +NodeByLabelScan | 4 | l:Location | 10 | 10 | 11 | 248 | 8/0 | 0.758 | Fused in Pipeline 0 | ++------------------+----+----------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 85, total allocated memory: 1264 +Total database accesses: 95, total allocated memory: 432 ---- ====== -[[query-plan-partial-top]] -== Partial Top -// PartialTop +[[query-plan-ordered-distinct]] +=== Ordered Distinct -The `PartialTop` operator is an optimization of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-top[`Top`] operator that takes advantage of the ordering of the incoming rows. -This operator uses lazy evaluation and has a lower memory pressure in the system than the `Top` operator. -Partial top is only applicable when sorting on multiple columns. +The `OrderedDistinct` operator is an optimization of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-distinct[`Distinct`] operator that takes advantage of the ordering of the incoming rows. +This operator has a lower memory pressure in the system than the `Distinct` operator. -.PartialTop +.OrderedDistinct ====== .Query @@ -5574,9 +5184,7 @@ Partial top is only applicable when sorting on multiple columns. PROFILE MATCH (p:Person) WHERE p.name STARTS WITH 'P' -RETURN p -ORDER BY p.name, p.age -LIMIT 2 +RETURN DISTINCT p.name ---- .Query Plan @@ -5586,46 +5194,40 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+-----------------------+--------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+-----------------------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Ordered by | Pipeline | -+-----------------------+--------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+-----------------------+---------------------+ -| +ProduceResults | p | 0 | 2 | 0 | | 2/0 | 0.093 | | | -| | +--------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | | -| +PartialTop | `p.name` ASC, `p.age` ASC LIMIT 2 | 0 | 2 | 0 | 640 | 0/0 | 0.870 | p.name ASC, p.age ASC | In Pipeline 1 | -| | +--------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+-----------------------+---------------------+ -| +Projection | cache[p.name] AS `p.name`, p.age AS `p.age` | 0 | 2 | 0 | | | | `p.name` ASC | | -| | +--------------------------------------------------------------------------------+----------------+------+---------+----------------+ | +-----------------------+ | -| +NodeIndexSeekByRange | RANGE INDEX p:Person(name) WHERE name STARTS WITH $autostring_0, cache[p.name] | 0 | 2 | 3 | 120 | 0/1 | 0.556 | p.name ASC | Fused in Pipeline 0 | -+-----------------------+--------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+-----------------------+---------------------+ ++-----------------------+--------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+--------------+---------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Ordered by | Pipeline | ++-----------------------+--------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+--------------+---------------+ +| +ProduceResults | `p.name` | 0 | 2 | 0 | | 0/0 | 0.046 | | | +| | +--------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | | +| +OrderedDistinct | cache[p.name] AS `p.name` | 0 | 2 | 0 | 32 | 0/0 | 0.090 | `p.name` ASC | | +| | +--------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+--------------+ | +| +NodeIndexSeekByRange | RANGE INDEX p:Person(name) WHERE name STARTS WITH $autostring_0, cache[p.name] | 0 | 2 | 3 | 120 | 0/1 | 0.493 | p.name ASC | In Pipeline 0 | ++-----------------------+--------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+--------------+---------------+ -Total database accesses: 3, total allocated memory: 704 +Total database accesses: 3, total allocated memory: 184 ---- ====== +[[query-plan-procedure-call]] +=== Procedure Call -[[query-plan-union]] -== Union -// Union - -The `Union` operator concatenates the results from the right child operator with the results from the left child operator. - +The `ProcedureCall` operator indicates an invocation to a procedure. -.Union +.ProcedureCall ====== + .Query [source, cypher] ---- PROFILE -MATCH (p:Location) - RETURN p.name -UNION ALL -MATCH (p:Country) - RETURN p.name +CALL db.labels() YIELD label +RETURN * +ORDER BY label ---- .Query Plan @@ -5635,43 +5237,30 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+--------------------+----+--------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+--------------------+----+--------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | 0 | `p.name` | 20 | 0 | 0 | | | | | -| | +----+--------------------+----------------+------+---------+----------------+ | | | -| +Union | 1 | | 20 | 0 | 0 | 0 | 0/0 | 0.000 | Fused in Pipeline 2 | -| |\ +----+--------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| | +Projection | 2 | `p.name` | 10 | 0 | 0 | | | | | -| | | +----+--------------------+----------------+------+---------+----------------+ | | | -| | +Projection | 3 | p.name AS `p.name` | 10 | 0 | 0 | | | | | -| | | +----+--------------------+----------------+------+---------+----------------+ | | | -| | +NodeByLabelScan | 4 | p:Country | 10 | 0 | 0 | 120 | 0/0 | 0.049 | Fused in Pipeline 1 | -| | +----+--------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +Projection | 5 | `p.name` | 10 | 0 | 0 | | | | | -| | +----+--------------------+----------------+------+---------+----------------+ | | | -| +Projection | 6 | p.name AS `p.name` | 10 | 0 | 0 | | | | | -| | +----+--------------------+----------------+------+---------+----------------+ | | | -| +NodeByLabelScan | 7 | p:Location | 10 | 0 | 0 | 120 | 0/0 | 0.077 | Fused in Pipeline 0 | -+--------------------+----+--------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++-----------------+-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Ordered by | Pipeline | ++-----------------+-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ +| +ProduceResults | label | 10 | 4 | 0 | | 0/0 | 0.091 | | | +| | +-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | | +| +Sort | label ASC | 10 | 4 | 0 | 536 | 0/0 | 0.178 | label ASC | In Pipeline 1 | +| | +-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ +| +ProcedureCall | db.labels() :: (label :: STRING) | 10 | 4 | | | | | | Fused in Pipeline 0 | ++-----------------+-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ -Total database accesses: 0, total allocated memory: 320 +Total database accesses: ?, total allocated memory: 600 ---- ====== - [[query-plan-unwind]] -== Unwind -// Unwind +=== Unwind The `Unwind` operator returns one row per item in a list. - .Unwind ====== @@ -5690,7 +5279,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 @@ -5707,16 +5296,12 @@ Total database accesses: 0, total allocated memory: 184 ====== - [[query-plan-partitioned-unwind]] -== Partitioned Unwind -// PartitionedUnwind - +=== Partitioned Unwind The `PartitionedUnwind` is a variant of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-unwind[`Unwind`] operator used by the xref:planning-and-tuning/runtimes/concepts.adoc#runtimes-parallel-runtime[parallel runtime]. It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. - .PartitionedUnwind ====== @@ -5736,7 +5321,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 @@ -5753,16 +5338,20 @@ Total database accesses: 0 ====== -[[query-plan-exhaustive-limit]] -== Exhaustive Limit -// LockNodes - changed in 4.3 -// ExhaustiveLimit -The `ExhaustiveLimit` operator is similar to the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-limit[`Limit`] operator but will always exhaust the input. -Used when combining `LIMIT` and updates +[[sort-limit-operators]] +== Sort and limit operators +The operators in this group manage result set ordering and control the flow of data by limiting or skipping rows. +They optimize query performance and ensure users receive results in the desired order and quantity. -.ExhaustiveLimit +[[query-plan-sort]] +=== Sort + +The `Sort` operator sorts rows by a provided key. +In order to sort the data, all data from the source operator needs to be pulled in eagerly and kept in the query state, which will lead to increased memory pressure in the system. + +.Sort ====== .Query @@ -5770,9 +5359,8 @@ Used when combining `LIMIT` and updates ---- PROFILE MATCH (p:Person) -SET p.seen = true RETURN p -LIMIT 3 +ORDER BY p.name ---- .Query Plan @@ -5782,47 +5370,145 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+------------------+----+---------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+------------------+----+---------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | 0 | p | 3 | 3 | 10 | 0 | | | | -| | +----+---------------+----------------+------+---------+----------------+ | | | -| +ExhaustiveLimit | 1 | 3 | 3 | 3 | 0 | 32 | | | | -| | +----+---------------+----------------+------+---------+----------------+ | | | -| +SetProperty | 2 | p.seen = true | 17 | 17 | 34 | | | | | -| | +----+---------------+----------------+------+---------+----------------+ | | | -| +NodeByLabelScan | 3 | p:Person | 17 | 17 | 18 | 240 | 3/0 | 1.966 | Fused in Pipeline 0 | -+------------------+----+---------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++------------------+--------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Ordered by | Pipeline | ++------------------+--------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ +| +ProduceResults | p | 14 | 14 | 0 | | 2/0 | 0.178 | | | +| | +--------------------+----------------+------+---------+----------------+------------------------+-----------+ | | +| +Sort | `p.name` ASC | 14 | 14 | 0 | 1192 | 0/0 | 0.107 | p.name ASC | In Pipeline 1 | +| | +--------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ +| +Projection | p.name AS `p.name` | 14 | 14 | 14 | | | | | | +| | +--------------------+----------------+------+---------+----------------+ | +------------+ | +| +NodeByLabelScan |p:Person | 14 | 14 | 35 | 120 | 3/0 | 0,221 | | Fused in Pipeline 0 | ++------------------+--------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ -Total database accesses: 62, total allocated memory: 304 +Total database accesses: 85, total allocated memory: 1272 ---- ====== -[[query-plan-optional]] -== Optional -// Optional +[[query-plan-partial-sort]] +=== Partial Sort -The `Optional` operator is used to solve some xref::clauses/optional-match.adoc[OPTIONAL MATCH] queries. -It will pull data from its source, simply passing it through if any data exists. -However, if no data is returned by its source, `Optional` will yield a single row with all columns set to `null`. +The `PartialSort` operator is an optimization of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-sort[`Sort`] operator that takes advantage of the ordering of the incoming rows. +This operator uses lazy evaluation and has a lower memory pressure in the system than the `Sort` operator. +Partial sort is only applicable when sorting on multiple columns. + +.PartialSort +====== +.Query +[source, cypher] +---- +PROFILE +MATCH (p:Person) +WHERE p.name STARTS WITH 'P' +RETURN p +ORDER BY p.name, p.age +---- -.Optional +.Query Plan +[role="queryplan", subs="attributes+"] +---- +Planner COST + +Runtime PIPELINED + +Runtime version {neo4j-version-minor} + +Batch size 128 + ++-----------------------+--------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+-----------------------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Ordered by | Pipeline | ++-----------------------+--------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+-----------------------+---------------------+ +| +ProduceResults | p | 0 | 2 | 0 | | 2/0 | 0.087 | | | +| | +--------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | | +| +PartialSort | `p.name` ASC, `p.age` ASC | 0 | 2 | 0 | 544 | 0/0 | 0.184 | p.name ASC, p.age ASC | In Pipeline 1 | +| | +--------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+-----------------------+---------------------+ +| +Projection | cache[p.name] AS `p.name`, p.age AS `p.age` | 0 | 2 | 0 | | | | `p.name` ASC | | +| | +--------------------------------------------------------------------------------+----------------+------+---------+----------------+ | +-----------------------+ | +| +NodeIndexSeekByRange | RANGE INDEX p:Person(name) WHERE name STARTS WITH $autostring_0, cache[p.name] | 0 | 2 | 3 | 120 | 0/1 | 0.362 | p.name ASC | Fused in Pipeline 0 | ++-----------------------+--------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+-----------------------+---------------------+ + +Total database accesses: 3, total allocated memory: 608 +---- + +====== + + +[[query-plan-top]] +=== Top + +The `Top` operator returns the first `+n+` rows sorted by a provided key. +Instead of sorting the entire input, only the top `+n+` rows are retained. + +.Top ====== .Query [source, cypher] ---- PROFILE -MATCH (p:Person {name: 'me'}) -OPTIONAL MATCH (q:Person {name: 'Lulu'}) -RETURN p, q +MATCH (p:Person) +RETURN p +ORDER BY p.name +LIMIT 2 +---- + +.Query Plan +[role="queryplan", subs="attributes+"] +---- +Planner COST + +Runtime PIPELINED + +Runtime version {neo4j-version-minor} + +Batch size 128 + ++------------------+----------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Ordered by | Pipeline | ++------------------+----------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ +| +ProduceResults | p | 2 | 2 | 0 | | 2/0 | 0.093 | | | +| | +----------------------+----------------+------+---------+----------------+------------------------+-----------+ | | +| +Top | `p.name` ASC LIMIT 2 | 2 | 2 | 0 | 1184 | 0/0 | 0.295 | p.name ASC | In Pipeline 1 | +| | +----------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ +| +Projection | p.name AS `p.name` | 14 | 14 | 14 | | | | | | +| | +----------------------+----------------+------+---------+----------------+ | +------------+ | +| +NodeByLabelScan | p:Person | 14 | 14 | 35 | 120 | 3/0 | 0,166 | | Fused in Pipeline 0 | ++------------------+----------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ + +Total database accesses: 85, total allocated memory: 1264 +---- + +====== + + +[[query-plan-partial-top]] +=== Partial Top + +The `PartialTop` operator is an optimization of the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-top[`Top`] operator that takes advantage of the ordering of the incoming rows. +This operator uses lazy evaluation and has a lower memory pressure in the system than the `Top` operator. +Partial top is only applicable when sorting on multiple columns. + + +.PartialTop +====== + +.Query +[source, cypher] +---- +PROFILE +MATCH (p:Person) +WHERE p.name STARTS WITH 'P' +RETURN p +ORDER BY p.name, p.age +LIMIT 2 ---- .Query Plan @@ -5832,48 +5518,42 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+------------------+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+------------------+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ -| +ProduceResults | p, q | 1 | 1 | 0 | | 2/0 | 0.079 | In Pipeline 2 | -| | +-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ -| +Apply | | 1 | 1 | 0 | | 0/0 | 0.096 | | -| |\ +-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ -| | +Optional | p | 1 | 1 | 0 | 768 | 0/0 | 0.043 | In Pipeline 2 | -| | | +-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ -| | +NodeIndexSeek | RANGE INDEX q:Person(name) WHERE name = $autostring_1 | 1 | 0 | 1 | 2152 | 1/0 | 0.098 | In Pipeline 1 | -| | +-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ -| +NodeIndexSeek | RANGE INDEX p:Person(name) WHERE name = $autostring_0 | 1 | 1 | 2 | 120 | 0/1 | 0.364 | In Pipeline 0 | -+------------------+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ ++-----------------------+--------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+-----------------------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Ordered by | Pipeline | ++-----------------------+--------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+-----------------------+---------------------+ +| +ProduceResults | p | 0 | 2 | 0 | | 2/0 | 0.093 | | | +| | +--------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | | +| +PartialTop | `p.name` ASC, `p.age` ASC LIMIT 2 | 0 | 2 | 0 | 640 | 0/0 | 0.870 | p.name ASC, p.age ASC | In Pipeline 1 | +| | +--------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+-----------------------+---------------------+ +| +Projection | cache[p.name] AS `p.name`, p.age AS `p.age` | 0 | 2 | 0 | | | | `p.name` ASC | | +| | +--------------------------------------------------------------------------------+----------------+------+---------+----------------+ | +-----------------------+ | +| +NodeIndexSeekByRange | RANGE INDEX p:Person(name) WHERE name STARTS WITH $autostring_0, cache[p.name] | 0 | 2 | 3 | 120 | 0/1 | 0.556 | p.name ASC | Fused in Pipeline 0 | ++-----------------------+--------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+-----------------------+---------------------+ -Total database accesses: 3, total allocated memory: 3000 +Total database accesses: 3, total allocated memory: 704 ---- ====== +[[query-plan-limit]] +=== Limit -[[query-plan-project-endpoints]] -== Project Endpoints -// ProjectEndpoints - -The `ProjectEndpoints` operator projects the start and end node of a relationship. - +The `Limit` operator returns the first `+n+` rows from the incoming input. -.ProjectEndpoints +.Limit ====== .Query [source, cypher] ---- PROFILE -CREATE (n)-[p:KNOWS]->(m) -WITH p AS r -MATCH (u)-[r]->(v) -RETURN u, v +MATCH (p:Person) +RETURN p +LIMIT 3 ---- .Query Plan @@ -5883,49 +5563,44 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+---------------------+----+-----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+---------------------+----+-----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | 0 | u, v | 1 | 1 | 2 | 0 | | | | -| | +----+-----------------------------------------+----------------+------+---------+----------------+ | | | -| +Apply | 1 | | 1 | 1 | 0 | | | | | -| |\ +----+-----------------------------------------+----------------+------+---------+----------------+ | | | -| | +ProjectEndpoints | 2 | (u)-[r]->(v) | 1 | 1 | 0 | | | | | -| | | +----+-----------------------------------------+----------------+------+---------+----------------+ | | | -| | +Argument | 3 | r | 1 | 1 | 0 | 4328 | 0/0 | 0.194 | Fused in Pipeline 2 | -| | +----+-----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +Eager | 4 | read/create conflict (Operator: 6 vs 2) | 1 | 1 | 0 | 368 | 0/0 | 0.025 | In Pipeline 1 | -| | +----+-----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +Projection | 5 | p AS r | 1 | 1 | 0 | | | | | -| | +----+-----------------------------------------+----------------+------+---------+----------------+ | | | -| +Create | 6 | (n), (m), (n)-[p:KNOWS]->(m) | 1 | 1 | 3 | | 0/0 | 0.000 | Fused in Pipeline 0 | -+---------------------+----+-----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++-----------------+----------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-----------------+----------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | p | 3 | 3 | 0 | | | | | +| | +----------+----------------+------+---------+----------------+ | | | +| +Limit | 3 | 3 | 3 | 0 | 32 | | | | +| | +----------+----------------+------+---------+----------------+ | | | +| +NodeByLabelScan| p:Person | 3 | 4 | 5 | 120 | 3/0 | 0,540 | Fused in Pipeline 0 | ++-----------------+----------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 5, total allocated memory: 4920 +Total database accesses: 8, total allocated memory: 184 ---- ====== +[[query-plan-exhaustive-limit]] +=== Exhaustive Limit +// LockNodes - changed in 4.3 -[[query-plan-projection]] -== Projection -// Projection - -For each incoming row, the `Projection` operator evaluates a set of expressions and produces a row with the results of the expressions. +The `ExhaustiveLimit` operator is similar to the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-limit[`Limit`] operator but will always exhaust the input. +Used when combining `LIMIT` and updates -.Projection +.ExhaustiveLimit ====== .Query [source, cypher] ---- PROFILE -RETURN 'hello' AS greeting +MATCH (p:Person) +SET p.seen = true +RETURN p +LIMIT 3 ---- .Query Plan @@ -5935,43 +5610,43 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+-----------------+---------------------------+----------------+------+---------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-----------------+---------------------------+----------------+------+---------+------------------------+-----------+---------------------+ -| +ProduceResults | greeting | 1 | 1 | 0 | | | | -| | +---------------------------+----------------+------+---------+ | | | -| +Projection | $autostring_0 AS greeting | 1 | 1 | 0 | 0/0 | 0.000 | Fused in Pipeline 0 | -+-----------------+---------------------------+----------------+------+---------+------------------------+-----------+---------------------+ ++------------------+----+---------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++------------------+----+---------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | p | 3 | 3 | 10 | 0 | | | | +| | +----+---------------+----------------+------+---------+----------------+ | | | +| +ExhaustiveLimit | 1 | 3 | 3 | 3 | 0 | 32 | | | | +| | +----+---------------+----------------+------+---------+----------------+ | | | +| +SetProperty | 2 | p.seen = true | 17 | 17 | 34 | | | | | +| | +----+---------------+----------------+------+---------+----------------+ | | | +| +NodeByLabelScan | 3 | p:Person | 17 | 17 | 18 | 240 | 3/0 | 1.966 | Fused in Pipeline 0 | ++------------------+----+---------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 0, total allocated memory: 184 +Total database accesses: 62, total allocated memory: 304 ---- ====== +[[query-plan-skip]] +=== Skip -[[query-plan-shortest-path]] -== Shortest path -// ShortestPath - -The `ShortestPath` operator finds one or all shortest paths between two previously matched node variables. -This operator is used for the xref:patterns/reference.adoc#shortest-functions[`shortestPath()` and `allShortestPaths`] functions. +The `Skip` operator skips `+n+` rows from the incoming rows. -.ShortestPath +.Skip ====== .Query [source, cypher] ---- PROFILE -MATCH - (andy:Person {name: 'Andy'}), - (mattias:Person {name: 'Mattias'}), - p = shortestPath((andy)-[*]-(mattias)) +MATCH (p:Person) RETURN p +ORDER BY p.id +SKIP 1 ---- .Query Plan @@ -5981,54 +5656,52 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+---------------------+-------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+---------------------+-------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ -| +ProduceResults | p | 1 | 1 | 0 | | 1/0 | 0.241 | | -| | +-------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | -| +ShortestPath | p = (andy)-[anon_0*]-(mattias) | 1 | 1 | 1 | 1424 | | | In Pipeline 1 | -| | +-------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ -| +MultiNodeIndexSeek | RANGE INDEX andy:Person(name) WHERE name = $autostring_0, | 1 | 1 | 4 | 120 | 1/1 | 0.308 | In Pipeline 0 | -| | RANGE INDEX mattias:Person(name) WHERE name = $autostring_1 | | | | | | | | -+---------------------+-------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ ++------------------+----------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Ordered by | Pipeline | ++------------------+----------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ +| +ProduceResults | p | 13 | 13 | 0 | | 2/0 | 0.165 | | | +| | +----------------+----------------+------+---------+----------------+------------------------+-----------+ | | +| +Skip | $autoint_0 | 13 | 13 | 0 | 32 | 0/0 | 0.043 | | | +| | +----------------+----------------+------+---------+----------------+------------------------+-----------+ | | +| +Sort | `p.id` ASC | 14 | 14 | 0 | 400 | 0/0 | 0.155 | p.id ASC | In Pipeline 1 | +| | +----------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ +| +Projection | p.id AS `p.id` | 14 | 14 | 0 | | | | | | +| | +----------------+----------------+------+---------+----------------+ | +------------+ | +| +NodeByLabelScan | p:Person | 18 | 18 | 19 | 120 | 3/0 | 0,157 | | Fused in Pipeline 0 | ++------------------+----------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ -Total database accesses: 5, total allocated memory: 1488 +Total database accesses: 71, total allocated memory: 512 ---- ====== -[[query-plan-stateful-shortest-path-into]] -== StatefulShortestPath(Into) -// StatefulShortestPath(Into) +[[data-modification-operators]] +== Data modification operators -//// -[source, cypher, role=test-setup] ----- -DROP INDEX range_person_name IF EXISTS; -CREATE CONSTRAINT person_name_unique IF NOT EXISTS FOR (p:Person) REQUIRE (p.name) IS UNIQUE; ----- -//// +The operators in this group modify graph data by creating, deleting, and altering nodes, relationships, and properties. -The `StatefulShortestPath(Into)` operator finds shortest paths between a start node and a single target node. -It uses a bidirectional breadth-first search (BFS) algorithm, which performs two BFS invocations at the same time, one from the left boundary node and one from the right boundary node. -Once a node is found by both BFS invocations, which indicates that it can be reached from both boundary nodes, the algorithm successfully terminates. -If one of the BFS invocations exhausts its search before intersecting, either because no further nodes can be reached or because the maximum number of hops has been reached, then there is no valid path between the boundary nodes and the algorithm terminates. +[[query-plan-create]] +=== Create -.StatefulShortestPath(Into) +The `Create` operator is used to create nodes and relationships. + + +.Create ====== .Query [source, cypher] ---- PROFILE -MATCH - p = ALL SHORTEST (chris:Person {name: 'Chris'})(()-[]-()-[]-()){1,}(stefan:Person {name: 'Stefan'}) -RETURN p +CREATE + (max:Person {name: 'Max'}), + (chris:Person {name: 'Chris'}) +CREATE (max)-[:FRIENDS_WITH]->(chris) ---- .Query Plan @@ -6038,48 +5711,41 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+-----------------------------+----+--------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-----------------------------+----+--------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ -| +ProduceResults | 0 | p | 2 | 2 | 0 | 0 | 0/0 | 0.039 | | -| | +----+--------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | -| +Projection | 1 | (chris) ((anon_12)-[anon_14]-(anon_13)-[anon_11]-())* (stefan) AS p | 2 | 2 | 0 | | 0/0 | 1.365 | | -| | +----+--------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | -| +StatefulShortestPath(Into) | 2 | SHORTEST 1 GROUPS (chris) ((`anon_5`)-[`anon_6`]-(`anon_7`)-[`anon_8`]-(`anon_9`)){1, } (stefan) | 2 | 2 | 39 | 22237 | 1/0 | 37.376 | In Pipeline 1 | -| | +----+--------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ -| +MultiNodeIndexSeek | 3 | UNIQUE chris:Person(name) WHERE name = $autostring_0, | 1 | 1 | 4 | 376 | 1/1 | 10.245 | In Pipeline 0 | -| | | UNIQUE stefan:Person(name) WHERE name = $autostring_1 | | | | | | | | -+-----------------------------+----+--------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ - -Total database accesses: 43, total allocated memory: 22557 ++-----------------+---------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-----------------+---------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------------+ +| +ProduceResults | | 1 | 0 | 0 | | | | +| | +---------------------------------------------------------------------------+----------------+------+---------+ | | | +| +EmptyResult | | 1 | 0 | 0 | | | | +| | +---------------------------------------------------------------------------+----------------+------+---------+ | | | +| +Create | (max:Person {name: $autostring_0}), (chris:Person {name: $autostring_1}), | 1 | 1 | 7 | 0/0 | 0.000 | Fused in Pipeline 0 | +| | (max)-[anon_0:FRIENDS_WITH]->(chris) | | | | | | | ++-----------------+---------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------------+ +Total database accesses: 7, total allocated memory: 184 ---- ====== -[[query-plan-stateful-shortest-path-all]] -== StatefulShortestPath(All) -// StatefulShortestPath(All) - -The `StatefulShortestPath(All)` operator finds shortest paths from a single node to multiple target nodes. -It uses a breadth-first search algorithm. +[[query-plan-delete]] +=== Delete +The `Delete` operator is used to delete a node or a relationship. -.StatefulShortestPath(All) +.Delete ====== .Query [source, cypher] ---- PROFILE -MATCH - p = ALL SHORTEST (chris:Person {name:'Chris'})(()-[]-()-[]-()){1,}(location:Location) -RETURN length(p) AS pathLength, location.name AS locationName +MATCH (you:Person {name: 'you'}) +DELETE you ---- .Query Plan @@ -6089,55 +5755,43 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+----------------------------+----+----------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+----------------------------+----+----------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ -| +ProduceResults | 0 | pathLength, locationName | 14 | 20 | 0 | 0 | 0/0 | 0.074 | | -| | +----+----------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | -| +Projection | 1 | length((chris) ((anon_12)-[anon_14]-(anon_13)-[anon_11]-())* (location)) AS pathLength, | 14 | 20 | 40 | | 1/0 | 6.828 | | -| | | | location.name AS locationName | | | | | | | | -| | +----+----------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | -| +StatefulShortestPath(All) | 2 | SHORTEST 1 GROUPS (chris) ((`anon_5`)-[`anon_6`]-(`anon_7`)-[`anon_8`]-(`anon_9`)){1, } (location) | 14 | 20 | 179 | 37663 | 1/0 | 52.849 | In Pipeline 1 | -| | | | expanding from: chris | | | | | | | | -| | | | inlined predicates: location:Location | | | | | | | | -| | +----+----------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ -| +NodeUniqueIndexSeek | 3 | UNIQUE chris:Person(name) WHERE name = $autostring_0 | 1 | 1 | 2 | 376 | 0/1 | 9.078 | In Pipeline 0 | -+----------------------------+----+----------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ - -Total database accesses: 221, total allocated memory: 37983 ++-----------------+----+--------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-----------------+----+--------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | | 0 | 0 | 0 | | | | | +| | +----+--------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +EmptyResult | 1 | | 0 | 0 | 0 | | | | | +| | +----+--------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +Delete | 2 | you | 0 | 0 | 0 | | | | | +| | +----+--------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +NodeIndexSeek | 3 | RANGE INDEX you:Person(name) WHERE name = $autostring_0 | 0 | 0 | 1 | 120 | 1/0 | 0.330 | Fused in Pipeline 0 | ++-----------------+----+--------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +Total database accesses: 13, total allocated memory: 216 ---- -//// -[source, cypher, role=test-setup] ----- -DROP CONSTRAINT person_name_unique IF EXISTS; -CREATE RANGE INDEX range_person_name FOR (p:Person) ON (p.name); ----- -//// ====== -[[query-plan-empty-row]] -== Empty Row -// EmptyRow +[[query-plan-detach-delete]] +=== Detach Delete -The `EmptyRow` operator returns a single row with no columns. +The `DetachDelete` operator is used in all queries containing the xref::clauses/delete.adoc[DETACH DELETE] clause, when deleting nodes and their relationships. -.EmptyRow +.DetachDelete ====== .Query [source, cypher] ---- PROFILE -CYPHER runtime=slotted -FOREACH (value IN [1,2,3] | MERGE (:Person {age: value})) +MATCH (p:Person) +DETACH DELETE p ---- .Query Plan @@ -6145,51 +5799,50 @@ FOREACH (value IN [1,2,3] | MERGE (:Person {age: value})) ---- Planner COST -Runtime SLOTTED +Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} -+-----------------+--------------------------------------+----------------+------+---------+------------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | -+--------------------+--------------------------------------+----------------+------+---------+------------------------+ -| +ProduceResults | | 1 | 0 | 0 | 0/0 | -| | +--------------------------------------+----------------+------+---------+------------------------+ -| +EmptyResult | | 1 | 0 | 0 | 0/0 | -| | +--------------------------------------+----------------+------+---------+------------------------+ -| +Foreach | value IN [1, 2, 3] | 1 | 1 | 0 | 0/0 | -| |\ +--------------------------------------+----------------+------+---------+------------------------+ -| | +Merge | CREATE (anon_0:Person {age: value}) | 1 | 3 | 9 | 0/0 | -| | | +--------------------------------------+----------------+------+---------+------------------------+ -| | +Filter | anon_0.age = value | 1 | 0 | 184 | 2/0 | -| | | +--------------------------------------+----------------+------+---------+------------------------+ -| | +NodeByLabelScan | anon_0:Person | 35 | 108 | 111 | 3/0 | -| | +--------------------------------------+----------------+------+---------+------------------------+ -| +EmptyRow | | 1 | 1 | 0 | 0/0 | -+--------------------+--------------------------------------+----------------+------+---------+------------------------+ +Batch size 128 -Total database accesses: 304, total allocated memory: 64 ++------------------+----------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++------------------+----------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | | 14 | 0 | 0 | | | | | +| | +----------+----------------+------+---------+----------------+ | | | +| +EmptyResult | | 14 | 0 | 0 | | | | | +| | +----------+----------------+------+---------+----------------+ | | | +| +DetachDelete | p | 14 | 14 | 41 | | | | | +| | +----------+----------------+------+---------+----------------+ | | | +| +NodeByLabelScan | p:Person | 14 | 14 | 35 | 120 | 21/0 | 12,439 | Fused in Pipeline 0 | ++------------------+----------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ + +Total database accesses: 112, total allocated memory: 200 ---- ====== +[[query-plan-merge]] +=== Merge +// ConditionalApply -- changed in 4.3 to Merge. +// AntiConditionalApply -- removed in 4.3 (by Merge). -[[query-plan-procedure-call]] -== Procedure Call -// ProcedureCall +The `Merge` operator will either read or create nodes and/or relationships. -The `ProcedureCall` operator indicates an invocation to a procedure. +If matches are found it will execute the provided `ON MATCH` operations foreach incoming row. +If no matches are found instead nodes and relationships are created and all `ON CREATE` operations are run. -.ProcedureCall +.Merge ====== .Query [source, cypher] ---- PROFILE -CALL db.labels() YIELD label -RETURN * -ORDER BY label +MERGE (p:Person {name: 'Andy'}) +ON MATCH SET p.existed = true +ON CREATE SET p.existed = false ---- .Query Plan @@ -6199,45 +5852,44 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+-----------------+-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Ordered by | Pipeline | -+-----------------+-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ -| +ProduceResults | label | 10 | 4 | 0 | | 0/0 | 0.091 | | | -| | +-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | | -| +Sort | label ASC | 10 | 4 | 0 | 536 | 0/0 | 0.178 | label ASC | In Pipeline 1 | -| | +-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ -| +ProcedureCall | db.labels() :: (label :: STRING) | 10 | 4 | | | | | | Fused in Pipeline 0 | -+-----------------+-----------------------------------+----------------+------+---------+----------------+------------------------+-----------+------------+---------------------+ ++-----------------+-------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-----------------+-------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | | 1 | 0 | 0 | | | | | +| | +-------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +EmptyResult | | 1 | 0 | 0 | | | | | +| | +-------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +Merge | CREATE (p:Person {name: $autostring_0}), ON MATCH SET p.existed = true, | 1 | 1 | 2 | | | | | +| | | ON CREATE SET p.existed = false | | | | | | | | +| | +-------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +NodeIndexSeek | RANGE INDEX p:Person(name) WHERE name = $autostring_0 | 1 | 1 | 2 | 120 | 2/1 | 0.749 | Fused in Pipeline 0 | ++-----------------+-------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: ?, total allocated memory: 600 +Total database accesses: 4, total allocated memory: 184 ---- ====== -[[query-plan-cache-properties]] -== Cache Properties -// CacheProperties +[[query-plan-locking-merge]] +=== Locking Merge -The `CacheProperties` operator reads nodes and relationship properties and caches them in the current row. -Future accesses to these properties can avoid reading from the store which will speed up the query. -In the plan below we will cache `l.name` before `Expand(All)` where there are fewer rows. +The `LockingMerge` operator is similar to the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-merge[`Merge`] operator but will lock the start and end node when creating a relationship if necessary. -.CacheProperties +.LockingMerge ====== + .Query [source, cypher] ---- PROFILE -MATCH (l:Location)<-[:WORKS_IN]-(p:Person) -RETURN - l.name AS location, - p.name AS name +MATCH (s:Person {name: 'me'}) +MERGE (s)-[:FRIENDS_WITH]->(s) ---- .Query Plan @@ -6247,50 +5899,52 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 -+------------------+----+-------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+------------------+----+-------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | 0 | location, name | 13 | 13 | 0 | | | | | -| | +----+-------------------------------------------+----------------+------+---------+----------------+ | | | -| +Projection | 1 | cache[l.name] AS location, p.name AS name | 13 | 13 | 26 | | | | | -| | +----+-------------------------------------------+----------------+------+---------+----------------+ | | | -| +Filter | 2 | p:Person | 13 | 13 | 26 | | | | | -| | +----+-------------------------------------------+----------------+------+---------+----------------+ | | | -| +Expand(All) | 3 | (l)<-[anon_0:WORKS_IN]-(p) | 13 | 13 | 24 | | | | | -| | +----+-------------------------------------------+----------------+------+---------+----------------+ | | | -| +CacheProperties | 4 | cache[l.name] | 10 | 10 | 20 | | | | | -| | +----+-------------------------------------------+----------------+------+---------+----------------+ | | | -| +NodeByLabelScan | 5 | l:Location | 10 | 10 | 11 | 120 | 4/0 | 0.344 | Fused in Pipeline 0 | -+------------------+----+-------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++-----------------+----+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-----------------+----+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | | 1 | 0 | 0 | | | | | +| | +----+-------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +EmptyResult | 1 | | 1 | 0 | 0 | | | | | +| | +----+-------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +Apply | 2 | | 1 | 1 | 0 | | | | | +| |\ +----+-------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +LockingMerge | 3 | CREATE (s)-[anon_0:FRIENDS_WITH]->(s), LOCK(s) | 1 | 1 | 1 | | | | | +| | | +----+-------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Expand(Into) | 4 | (s)-[anon_0:FRIENDS_WITH]->(s) | 0 | 0 | 10 | 904 | | | | +| | | +----+-------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Argument | 5 | s | 1 | 3 | 0 | 2280 | 2/0 | 0.460 | Fused in Pipeline 1 | +| | +----+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +NodeIndexSeek | 6 | RANGE INDEX s:Person(name) WHERE name = $autostring_0 | 1 | 1 | 2 | 376 | 1/0 | 0.211 | In Pipeline 0 | ++-----------------+----+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 107, total allocated memory: 200 +Total database accesses: 15, total allocated memory: 2232 ---- ====== -[[query-plan-create]] -== Create (nodes and relationships) -// Create -The `Create` operator is used to create nodes and relationships. +[[query-plan-foreach]] +=== Foreach +// Foreach + +The `Foreach` operator executes a nested loop between the left child operator and the right child operator. +In an analogous manner to the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-apply[Apply] operator, it takes a row from the left-hand side and, using the xref::planning-and-tuning/operators/operators-detail.adoc#query-plan-argument[Argument] operator, provides it to the operator tree on the right-hand side. +`Foreach` will yield all the rows coming in from the left-hand side; all results from the right-hand side are pulled in and discarded. -.Create +.Foreach ====== .Query [source, cypher] ---- PROFILE -CREATE - (max:Person {name: 'Max'}), - (chris:Person {name: 'Chris'}) -CREATE (max)-[:FRIENDS_WITH]->(chris) +FOREACH (value IN [1,2,3] | CREATE (:Person {age: value})) ---- .Query Plan @@ -6298,45 +5952,44 @@ CREATE (max)-[:FRIENDS_WITH]->(chris) ---- Planner COST -Runtime PIPELINED +Runtime SLOTTED Runtime version {neo4j-version} -Batch size 128 - -+-----------------+---------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-----------------+---------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------------+ -| +ProduceResults | | 1 | 0 | 0 | | | | -| | +---------------------------------------------------------------------------+----------------+------+---------+ | | | -| +EmptyResult | | 1 | 0 | 0 | | | | -| | +---------------------------------------------------------------------------+----------------+------+---------+ | | | -| +Create | (max:Person {name: $autostring_0}), (chris:Person {name: $autostring_1}), | 1 | 1 | 7 | 0/0 | 0.000 | Fused in Pipeline 0 | -| | (max)-[anon_0:FRIENDS_WITH]->(chris) | | | | | | | -+-----------------+---------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------------+ ++-----------------+---------------------------------------------------------+----------------+------+---------+------------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | ++-----------------+---------------------------------------------------------+----------------+------+---------+------------------------+ +| +ProduceResults | | 1 | 0 | 0 | 0/0 | +| | +---------------------------------------------------------+----------------+------+---------+------------------------+ +| +EmptyResult | | 1 | 0 | 0 | 0/0 | +| | +---------------------------------------------------------+----------------+------+---------+------------------------+ +| +Foreach | value IN [1, 2, 3], CREATE (anon_0:Person {age: value}) | 1 | 1 | 9 | 0/0 | ++-----------------+---------------------------------------------------------+----------------+------+---------+------------------------+ -Total database accesses: 7, total allocated memory: 184 +Total database accesses: 9, total allocated memory: 64 ---- ====== +[[query-plan-subquery-foreach]] +=== SubqueryForeach -[[query-plan-delete]] -== Delete (nodes and relationships) -// Delete - -The `Delete` operator is used to delete a node or a relationship. - +`SubqueryForeach` works like the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-foreach[`Foreach`]operator but it is only used for executing subqueries. -.Delete +.SubqueryForeach ====== +[NOTE] +The below query uses a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause] to import variables into the `CALL` subquery. + .Query [source, cypher] ---- PROFILE -MATCH (you:Person {name: 'you'}) -DELETE you +LOAD CSV FROM 'https://neo4j.com/docs/cypher-refcard/3.3/csv/artists.csv' AS line +CALL (line) { + CREATE (a: Artist {name: line[0]}) +} ---- .Query Plan @@ -6350,40 +6003,47 @@ Runtime version {neo4j-version} Batch size 128 -+-----------------+----+--------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-----------------+----+--------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | 0 | | 0 | 0 | 0 | | | | | -| | +----+--------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +EmptyResult | 1 | | 0 | 0 | 0 | | | | | -| | +----+--------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +Delete | 2 | you | 0 | 0 | 0 | | | | | -| | +----+--------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +NodeIndexSeek | 3 | RANGE INDEX you:Person(name) WHERE name = $autostring_0 | 0 | 0 | 1 | 120 | 1/0 | 0.330 | Fused in Pipeline 0 | -+-----------------+----+--------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++------------------+----+-------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++------------------+----+-------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | | 10 | 0 | 0 | 0 | | | | +| | +----+-------------------------------------+----------------+------+---------+----------------+ | | | +| +EmptyResult | 1 | | 10 | 0 | 0 | | 0/0 | 0.000 | Fused in Pipeline 3 | +| | +----+-------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +SubqueryForeach | 2 | | 10 | 4 | 0 | 4080 | | | | +| |\ +----+-------------------------------------+----------------+------+---------+----------------+ | | | +| | +Create | 3 | (a:Artist {name: line[$autoint_0]}) | 10 | 4 | 12 | | | | | +| | | +----+-------------------------------------+----------------+------+---------+----------------+ | | | +| | +Argument | 4 | line | 10 | 4 | 0 | 3472 | 0/0 | 0.852 | Fused in Pipeline 2 | +| | +----+-------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +LoadCSV | 5 | line | 10 | 4 | 0 | 328 | | | In Pipeline 1 | ++------------------+----+-------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -Total database accesses: 13, total allocated memory: 216 +Total database accesses: 12, total allocated memory: 4928 ---- ====== -[[query-plan-detach-delete]] -== Detach Delete -// DetachDelete - -The `DetachDelete` operator is used in all queries containing the xref::clauses/delete.adoc[DETACH DELETE] clause, when deleting nodes and their relationships. +[[query-plan-transaction-foreach]] +=== TransactionForeach +`TransactionForeach` works like the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-foreach[`Foreach`] operator but will commit the current transaction after a specified number of rows. -.DetachDelete +.TransactionForeach ====== +[NOTE] +The below query uses a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause] to import variables into the `CALL` subquery. + .Query [source, cypher] ---- PROFILE -MATCH (p:Person) -DETACH DELETE p +LOAD CSV FROM 'https://neo4j.com/docs/cypher-refcard/3.3/csv/artists.csv' AS line +CALL (line) { + CREATE (a: Artist {name: line[0]}) +} IN TRANSACTIONS OF 100 ROWS ---- .Query Plan @@ -6393,40 +6053,36 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} - -Batch size 128 - -+------------------+----------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+------------------+----------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | | 14 | 0 | 0 | | | | | -| | +----------+----------------+------+---------+----------------+ | | | -| +EmptyResult | | 14 | 0 | 0 | | | | | -| | +----------+----------------+------+---------+----------------+ | | | -| +DetachDelete | p | 14 | 14 | 41 | | | | | -| | +----------+----------------+------+---------+----------------+ | | | -| +NodeByLabelScan | p:Person | 14 | 14 | 35 | 120 | 21/0 | 12,439 | Fused in Pipeline 0 | -+------------------+----------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ - -Total database accesses: 112, total allocated memory: 200 ----- - -====== +Runtime version {neo4j-version-minor} +Batch size 128 -// MergeCreateNode -- removed in 4.3 +++---------------------+----+--------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ + | Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | + +---------------------+----+--------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ + | +ProduceResults | 0 | | 10 | 0 | 0 | 0 | | | | + | | +----+--------------------------------------------------+----------------+------+---------+----------------+ | | | + | +EmptyResult | 1 | | 10 | 0 | 0 | | 0/0 | 0.000 | Fused in Pipeline 3 | + | | +----+--------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ + | +TransactionForeach | 2 | IN TRANSACTIONS OF $autoint_1 ROWS ON ERROR FAIL | 10 | 4 | 0 | 4856 | | | | + | |\ +----+--------------------------------------------------+----------------+------+---------+----------------+ | | | + | | +Create | 3 | (a:Artist {name: line[$autoint_0]}) | 10 | 4 | 12 | | | | | + | | | +----+--------------------------------------------------+----------------+------+---------+----------------+ | | | + | | +Argument | 4 | line | 10 | 4 | 0 | 3472 | 0/0 | 0.712 | Fused in Pipeline 2 | + | | +----+--------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ + | +LoadCSV | 5 | line | 10 | 4 | 0 | 328 | | | In Pipeline 1 | + +---------------------+----+--------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -// MergeCreateRelationship -- removed in 4.3 + Total database accesses: 12, total allocated memory: 5704 +---- +====== [[query-plan-set-labels]] -== Set Labels -// SetLabels +=== Set Labels The `SetLabels` operator is used when setting labels on a node. - .SetLabels ====== @@ -6445,7 +6101,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 @@ -6468,12 +6124,10 @@ Total database accesses: 58, total allocated memory: 184 [[query-plan-remove-labels]] -== Remove Labels -// RemoveLabels +=== Remove Labels The `RemoveLabels` operator is used when deleting labels from a node. - .RemoveLabels ====== @@ -6492,7 +6146,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 @@ -6515,12 +6169,10 @@ Total database accesses: 51, total allocated memory: 184 [[query-plan-set-node-properties-from-map]] -== Set Node Properties From Map -// SetNodePropertiesFromMap +=== Set Node Properties From Map The `SetNodePropertiesFromMap` operator is used when setting properties from a map on a node. - .SetNodePropertiesFromMap ====== @@ -6539,7 +6191,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 @@ -6562,12 +6214,10 @@ Total database accesses: 141, total allocated memory: 184 [[query-plan-set-relationship-properties-from-map]] -== Set Relationship Properties From Map -// SetRelationshipPropertiesFromMap +=== Set Relationship Properties From Map The `SetRelationshipPropertiesFromMap` operator is used when setting properties from a map on a relationship. - .SetRelationshipPropertiesFromMap ====== @@ -6586,7 +6236,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 @@ -6609,12 +6259,11 @@ Total database accesses: 112, total allocated memory: 184 [[query-plan-set-property]] -== Set Property +=== Set Property // SetProperty The `SetProperty` operator is used when setting a property on a node or relationship. - .SetProperty ====== @@ -6633,7 +6282,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 @@ -6655,12 +6304,10 @@ Total database accesses: 106, total allocated memory: 184 ====== [[query-plan-set-properties]] -== Set Properties -// SetProperties +=== Set Properties The `SetProperties` operator is used when setting multiple properties on a node or relationship. - .SetProperties ====== @@ -6679,7 +6326,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version} +Runtime version {neo4j-version-minor} Batch size 128 @@ -6700,11 +6347,233 @@ Total database accesses: 141, total allocated memory: 312 ====== -[[query-plan-create-constraint]] -== Create Constraint -// CreateConstraint + +[[query-plan-load-csv]] +=== Load CSV + +The `LoadCSV` operator loads data from a CSV source into the query. +It is used whenever the xref::clauses/load-csv.adoc[LOAD CSV] clause is used in a query. + + +.LoadCSV +====== + +.Query +[source, cypher] +---- +PROFILE +LOAD CSV FROM 'https://neo4j.com/docs/cypher-refcard/3.3/csv/artists.csv' AS line +RETURN line +---- + +.Query Plan +[role="queryplan", subs="attributes+"] +---- +Planner COST + +Runtime PIPELINED + +Runtime version {neo4j-version-minor} + +Batch size 128 + ++-----------------+---------+----------------+------+---------+----------------+------------------------+-----------+---------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++-----------------+---------+----------------+------+---------+----------------+------------------------+-----------+---------------+ +| +ProduceResults | line | 10 | 4 | 0 | | 0/0 | 0.210 | | +| | +---------+----------------+------+---------+----------------+------------------------+-----------+ | +| +LoadCSV | line | 10 | 4 | 0 | 72 | | | In Pipeline 1 | ++-----------------+---------+----------------+------+---------+----------------+------------------------+-----------+---------------+ + +Total database accesses: 0, total allocated memory: 184 +---- + +====== + + +[[query-plan-eager]] +=== Eager + +The `Eager` operator causes all preceding operators to execute fully, for the whole dataset, before continuing execution. +This is done to ensure isolation between parts of the query plan that might otherwise affect each other. + +Values from the graph are fetched in a lazy manner; i.e. a pattern matching might not be fully exhausted before updates are applied. +To maintain correct semantics, the query planner will insert `Eager` operators into the query plan to prevent updates from influencing pattern matching, or other read operations. +This scenario is exemplified by the query below, where the `DELETE` clause would otherwise influence both the `MATCH` clause and the `MERGE` clause. +For more information on how the `Eager` operator can ensure correct semantics, see the section on xref::clauses/clause-composition.adoc[Clause composition]. + +The `Eager` operator can cause high memory usage when importing data or migrating graph structures. +In such cases, the operations should be split into simpler steps; e.g. importing nodes and relationships separately. +Alternatively, the records to be updated can be returned, followed by an update statement. + + +.Eager +====== + +.Query +[source, cypher] +---- +PROFILE +MATCH (a:Person {name: 'me'}), (b:Person {name: 'Bob'}) +DETACH DELETE a, b +MERGE (:Person {name: 'me'}) +---- + +.Query Plan +[role="queryplan", subs="attributes+"] +---- +Planner COST + +Runtime PIPELINED + +Runtime version {neo4j-version} + +Batch size 128 + ++---------------------+----+------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++---------------------+----+------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | | 0 | 0 | 0 | 0 | | | | +| | +----+------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +EmptyResult | 1 | | 0 | 0 | 0 | | | | | +| | +----+------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +Apply | 2 | | 0 | 1 | 0 | | | | | +| |\ +----+------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Merge | 3 | CREATE (anon_0:Person {name: $autostring_2}) | 0 | 1 | 3 | | | | | +| | | +----+------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +NodeIndexSeek | 4 | RANGE INDEX anon_0:Person(name) WHERE name = $autostring_2 | 0 | 0 | 1 | 3304 | 1/0 | 0.663 | Fused in Pipeline 3 | +| | +----+------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +Eager | 5 | read/delete conflict for variable: anon_0 (Operator: 6 vs 4, and 1 more conflicting operators) | 0 | 1 | 0 | 360 | 0/0 | 0.008 | In Pipeline 2 | +| | +----+------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +DetachDelete | 6 | b | 0 | 1 | 4 | | | | | +| | +----+------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +DetachDelete | 7 | a | 0 | 1 | 5 | | | | | +| | +----+------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +Eager | 8 | read/delete conflict for variable: b (Operator: 6 vs 10, and 1 more conflicting operators), | 0 | 1 | 0 | 360 | 1/0 | 0.226 | Fused in Pipeline 1 | +| | | | read/set conflict for label: Person (Operator: 3 vs 10), | | | | | | | | +| | | | read/set conflict for property: name (Operator: 3 vs 10) | | | | | | | | +| | +----+------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +MultiNodeIndexSeek | 9 | RANGE INDEX a:Person(name) WHERE name = $autostring_0, | 0 | 1 | 4 | 376 | 2/0 | 0.218 | In Pipeline 0 | +| | | RANGE INDEX b:Person(name) WHERE name = $autostring_1 | | | | | | | | ++---------------------+----+------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ + +Total database accesses: 17, total allocated memory: 4184 +---- + +====== + + +[[query-plan-assert-same-node]] +=== Assert Same Node + +The `AssertSameNode` operator is used to ensure that no node property uniqueness constraints are violated in the slotted and interpreted runtime. +The example looks for the presence of a team node with the supplied name and id, and if one does not exist, it will be created. +Owing to the existence of two node property uniqueness constraints on `:Team(name)` and `:Team(id)`, any node that would be found by the `UniqueIndexSeek` operator must be the very same node or the constraints would be violated. + + +.AssertSameNode +====== + +.Query +[source, cypher] +---- +PROFILE +CYPHER runtime=slotted +MERGE (t:Team {name: 'Engineering', id: 42}) +---- + +.Query Plan +[role="queryplan", subs="attributes+"] +---- +Planner COST + +Runtime SLOTTED + +Runtime version {neo4j-version} + ++---------------------------------+-------------------------------------------------------+----------------+------+---------+------------------------+ +| Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | ++---------------------------------+-------------------------------------------------------+----------------+------+---------+------------------------+ +| +ProduceResults | | 1 | 0 | 0 | 0/0 | +| | +-------------------------------------------------------+----------------+------+---------+------------------------+ +| +EmptyResult | | 1 | 0 | 0 | 0/0 | +| | +-------------------------------------------------------+----------------+------+---------+------------------------+ +| +Merge | CREATE (t:Team {name: $autostring_0, id: $autoint_1}) | 1 | 1 | 0 | 0/0 | +| | +-------------------------------------------------------+----------------+------+---------+------------------------+ +| +AssertSameNode | t | 0 | 1 | 0 | 0/0 | +| |\ +-------------------------------------------------------+----------------+------+---------+------------------------+ +| | +NodeUniqueIndexSeek(Locking) | UNIQUE t:Team(id) WHERE id = $autoint_1 | 1 | 1 | 1 | 0/1 | +| | +-------------------------------------------------------+----------------+------+---------+------------------------+ +| +NodeUniqueIndexSeek(Locking) | UNIQUE t:Team(name) WHERE name = $autostring_0 | 1 | 1 | 1 | 0/1 | ++---------------------------------+-------------------------------------------------------+----------------+------+---------+------------------------+ + +Total database accesses: 2, total allocated memory: 64 +---- + +====== +[[query-plan-assert-same-relationship]] +=== Assert Same Relationship + +The `AssertSameRelationship` operator is used to ensure that no relationship property uniqueness constraints are violated in the slotted and interpreted runtime. +The example looks for the presence of a `WORKS_IN` relationship with the supplied `id` and `badgeNumber`. +If it can't be found, then it will be created. +Owing to the existence of two property uniqueness constraints on `:WORKS_IN(id)` and `:WORKS_IN(badgeNumber)`, any relationship that would be found by the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-directed-relationship-unique-index-seek[`DirectedRelationshipUniqueIndexSeek`] operator must be the very same relationship or the constraints would be violated. + + +.AssertSameRelationship +====== + +.Query +[source, cypher] +---- +PROFILE +CYPHER runtime=slotted +MERGE (person)-[work:WORKS_IN {id: 0, badgeNumber: 4332}]->(location) +---- + +.Query Plan +[role="queryplan", subs="attributes+"] +---- +Planner COST + +Runtime SLOTTED + +Runtime version {neo4j-version} + ++-------------------------------------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+------------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | ++-------------------------------------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+------------------------+ +| +ProduceResults | 0 | | 1 | 0 | 0 | 0/0 | +| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+------------------------+ +| +EmptyResult | 1 | | 1 | 0 | 0 | 0/0 | +| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+------------------------+ +| +Merge | 2 | CREATE (person), (location), (person)-[work:WORKS_IN {id: $autoint_0, badgeNumber: $autoint_1}]->(lo | 1 | 1 | 0 | 0/0 | +| | | | cation) | | | | | +| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+------------------------+ +| +AssertSameRelationship | 3 | work | 0 | 1 | 0 | 0/0 | +| |\ +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+------------------------+ +| | +DirectedRelationshipUniqueIndexSeek(Locking) | 4 | RANGE INDEX (person)-[work:WORKS_IN(badgeNumber)]->(location) WHERE badgeNumber = $autoint_1 | 1 | 1 | 1 | 0/1 | +| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+------------------------+ +| +DirectedRelationshipUniqueIndexSeek(Locking) | 5 | RANGE INDEX (person)-[work:WORKS_IN(id)]->(location) WHERE id = $autoint_0 | 1 | 1 | 1 | 1/1 | ++-------------------------------------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+------------------------+ + +Total database accesses: 2, total allocated memory: 64 +---- + +====== + + +[[schema-system-operators]] +== Schema and system operators + +The operators in this group manage the schema and system-level operations within the database. +They handle tasks such as creating or dropping constraints and indexes, showing or terminating transactions, and listing the available procedures, functions, and settings. + +[[query-plan-create-constraint]] +=== Create Constraint + The `CreateConstraint` operator creates a constraint. This constraint can have any of the available constraint types: @@ -6716,7 +6585,6 @@ This constraint can have any of the available constraint types: The following query will create a property uniqueness constraint with the name `uniqueness` on the `name` property of nodes with the `Country` label. - .CreateConstraint ====== @@ -6750,8 +6618,7 @@ Total database accesses: ? [[query-plan-do-nothing-if-exists-constraint]] -== Do Nothing If Exists (constraint) -// DoNothingIfExists(CONSTRAINT) +=== Do Nothing If Exists (constraint) To not get an error creating the same constraint twice, we use the `DoNothingIfExists` operator for constraints. This will make sure no other constraint with the given name or another constraint of the same type and schema already exists before the specific `CreateConstraint` operator creates the constraint. @@ -6795,13 +6662,10 @@ Total database accesses: ? ====== [[query-plan-drop-constraint]] -== Drop Constraint -// DropConstraint +=== Drop Constraint The `DropConstraint` operator removes a constraint using the name of the constraint, no matter the type. - - .DropConstraint ====== @@ -6834,13 +6698,11 @@ Total database accesses: ? [[query-plan-show-constraints]] -== Show Constraints -// ShowConstraints +=== Show Constraints The `ShowConstraints` operator lists constraints. It may include filtering on constraint type and can have either default or full output. - .ShowConstraints ====== @@ -6875,8 +6737,7 @@ Total database accesses: 2, total allocated memory: 64 [[query-plan-create-index]] -== Create Index -// CreateIndex +=== Create Index The `CreateIndex` operator creates an index. @@ -6917,8 +6778,7 @@ Total database accesses: ? [[query-plan-do-nothing-if-exists-index]] -== Do Nothing If Exists (index) -// DoNothingIfExists(INDEX) +=== Do Nothing If Exists (index) To not get an error creating the same index twice, we use the `DoNothingIfExists` operator for indexes. This will make sure no other index with the given name or schema already exists before the `CreateIndex` operator creates an index. @@ -6961,12 +6821,10 @@ Total database accesses: ? [[query-plan-drop-index]] -== Drop Index -// DropIndex +=== Drop Index The `DropIndex` operator removes an index using the name of the index. - .DropIndex ====== @@ -6999,13 +6857,11 @@ Total database accesses: ? [[query-plan-show-indexes]] -== Show Indexes -// ShowIndexes +=== Show Indexes The `ShowIndexes` operator lists indexes. It may include filtering on index type and can have either default or full output. - .ShowIndexes ====== @@ -7041,8 +6897,7 @@ Total database accesses: 2, total allocated memory: 64 [[query-plan-show-functions]] -== Show Functions -// ShowFunctions +=== Show Functions The `ShowFunctions` operator lists functions. It may include filtering on built-in vs user-defined functions as well as if a given user can execute the function. @@ -7083,13 +6938,11 @@ Total database accesses: 0, total allocated memory: 64 [[query-plan-show-procedures]] -== Show Procedures -// ShowProcedures +=== Show Procedures The `ShowProcedures` operator lists procedures. It may include filtering on whether a given user can execute the procedure and can have either default or full output. - .ShowProcedures ====== @@ -7123,8 +6976,7 @@ Total database accesses: 0, total allocated memory: 64 ====== [[query-plan-show-settings]] -== Show Settings -// ShowSettings +=== Show Settings The `ShowSettings` operator lists configuration settings. @@ -7161,13 +7013,11 @@ Total database accesses: 0, total allocated memory: 64 ====== [[query-plan-show-transactions]] -== Show Transactions -// ShowTransactions +=== Show Transactions The `ShowTransactions` operator lists transactions. It may include filtering on given ids and can have either default or full output. - .ShowTransactions ====== @@ -7203,12 +7053,10 @@ Total database accesses: 0, total allocated memory: 64 [[query-plan-terminate-transactions]] -== Terminate Transactions -// TerminateTransactions +=== Terminate Transactions The `TerminateTransactions` operator terminates transactions by ID. - .TerminateTransactions ====== diff --git a/modules/ROOT/pages/planning-and-tuning/query-tuning.adoc b/modules/ROOT/pages/planning-and-tuning/query-tuning.adoc index 9c7130e0c..7f9af83f4 100644 --- a/modules/ROOT/pages/planning-and-tuning/query-tuning.adoc +++ b/modules/ROOT/pages/planning-and-tuning/query-tuning.adoc @@ -308,7 +308,7 @@ During times of known high load, `replan=skip` can be useful to not introduce un === Cypher infer schema parts For some queries, the planner can infer predicates such as labels or types from the graph structure, thereby enhancing its ability to estimate the number of rows each operator will produce. -(See xref:planning-and-tuning/execution-plans.adoc#runtimes-reading-execution-plans[Understanding execution plans - Reading execution plans] for more information about the role of operators and estimated row counts in query execution plans.) +(See xref:planning-and-tuning/execution-plans.adoc#reading-execution-plans[Understanding execution plans - Reading execution plans] for more information about the role of operators and estimated row counts in query execution plans.) The option `inferSchemaParts` controls the extent to which the planner should infer predicates. [options="header",cols="2m,3a"] From dc2a8b19bc89263193ce27f841f7f639377cf0a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Tue, 3 Dec 2024 14:19:30 +0100 Subject: [PATCH 48/77] Add page-alias to CALL subquery page (#1127) --- modules/ROOT/pages/subqueries/call-subquery.adoc | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/ROOT/pages/subqueries/call-subquery.adoc b/modules/ROOT/pages/subqueries/call-subquery.adoc index 6f8a4905a..81edd047c 100644 --- a/modules/ROOT/pages/subqueries/call-subquery.adoc +++ b/modules/ROOT/pages/subqueries/call-subquery.adoc @@ -1,5 +1,6 @@ = CALL subqueries :description: This page describes how to use Cypher's `CALL` subquery. +:page-aliases: clauses/call-subquery.adoc The `CALL` clause can be used to invoke subqueries that execute operations within a defined scope, thereby optimizing data handling and query efficiency. Unlike other subqueries in Cypher, `CALL` subqueries can be used to perform changes to the database (e.g. xref:clauses/create.adoc[] new nodes). From 900109991144a4ea7a8d471cee4f8aea5f608b84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Tue, 3 Dec 2024 15:03:28 +0100 Subject: [PATCH 49/77] Clarify that negative concurrency values in CiCT can only be done through a parameter (#1128) --- modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc b/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc index b2eb52351..6202cb5f8 100644 --- a/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc +++ b/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc @@ -601,7 +601,7 @@ This allows `CALL` subqueries to utilize multiple CPU cores simultaneously, whic [NOTE] The concurrency value is optional. If not specified, a default value based on the amount of available CPU cores will be chosen. -If a negative number is specified, the concurrency will be the number of available CPU cores reduced by the absolute value of that number. +If a negative number is specified (which can only be done through a parameter), the concurrency will be the number of available CPU cores reduced by the absolute value of that number. .Load a CSV file in concurrent transactions ==== From 4c20ac5a9d86b4a8da9bdf6f37759cfa05ecadc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Thu, 19 Dec 2024 09:59:50 +0100 Subject: [PATCH 50/77] Several small fixes to query plan ascii and links (#1136) --- ...ions-additions-removals-compatibility.adoc | 2 +- .../operators/operators-detail.adoc | 133 +++++++++--------- 2 files changed, 66 insertions(+), 69 deletions(-) diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index f7691d071..c9d79b2c8 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -371,7 +371,7 @@ CREATE (n:$(line.label) {name: line.Name}) ---- | Added the ability to dynamically reference node labels and relationship types in xref:clauses/match.adoc#dynamic-match[`MATCH`], xref:clauses/create.adoc#dynamic-create[`CREATE`], and xref:clauses/merge.adoc#dynamic-merge[`MERGE`] clauses. -Also introduced the ability to specify CSV columns dynamically when using xref:clauses/load-csv.adoc#dynamic-load[`LOAD CSV`]. +Also introduced the ability to specify CSV columns dynamically when using xref:clauses/load-csv.adoc#dynamic-columns[`LOAD CSV`]. |=== diff --git a/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc b/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc index 2b6b818e4..fa208f2c2 100644 --- a/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc +++ b/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc @@ -4379,26 +4379,25 @@ Runtime SLOTTED Runtime version {neo4j-version} -+-------------------+----------------------------------------+----------------+------+---------+------------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | -+-------------------+----------------------------------------+----------------+------+---------+------------------------+ -| +ProduceResults | `other.name` | 4 | 24 | 0 | 0/0 | -| | +----------------------------------------+----------------+------+---------+------------------------+ -| +Projection | other.name AS `other.name` | 4 | 24 | 24 | 1/0 | -| | +----------------------------------------+----------------+------+---------+------------------------+ -| +Filter | not anon_2 = anon_4 | 16 | 24 | 0 | 0/0 | -| | +----------------------------------------+----------------+------+---------+------------------------+ -| +TriadicSelection | WHERE NOT (me)--(other) | 4 | 24 | 0 | 0/0 | -| |\ +----------------------------------------+----------------+------+---------+------------------------+ -| | | +----------------------------------------+----------------+------+---------+------------------------+ -| | +Expand(All) | (anon_3)-[anon_4:FRIENDS_WITH]-(other) | 16 | 48 | 98 | 48/0 | -| | | +----------------------------------------+----------------+------+---------+------------------------+ -| | +Argument | anon_3, anon_2 | 24 | 24 | 0 | 0/0 | -| | +----------------------------------------+----------------+------+---------+------------------------+ -| +Expand(All) | (me)-[anon_2:FRIENDS_WITH]-(anon_3) | 24 | 24 | 53 | 28/0 | -| | +----------------------------------------+----------------+------+---------+------------------------+ -| +NodeByLabelScan | me:Person | 15 | 15 | 16 | 1/0 | -+-------------------+----------------------------------------+----------------+------+---------+------------------------+ ++-------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | ++-------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+ +| +ProduceResults | 0 | `other.name` | 15 | 24 | 0 | 0 | 0/0 | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ +| +Projection | 1 | other.name AS `other.name` | 15 | 24 | 24 | | 0/0 | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ +| +Filter | 2 | NOT anon_2 = anon_0 | 15 | 24 | 0 | | 0/0 | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ +| +TriadicSelection | 3 | WHERE NOT (me)--(other) | 15 | 48 | 0 | | 0/0 | +| |\ +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ +| | +Expand(All) | 4 | (anon_1)-[anon_2:FRIENDS_WITH]-(other) | 16 | 48 | 72 | | 0/0 | +| | | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ +| | +Argument | 5 | anon_1, anon_0 | 24 | 24 | 0 | | 0/0 | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ +| +Expand(All) | 6 | (me)-[anon_0:FRIENDS_WITH]-(anon_1) | 24 | 24 | 38 | | 2/0 | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ +| +NodeByLabelScan | 7 | me:Person | 14 | 14 | 15 | | 1/0 | ++-------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+ Total database accesses: 246, total allocated memory: 64 ---- @@ -4439,30 +4438,29 @@ Runtime version {neo4j-version} Batch size 128 -+-----------------+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-----------------+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | `other.name` | 4 | 24 | 0 | | 0/0 | 0.133 | | -| | +----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | -| +Projection | other.name AS `other.name` | 4 | 24 | 48 | | 2/0 | 0.056 | | -| | +----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +Filter | not anon_2 = anon_4 | 16 | 24 | 0 | | | | | -| | +----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +TriadicFilter | WHERE NOT (me)--(other) | 4 | 24 | 0 | 4136 | 0/0 | 0.195 | In Pipeline 3 | -| | +----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +Apply | | 16 | 24 | 0 | | 0/0 | | | -| |\ +----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| | | +----------------------------------------+----------------+------+---------+----------------+ | | | -| | +Expand(All) | (anon_3)-[anon_4:FRIENDS_WITH]-(other) | 16 | 48 | 98 | | | | | -| | | +----------------------------------------+----------------+------+---------+----------------+ | | | -| | +Argument | anon_3, anon_2 | 24 | 24 | 0 | 4200 | 0/0 | 0.397 | Fused in Pipeline 2 | -| | +----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +TriadicBuild | (me)--(anon_3) | 24 | 24 | 0 | 888 | 0/0 | 1.427 | In Pipeline 1 | -| | +----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +Expand(All) | (me)-[anon_2:FRIENDS_WITH]-(anon_3) | 24 | 24 | 39 | | | | | -| | +----------------------------------------+----------------+------+---------+----------------+ | | | -| +NodeByLabelScan| me:Person | 15 | 15 | 16 | 120 | 3/0 | 0,200 | Fused in Pipeline 0 | -+-----------------+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | `other.name` | 15 | 24 | 0 | 0 | 0/0 | 0.230 | | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | +| +Projection | 1 | other.name AS `other.name` | 15 | 24 | 48 | | 0/0 | 0.424 | | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | +| +Filter | 2 | NOT anon_2 = anon_0 | 15 | 24 | 0 | | 0/0 | 0.731 | | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | +| +TriadicFilter | 10 | WHERE NOT (me)--(other) | 15 | 48 | 0 | 7216 | 0/0 | 0.690 | In Pipeline 3 | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +Apply | 9 | | 16 | 48 | 0 | | 0/0 | | | +| |\ +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| | +Expand(All) | 4 | (anon_1)-[anon_2:FRIENDS_WITH]-(other) | 16 | 48 | 72 | | | | | +| | | +----+----------------------------------------+----------------+------+---------+----------------+ | | | +| | +Argument | 5 | anon_1, anon_0 | 24 | 24 | 0 | 4464 | 0/0 | 1.143 | Fused in Pipeline 2 | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +TriadicBuild | 8 | (me)--(anon_1) | 24 | 24 | 0 | 1080 | 0/0 | 5.317 | In Pipeline 1 | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +Expand(All) | 6 | (me)-[anon_0:FRIENDS_WITH]-(anon_1) | 24 | 24 | 38 | | | | | +| | +----+----------------------------------------+----------------+------+---------+----------------+ | | | +| +NodeByLabelScan | 7 | me:Person | 14 | 14 | 15 | 376 | 3/0 | 2.444 | Fused in Pipeline 0 | ++------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ Total database accesses: 256, total allocated memory: 7376 ---- @@ -4503,30 +4501,29 @@ Runtime version {neo4j-version} Batch size 128 -+-----------------+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+-----------------+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | `other.name` | 4 | 24 | 0 | | 0/0 | 0.189 | | -| | +----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | -| +Projection | other.name AS `other.name` | 4 | 24 | 48 | | 2/0 | 0.381 | | -| | +----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +Filter | not anon_2 = anon_4 | 16 | 24 | 0 | | | | | -| | +----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +TriadicFilter | WHERE NOT (me)--(other) | 4 | 24 | 0 | 4136 | 0/0 | 0.685 | In Pipeline 3 | -| | +----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +Apply | | 16 | 24 | 0 | | 0/0 | | | -| |\ +----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| | | +----------------------------------------+----------------+------+---------+----------------+ | | | -| | +Expand(All) | (anon_3)-[anon_4:FRIENDS_WITH]-(other) | 16 | 48 | 98 | | | | | -| | | +----------------------------------------+----------------+------+---------+----------------+ | | | -| | +Argument | anon_3, anon_2 | 24 | 24 | 0 | 4200 | 0/0 | 0.496 | Fused in Pipeline 2 | -| | +----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +TriadicBuild | (me)--(anon_3) | 24 | 24 | 0 | 888 | 0/0 | 3.268 | In Pipeline 1 | -| | +----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +Expand(All) | (me)-[anon_2:FRIENDS_WITH]-(anon_3) | 24 | 24 | 39 | | | | | -| | +----------------------------------------+----------------+------+---------+----------------+ | | | -| +NodeByLabelScan| me:Person | 15 | 15 | 16 | 120 | 3/0 | 0,481 | Fused in Pipeline 0 | -+-----------------+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | `other.name` | 15 | 24 | 0 | 0 | 0/0 | 0.460 | | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | +| +Projection | 1 | other.name AS `other.name` | 15 | 24 | 48 | | 0/0 | 0.437 | | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | +| +Filter | 2 | NOT anon_2 = anon_0 | 15 | 24 | 0 | | 0/0 | 0.377 | | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | +| +TriadicFilter | 10 | WHERE NOT (me)--(other) | 15 | 48 | 0 | 7216 | 0/0 | 0.337 | In Pipeline 3 | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +Apply | 9 | | 16 | 48 | 0 | | 0/0 | | | +| |\ +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| | +Expand(All) | 4 | (anon_1)-[anon_2:FRIENDS_WITH]-(other) | 16 | 48 | 72 | | | | | +| | | +----+----------------------------------------+----------------+------+---------+----------------+ | | | +| | +Argument | 5 | anon_1, anon_0 | 24 | 24 | 0 | 4464 | 0/0 | 0.608 | Fused in Pipeline 2 | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +TriadicBuild | 8 | (me)--(anon_1) | 24 | 24 | 0 | 1080 | 0/0 | 0.540 | In Pipeline 1 | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +Expand(All) | 6 | (me)-[anon_0:FRIENDS_WITH]-(anon_1) | 24 | 24 | 38 | | | | | +| | +----+----------------------------------------+----------------+------+---------+----------------+ | | | +| +NodeByLabelScan | 7 | me:Person | 14 | 14 | 15 | 376 | 3/0 | 0.459 | Fused in Pipeline 0 | ++------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ Total database accesses: 256, total allocated memory: 7376 ---- From f8509241e13bd8a67ff0addf331b7d14d8ef3c22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Thu, 19 Dec 2024 15:22:30 +0100 Subject: [PATCH 51/77] Add Performance caveats section to Merge/Match dynamic labels section (#1137) --- modules/ROOT/pages/clauses/load-csv.adoc | 5 +++ modules/ROOT/pages/clauses/match.adoc | 12 ++++-- modules/ROOT/pages/clauses/merge.adoc | 48 +++++++++++++++++++++--- 3 files changed, 56 insertions(+), 9 deletions(-) diff --git a/modules/ROOT/pages/clauses/load-csv.adoc b/modules/ROOT/pages/clauses/load-csv.adoc index aae02b519..740ae67b7 100644 --- a/modules/ROOT/pages/clauses/load-csv.adoc +++ b/modules/ROOT/pages/clauses/load-csv.adoc @@ -339,6 +339,11 @@ RETURN n AS bandNodes Added 4 nodes, Set 4 properties, Added 4 labels |=== +[NOTE] +`MERGE` queries using dynamic values may not be as performant as those using static values. +This is because the xref:planning-and-tuning/execution-plans.adoc[Cypher planner] uses statically available information when planning queries to determine whether to use an xref:indexes/search-performance-indexes/overview.adoc[index] or not, and this is not possible when using dynamic values. +For more information, see xref:clauses/merge.adoc#dynamic-merge-caveats[`MERGE` using dynamic node labels and relationship types -> Performance caveats]. + === Import compressed CSV files `LOAD CSV` can read local CSV files compressed with ZIP or gzip. diff --git a/modules/ROOT/pages/clauses/match.adoc b/modules/ROOT/pages/clauses/match.adoc index 446e48d8d..207483bde 100644 --- a/modules/ROOT/pages/clauses/match.adoc +++ b/modules/ROOT/pages/clauses/match.adoc @@ -522,10 +522,6 @@ The expression must evaluate to a `STRING NOT NULL | LIST NOT N If you use a `LIST` with more than one item in a relationship pattern with dynamic relationship types, no results will be returned. This is because a relationship can only have exactly one type. -[NOTE] -Queries using dynamic values may not be as performant as those using static values. -This is because the xref:planning-and-tuning/execution-plans.adoc[Cypher planner] uses statically available information when planning queries to determine whether to use an xref:indexes/search-performance-indexes/overview.adoc[index] or not, and this is not possible when using dynamic values. - .Match labels dynamically [source, cypher] ---- @@ -614,3 +610,11 @@ RETURN relationshipType, count(r) AS relationshipCount 2+d|Rows: 2 |=== +[[dynamic-match-caveats]] +=== Performance caveats + +`MATCH` queries using dynamic values may not be as performant as those using static values. +This is because the xref:planning-and-tuning/execution-plans.adoc[Cypher planner] uses statically available information when planning queries to determine whether to use an xref:indexes/search-performance-indexes/overview.adoc[index] or not, and this is not possible when using dynamic values. + +As a result, `MATCH` queries using dynamic values cannot leverage xref:planning-and-tuning/operators/operators-detail.adoc#leaf-operators[index scans or seeks] and must instead use the xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-all-nodes-scan[`AllNodesScan`] operator, which reads all nodes from the node store and is therefore more costly. + diff --git a/modules/ROOT/pages/clauses/merge.adoc b/modules/ROOT/pages/clauses/merge.adoc index bb3000a38..afb4b7533 100644 --- a/modules/ROOT/pages/clauses/merge.adoc +++ b/modules/ROOT/pages/clauses/merge.adoc @@ -702,10 +702,6 @@ The expression must evaluate to a `STRING NOT NULL | LIST NOT N Using a `LIST` with more than one item when merging a relationship using dynamic relationship types will fail. This is because a relationship can only have exactly one type. -[NOTE] -Queries using dynamic values may not be as performant as those using static values. -This is because the xref:planning-and-tuning/execution-plans.adoc[Cypher planner] uses statically available information when planning queries to determine whether to use an xref:indexes/search-performance-indexes/overview.adoc[index] or not, and this is not possible when using dynamic values. - .Parameters [source, parameters] ---- @@ -727,7 +723,7 @@ RETURN greta.name AS name, labels(greta) AS labels, type(rel) AS relType, collec ---- .Result -[role="queryresult",options="footer",cols="3* Date: Fri, 20 Dec 2024 13:02:35 +0100 Subject: [PATCH 52/77] Change release version to 2025.02 (#1140) --- .../pages/deprecations-additions-removals-compatibility.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index c9d79b2c8..aee5a8c52 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -17,7 +17,7 @@ This section lists all of the features that have been removed, deprecated, added Replacement syntax for deprecated and removed features are also indicated. [[cypher-deprecations-additions-removals-2025.01]] -== Neo4j 2025.01 +== Neo4j 2025.02 === Removed features [cols="2", options="header"] From c4c14fcf3f5bc9ac75514b76ae63b1e41e35d5c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Fri, 20 Dec 2024 13:28:27 +0100 Subject: [PATCH 53/77] Add seedRestoreUntil option (#1141) --- ...tions-additions-removals-compatibility.adoc | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index aee5a8c52..7950da1b2 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -134,6 +134,24 @@ Several xref:clauses/transaction-clauses.adoc#query-listing-transactions[`SHOW * The current query-related columns — `currentQuery`, `currentQueryId`, `parameters`, `planner`, `runtime`, `indexes`, `currentQueryStartTime`, `currentQueryElapsedTime`, `currentQueryCpuTime`, `currentQueryIdleTime`, and `currentQueryStatus` — now return `null` when no query is executing. |=== +=== New features + +[cols="2", options="header"] +|=== +| Feature +| Details +a| +label:functionality[] +label:new[] +[source, cypher, role="noheader"] +---- +CREATE DATABASE db OPTIONS { seedRestoreUntil: ... } +---- +| The option `seedRestoreUntil` can now be specified in the `CREATE DATABASE` `OPTIONS` map. +This allows a database to be seeded up to a specific date or transaction ID. +For more information, see link:{neo4j-docs-base-uri}/operations-manual/{page-version}/clustering/databases/#cluster-seed-uri[Operations Manual -> Clustering -> Seed from URI]. +|=== + [[cypher-deprecations-additions-removals-5.26]] == Neo4j 5.26 From 7a1fc2a5cb0e172f7584033befff92ad1aa88298 Mon Sep 17 00:00:00 2001 From: Gem Lamont <106068376+gem-neo4j@users.noreply.github.com> Date: Fri, 20 Dec 2024 14:45:15 +0100 Subject: [PATCH 54/77] Allow for parameters in SHORTEST (#1124) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jens Pryce-Åklundh <112686610+JPryce-Aklundh@users.noreply.github.com> --- ...ions-additions-removals-compatibility.adoc | 20 +++++++++++++++++++ modules/ROOT/pages/patterns/reference.adoc | 4 ++-- .../ROOT/pages/patterns/shortest-paths.adoc | 4 ++-- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index 7950da1b2..95e7a6c35 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -93,6 +93,26 @@ MATCH (n)-[r:REL]->(m) SET n = properties(r) | Feature | Details +a| +label:functionality[] +label:updated[] +[source, cypher, role=noheader] +---- +MATCH SHORTEST $param (:A)-[:R]->{0,10}(:B) +---- + +[source, cypher, role=noheader] +---- +MATCH p = ANY $param (:A)-[:R]->{0,10}(:B) +---- + +[source, cypher, role=noheader] +---- +MATCH SHORTEST $param GROUPS (:A)-[:R]->{0,10}(:B) +---- + +a| Parameters can now be used in xref:patterns/shortest-paths.adoc[`SHORTEST` and `ANY` path patterns]. + a| label:functionality[] label:updated[] diff --git a/modules/ROOT/pages/patterns/reference.adoc b/modules/ROOT/pages/patterns/reference.adoc index 4ea43aaab..3f762c53f 100644 --- a/modules/ROOT/pages/patterns/reference.adoc +++ b/modules/ROOT/pages/patterns/reference.adoc @@ -1165,10 +1165,10 @@ anyPathSearch ::= "ANY" [ numberOfPaths ] [ pathOrPaths ] pathOrPaths ::= { "PATH" | "PATHS" } -numberOfPaths ::= unsignedDecimalInteger +numberOfPaths ::= unsignedDecimalInteger | parameter -numberOfGroups ::= unsignedDecimalInteger +numberOfGroups ::= unsignedDecimalInteger | parameter ---- [NOTE] diff --git a/modules/ROOT/pages/patterns/shortest-paths.adoc b/modules/ROOT/pages/patterns/shortest-paths.adoc index a177ffce3..0893ce363 100644 --- a/modules/ROOT/pages/patterns/shortest-paths.adoc +++ b/modules/ROOT/pages/patterns/shortest-paths.adoc @@ -19,7 +19,7 @@ Use Cypher if: * You need to specify complex graph navigation via xref:patterns/variable-length-patterns.adoc#quantified-path-patterns[quantified path patterns]. * Creating a link:https://neo4j.com/docs/graph-data-science/current/management-ops/graph-creation/graph-project/[graph projection] takes too long. -* GDS is not available in your instance, or the size of the GDS projection is too large for your instance. +* GDS is not available in your instance, or the size of the GDS projection is too large for your instance. Use GDS if: @@ -64,7 +64,7 @@ CREATE (asc)-[:LINK {distance: 7.25}]->(cnm), (wof)-[:LINK {distance: 0.65}]->(wos) ---- -The paths matched by a xref:patterns/fixed-length-patterns.adoc#path-patterns[path pattern] can be restricted to only the shortest (by number of hops) by including the keyword `SHORTEST k`, where `k` is the number of paths to match. +The paths matched by a xref:patterns/fixed-length-patterns.adoc#path-patterns[path pattern] can be restricted to only the shortest (by number of hops) by including the keyword `SHORTEST k`, where `k` is the number of paths to match, and can be either an `INTEGER` literal or, as of Neo4j 2025.02, a parameter which resolves to an `INTEGER`. For example, the following example uses `SHORTEST 1` to return the length of the shortest path between `Worcester Shrub Hill` and `Bromsgrove`: .Query From 1418736535ab3b0155b642f80fdc44389ef55251 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Tue, 7 Jan 2025 11:23:48 +0100 Subject: [PATCH 55/77] Add dynamically referenced labels and types to allowed parameters (#1144) --- modules/ROOT/pages/clauses/where.adoc | 11 +++++++++-- modules/ROOT/pages/syntax/parameters.adoc | 12 +++++++----- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/modules/ROOT/pages/clauses/where.adoc b/modules/ROOT/pages/clauses/where.adoc index 9d4546119..977105dd6 100644 --- a/modules/ROOT/pages/clauses/where.adoc +++ b/modules/ROOT/pages/clauses/where.adoc @@ -185,12 +185,19 @@ The `name`, `age` and `email` values for `Peter` are returned because `Andy` has To filter on a property using a dynamically computed name, use square bracket syntax: +.Parameters +[source, parameters] +---- +{ + "propname": "age" +} +---- + .Query [source, cypher] ---- -WITH 'AGE' AS propname MATCH (n:Person) -WHERE n[toLower(propname)] < 30 +WHERE n[$propname] < 30 RETURN n.name, n.age ---- diff --git a/modules/ROOT/pages/syntax/parameters.adoc b/modules/ROOT/pages/syntax/parameters.adoc index 41a006e10..9c6920570 100644 --- a/modules/ROOT/pages/syntax/parameters.adoc +++ b/modules/ROOT/pages/syntax/parameters.adoc @@ -15,14 +15,16 @@ Additionally, parameters make caching of execution plans much easier for Cypher, Parameters can be used for: -* literals and expressions -* node and relationship ids +* Literals and expressions. +* Node and relationship ids. +* Properties, when referenced dynamically (for more information, see xref:clauses/where.adoc#filter-on-dynamic-property[Filter on dynamically-computed node property]). +* Node labels and relationship types, when referenced dynamically (for more information, see xref:clauses/match.adoc#dynamic-match[`MATCH` using dynamic node labels and relationship types]). Parameters cannot be used for the following constructs, as these form part of the query structure that is compiled into a query plan: -* property keys; so `MATCH (n) WHERE n.$param = 'something'` is invalid -* relationship types; so `MATCH (n)-[:$param]->(m)` is invalid -* labels; so `MATCH (n:$param)` is invalid +* Property keys; `MATCH (n) WHERE n.$param = 'something'` is invalid. +* Relationship types; `MATCH (n)-[:$param]->(m)` is invalid. +* Node labels; `MATCH (n:$param)` is invalid. Parameters may consist of letters and numbers, and any combination of these, but cannot start with a number or a currency symbol. From 304124e8951860d355b7387264b1f88d1a40a455 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nadja=20M=C3=BCller?= <73830555+nadja-muller@users.noreply.github.com> Date: Tue, 7 Jan 2025 15:26:22 +0100 Subject: [PATCH 56/77] document deprecation of graph names with unesacped dots in USE clauses (#1145) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jens Pryce-Åklundh <112686610+JPryce-Aklundh@users.noreply.github.com> --- ...eprecations-additions-removals-compatibility.adoc | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index 95e7a6c35..e65f02149 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -306,6 +306,18 @@ CREATE DATABASE db OPTIONS { storeFormat: 'high_limit' } | The `standard` and `high_limit` store formats have been deprecated. Creating databases with these formats is therefore also deprecated. For more information on the deprecation of these formats, see link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-internals/store-formats/#format-deprecations[Store formats -> Format deprecations]. + +a| +label:functionality[] +label:deprecated[] +[source, cypher, role="noheader"] +---- +USE my.db ... + +---- +| In xref:clauses/use.adoc[`USE`] clauses, databases and aliases with unquoted `.` are deprecated unless the `.` is used to indicate that the database or alias belongs to a composite database. +Names containing `.` should be quoted using backticks. +For example, `USE `my.db`` is valid. |=== From c66b0c20d6e7b3ee967186efa0ea3d5ba18bc81c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Thu, 9 Jan 2025 09:21:07 +0100 Subject: [PATCH 57/77] Correct genai example (#1149) Co-authored-by: Jennifer Reif --- modules/ROOT/pages/genai-integrations.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/ROOT/pages/genai-integrations.adoc b/modules/ROOT/pages/genai-integrations.adoc index 649de2644..13ff3ed3d 100644 --- a/modules/ROOT/pages/genai-integrations.adoc +++ b/modules/ROOT/pages/genai-integrations.adoc @@ -182,7 +182,7 @@ WITH collect(m) AS moviesList // <1> 100 AS batchSize // <2> UNWIND range(0, total, batchSize) AS batchStart // <3> CALL (moviesList, batchStart, batchSize) { // <4> - WITH [movie IN moviesList[batchStart .. batchStart + batchSize] | movie.title || ': ' || movie.plot] AS resources // <5> + WITH [movie IN moviesList[batchStart .. batchStart + batchSize] | movie.title || ': ' || movie.plot] AS batch // <5> CALL genai.vector.encodeBatch(batch, 'OpenAI', { token: $token }) YIELD index, vector CALL db.create.setNodeVectorProperty(moviesList[batchStart + index], 'embedding', vector) // <6> } IN TRANSACTIONS OF 1 ROW <7> @@ -195,7 +195,7 @@ Too large a batch size may also exceed the provider's threshold. <3> Process `Movie` nodes in increments of `batchSize`. <4> A xref:subqueries/subqueries-in-transactions.adoc[`CALL` subquery] executes a separate transaction for each batch. Note that this `CALL` subquery uses a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause]. -<5> `resources` is a list of strings, each being the concatenation of `title` and `plot` of one movie. +<5> `batch` is a list of strings, each being the concatenation of `title` and `plot` of one movie. <6> The procedure sets `vector` as value for the property named `embedding` for the node at position `batchStart + index` in the `moviesList`. <7> Set to `1` the amount of batches to be processed at once. From 7ae0caddb8ca313121d8b75af75c7ffb34c5be14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Thu, 9 Jan 2025 11:32:11 +0100 Subject: [PATCH 58/77] The Cypher query option eagerAnalyzer is deprecated #1147 (#1150) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bastien Louërat --- ...ions-additions-removals-compatibility.adoc | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index e65f02149..8e31d613c 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -16,7 +16,7 @@ New features are added to the language continuously, and occasionally, some feat This section lists all of the features that have been removed, deprecated, added, or extended in different Cypher versions. Replacement syntax for deprecated and removed features are also indicated. -[[cypher-deprecations-additions-removals-2025.01]] +[[cypher-deprecations-additions-removals-2025.02]] == Neo4j 2025.02 === Removed features @@ -172,6 +172,35 @@ This allows a database to be seeded up to a specific date or transaction ID. For more information, see link:{neo4j-docs-base-uri}/operations-manual/{page-version}/clustering/databases/#cluster-seed-uri[Operations Manual -> Clustering -> Seed from URI]. |=== +[[cypher-deprecations-additions-removals-2025.01]] +== Neo4j 2025.01 + +=== Deprecated features + +[cols="2", options="header"] +|=== +| Feature +| Details + +a| +label:functionality[] +label:deprecated[] +[source, cypher, role="noheader"] +---- +CYPHER eagerAnalyzer=ir MATCH (a)-->(b) DELETE b RETURN a +---- + +[source, cypher, role="noheader"] +---- +CYPHER eagerAnalyzer=lp MATCH (a)-->(b) DELETE b RETURN a +---- +a| + +The Cypher query option `eagerAnalyzer` is deprecated and will be removed without a replacement. +Eagerness analysis is systematically performed on the logical plan regardless of the value provided. + +|=== + [[cypher-deprecations-additions-removals-5.26]] == Neo4j 5.26 @@ -318,6 +347,7 @@ USE my.db ... | In xref:clauses/use.adoc[`USE`] clauses, databases and aliases with unquoted `.` are deprecated unless the `.` is used to indicate that the database or alias belongs to a composite database. Names containing `.` should be quoted using backticks. For example, `USE `my.db`` is valid. + |=== From 016406eae63202066ed96d17bdcfd17da3ad2d1b Mon Sep 17 00:00:00 2001 From: dogofbrian Date: Thu, 9 Jan 2025 15:15:05 +0000 Subject: [PATCH 59/77] Fix examples in Patterns / Syntax and semantics / shortestPaths (#1151) The examples in Patterns / Syntax and semantics / shortestPaths / Examples mix legacy shortest path and QPPs, which is disallowed. This PR changes them to variable-length relationships. It also improves the header "Restricted to variable length". QPPs are disallowed but also variable length. What they are not are variable-length relationships. --- modules/ROOT/pages/patterns/reference.adoc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/ROOT/pages/patterns/reference.adoc b/modules/ROOT/pages/patterns/reference.adoc index 3f762c53f..977a019a6 100644 --- a/modules/ROOT/pages/patterns/reference.adoc +++ b/modules/ROOT/pages/patterns/reference.adoc @@ -1399,7 +1399,7 @@ Note that it is possible to pass a fixed length path pattern (with a single rela === Rules [[shortest-functions-rules-var-length-restriction]] -==== Restricted to variable length +==== Restricted to variable-length relationships The pattern in the path selector function must be a variable-length relationship and not a quantified path pattern. @@ -1470,14 +1470,14 @@ Return a single shortest path for each distinct pair of nodes matching `(:A)` an [source, role=noheader] ---- -MATCH shortestPath((:A)-[:R]->{0,10}(:B)) +MATCH shortestPath((:A)-[:R*0..10]->(:B)) ---- Return all paths equal to the shortest path length for each distinct pair of nodes matching `(:A)` and `(:B)`: [source, role=noheader] ---- -MATCH allShortestPaths((:A)-[:R]->{0,10}(:B)) +MATCH allShortestPaths((:A)-[:R*0..10]->(:B)) ---- [[graph-patterns]] From f26f17abea0f5b1ea757e3d4d6b1bd2a41f20a67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Fri, 10 Jan 2025 13:01:02 +0100 Subject: [PATCH 60/77] Explain trigram index for text indexes (#1153) --- .../managing-indexes.adoc | 14 +++++++++++++- .../search-performance-indexes/using-indexes.adoc | 2 +- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/modules/ROOT/pages/indexes/search-performance-indexes/managing-indexes.adoc b/modules/ROOT/pages/indexes/search-performance-indexes/managing-indexes.adoc index 82a7a92d6..4e8f43cdd 100644 --- a/modules/ROOT/pages/indexes/search-performance-indexes/managing-indexes.adoc +++ b/modules/ROOT/pages/indexes/search-performance-indexes/managing-indexes.adoc @@ -214,7 +214,7 @@ Instad an informational notification is returned. Creating a text index can be done with the `CREATE TEXT INDEX` command. Note that the index name must be unique. -Text indexes have no supported index configuration and they have two index providers available, `text-2.0` (default) and `text-1.0` (deprecated). +Text indexes have no supported index configuration and they have two index providers available, `text-2.0` (default -- see xref:indexes/search-performance-indexes/managing-indexes.adoc#text-indexes-trigram-indexes[Trigram indexing] below for more information) and `text-1.0` (deprecated). [[text-indexes-supported-predicates]] [discrete] @@ -284,6 +284,18 @@ See the section about xref:indexes/search-performance-indexes/using-indexes.adoc [TIP] Text indexes are only used for exact query matches. To perform approximate matches (including, for example, variations and typos), and to compute a similarity score between `STRING` values, use semantic xref:indexes/semantic-indexes/full-text-indexes.adoc[full-text indexes] instead. +[[text-indexes-trigram-indexes]] +==== Trigram indexing + +The default text index provider, `text-2.0`, uses trigram indexing. +This means that `STRING` values are indexed into overlapping trigrams, each containing three Unicode code points. +For example, the word `"developer"` would be indexed by the following trigrams: `["dev", "eve", "vel", "elo", "lop", "ope", "per"]`. + +This makes text indexes particularly suitable for substring (`CONTAINS`) and suffix (`ENDS WITH`) searches, as well as prefix searches (`STARTS WITH`). +For example, searches like `CONTAINS "vel"` or `ENDS WITH "per"` can be efficiently performed by directly looking up the relevant trigrams in the index. +By comparison, range indexes, which indexes `STRING` values lexicographically (see xref:indexes/search-performance-indexes/using-indexes.adoc#range-index-backed-order-by[Range index-backed `ORDER BY`] for more information) and are therefore more suited for prefix searches, would need to scan through all indexed values to check if `"vel"` existed anywhere within the text. +For more information, see xref:indexes/search-performance-indexes/using-indexes.adoc#text-indexes[The impact of indexes on query performance -> Text indexes]. + [discrete] [[text-indexes-examples]] ==== Examples diff --git a/modules/ROOT/pages/indexes/search-performance-indexes/using-indexes.adoc b/modules/ROOT/pages/indexes/search-performance-indexes/using-indexes.adoc index 98f7ffb45..01fb04891 100644 --- a/modules/ROOT/pages/indexes/search-performance-indexes/using-indexes.adoc +++ b/modules/ROOT/pages/indexes/search-performance-indexes/using-indexes.adoc @@ -232,7 +232,7 @@ Total database accesses: 7, total allocated memory: 312 This is because range indexes store `STRING` values alphabetically. This means that, while they are very efficient for retrieving exact matches of a `STRING`, or for prefix matching, they are less efficient for suffix and contains searches, where they have to scan all relevant properties to filter any matches. -Text indexes do not store `STRING` properties alphabetically, and are instead optimized for suffix and contains searches. +Text indexes do not store `STRING` properties alphabetically, and are instead optimized for suffix and contains searches (for more information, see xref:indexes/search-performance-indexes/managing-indexes.adoc#text-indexes-trigram-indexes[Create a text index -> Trigram indexing]). That said, if no range index had been present on the name property, the previous query would still have been able to utilize the text index. It would have done so less efficiently than a range index, but it still would have been useful. From b3f67cee3a53de262f12aac7a0e2a368ca9d67ec Mon Sep 17 00:00:00 2001 From: Wilco <162103508+WilcoNeo@users.noreply.github.com> Date: Fri, 10 Jan 2025 13:35:26 +0100 Subject: [PATCH 61/77] Document lower bound restriction for shortestPath() and allShortestPath() functions (#1146) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Document that the shortestPath() and allShortestPath() functions can only have a lower bound of 0 or 1 for its variable length pattern. This is not allowed: ` MATCH p=shortestPath((a:A)-[:R*2..]->(b:B)) RETURN 1` A lower bound can be specified using a filter, but might lead to executing a possibly very slow fallback plan. ` MATCH p=shortestPath((a:A)-[:R*]->(b:B)) WHERE length(p)>2 RETURN 1` The possibly very slow fallback plan is this part: ``` | | +Top | 3 | anon_1 ASC LIMIT 1 | 1 | In Pipeline 6 | | | | +----+-------------------------------------------------------+----------------+---------------------+ | | +Projection | 4 | length(p) AS anon_1 | 1 | | | | | +----+-------------------------------------------------------+----------------+ | | | +Filter | 5 | length(p) > $autoint_0 | 1 | | | | | +----+-------------------------------------------------------+----------------+ | | | +Projection | 6 | (a)-[anon_0*]->(b) AS p | 4 | | | | | +----+-------------------------------------------------------+----------------+ | | | +VarLengthExpand(Into) | 7 | (a)-[anon_0:R*]->(b) | 4 | | | | | +----+-------------------------------------------------------+----------------+ | | | +Argument | 8 | a, b | 100 | Fused in Pipeline 5 | | | +----+-------------------------------------------------------+----------------+---------------------+ ``` Within this query plan: ``` +--------------------------+----+-------------------------------------------------------+----------------+---------------------+ | Operator | Id | Details | Estimated Rows | Pipeline | +--------------------------+----+-------------------------------------------------------+----------------+---------------------+ | +ProduceResults | 0 | `1` | 30 | | | | +----+-------------------------------------------------------+----------------+ | | +Projection | 1 | $autoint_1 AS `1` | 30 | | | | +----+-------------------------------------------------------+----------------+ | | +AntiConditionalApply | 2 | | 30 | Fused in Pipeline 7 | | |\ +----+-------------------------------------------------------+----------------+---------------------+ | | +Top | 3 | anon_1 ASC LIMIT 1 | 1 | In Pipeline 6 | | | | +----+-------------------------------------------------------+----------------+---------------------+ | | +Projection | 4 | length(p) AS anon_1 | 1 | | | | | +----+-------------------------------------------------------+----------------+ | | | +Filter | 5 | length(p) > $autoint_0 | 1 | | | | | +----+-------------------------------------------------------+----------------+ | | | +Projection | 6 | (a)-[anon_0*]->(b) AS p | 4 | | | | | +----+-------------------------------------------------------+----------------+ | | | +VarLengthExpand(Into) | 7 | (a)-[anon_0:R*]->(b) | 4 | | | | | +----+-------------------------------------------------------+----------------+ | | | +Argument | 8 | a, b | 100 | Fused in Pipeline 5 | | | +----+-------------------------------------------------------+----------------+---------------------+ | +Apply | 9 | | 100 | | | |\ +----+-------------------------------------------------------+----------------+---------------------+ | | +Optional | 10 | a, b | 100 | In Pipeline 4 | | | | +----+-------------------------------------------------------+----------------+---------------------+ | | +ShortestPath | 11 | p = (a)-[anon_0:R*]->(b) WHERE length(p) > $autoint_0 | 30 | | | | | +----+-------------------------------------------------------+----------------+ | | | +Argument | 12 | a, b | 100 | Fused in Pipeline 3 | | | +----+-------------------------------------------------------+----------------+---------------------+ | +CartesianProduct | 13 | | 100 | In Pipeline 2 | | |\ +----+-------------------------------------------------------+----------------+---------------------+ | | +NodeByLabelScan | 14 | b:B | 10 | In Pipeline 1 | | | +----+-------------------------------------------------------+----------------+---------------------+ | +NodeByLabelScan | 15 | a:A | 10 | In Pipeline 0 | +--------------------------+----+-------------------------------------------------------+----------------+---------------------+ ``` Better is to use the keyword-based SHORTEST. `MATCH p = SHORTEST 1 (a:A)-[:R]->{2,}(b:B) RETURN 1` --------- Co-authored-by: Jens Pryce-Åklundh <112686610+JPryce-Aklundh@users.noreply.github.com> --- modules/ROOT/pages/patterns/reference.adoc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/ROOT/pages/patterns/reference.adoc b/modules/ROOT/pages/patterns/reference.adoc index 977a019a6..06b5412c0 100644 --- a/modules/ROOT/pages/patterns/reference.adoc +++ b/modules/ROOT/pages/patterns/reference.adoc @@ -1372,6 +1372,7 @@ They are similar to `SHORTEST 1` and `ALL SHORTEST`, but with several difference * The path pattern is passed as an argument to the functions. * The path pattern is limited to a single relationship pattern. * To return results where the first and last node in the path are the same requires a change to the configuration setting link:{neo4j-docs-base-uri}/operations-manual/{page-version}/configuration/configuration-settings/#config_dbms.cypher.forbid_shortestpath_common_nodes[`dbms.cypher.forbid_shortestpath_common_nodes`]. +* The minimum path length, also called the lower bound of the variable length relationship pattern, should be 0 or 1. Both functions will continue to be available, but they are not xref:appendix/gql-conformance/index.adoc[GQL conformant]. @@ -1414,7 +1415,7 @@ shortestPath((:A)-->+(:B)) [[shortest-functions-rules-path-pattern-length]] ==== Path pattern length -There must be exactly one relationship pattern in the path pattern. +There must be exactly one relationship pattern in the path pattern, and the lower bound should be 0 or 1. .Allowed [source] @@ -1427,6 +1428,8 @@ shortestPath((a)-[:R*1..5]-(b)) ---- shortestPath((a)-[:R*1..5]-(b)-->(:X)) +shortestPath((a)-[:R*2..5]-(b)) + shortestPath((:A)) allShortestPaths((a:A)-[:S*]->(:B), (a)-[:R*1..3]->(:C)) From f86613acf3b58271bca7425a210e80287ab66719 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Fri, 10 Jan 2025 15:57:18 +0100 Subject: [PATCH 62/77] Hyphenation (#1154) --- modules/ROOT/pages/clauses/where.adoc | 2 +- modules/ROOT/pages/patterns/fixed-length-patterns.adoc | 6 +++--- modules/ROOT/pages/patterns/reference.adoc | 6 +++--- modules/ROOT/pages/patterns/variable-length-patterns.adoc | 2 +- modules/ROOT/pages/planning-and-tuning/query-tuning.adoc | 2 +- modules/ROOT/pages/queries/basic.adoc | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/modules/ROOT/pages/clauses/where.adoc b/modules/ROOT/pages/clauses/where.adoc index 977105dd6..e7b30e0ac 100644 --- a/modules/ROOT/pages/clauses/where.adoc +++ b/modules/ROOT/pages/clauses/where.adoc @@ -793,7 +793,7 @@ RETURN r.since |Rows: 1 |=== -However, it cannot be used inside of variable length relationships, as this would lead to an error. +However, it cannot be used inside of variable-length relationships, as this would lead to an error. For example: .Query diff --git a/modules/ROOT/pages/patterns/fixed-length-patterns.adoc b/modules/ROOT/pages/patterns/fixed-length-patterns.adoc index 96e66637c..bd1ac5799 100644 --- a/modules/ROOT/pages/patterns/fixed-length-patterns.adoc +++ b/modules/ROOT/pages/patterns/fixed-length-patterns.adoc @@ -1,7 +1,7 @@ :description: Information about node, relationship, and path patterns. -= Fixed length patterns += Fixed-length patterns -The most basic form of graph pattern matching in Cypher involves the matching of fixed length patterns. +The most basic form of graph pattern matching in Cypher involves the matching of fixed-length patterns. This includes node patterns, relationship patterns, and path patterns. [[node-patterns]] @@ -119,7 +119,7 @@ See the xref:patterns/reference.adoc#relationship-patterns[relationship patterns == Path patterns Any valid path starts and ends with a node, with relationships between each node (if there is more than one node). -Fixed length path patterns have the same restrictions, and for all valid path patterns the following are true: +Fixed-length path patterns have the same restrictions, and for all valid path patterns the following are true: * They have at least one node pattern. * They begin and end with a node pattern. diff --git a/modules/ROOT/pages/patterns/reference.adoc b/modules/ROOT/pages/patterns/reference.adoc index 06b5412c0..ac4754169 100644 --- a/modules/ROOT/pages/patterns/reference.adoc +++ b/modules/ROOT/pages/patterns/reference.adoc @@ -717,7 +717,7 @@ MATCH ((x:A)-[:R]->(z:B WHERE z.h > 2)){1,5} RETURN [n in x | n.h] AS x_h, [n in z | n.h] AS z_h ---- -Compared to the fixed length quantifier `\{2}`, this also matches paths of length one and three, but no matches exist for length greater than three: +Compared to the fixed-length quantifier `\{2}`, this also matches paths of length one and three, but no matches exist for length greater than three: [options="header",cols="2* Syntax and semantics -> Variable length relationships]. +For more information, see xref::patterns/reference.adoc#variable-length-relationships[Patterns -> Syntax and semantics -> Variable-length relationships]. The xref:patterns/shortest-paths.adoc[`SHORTEST`] keyword can be used to find a variation of the shortest paths between two nodes. In this example, `ALL SHORTEST` paths between the two nodes `Keanu Reeves` and `Tom Cruise` are found. From 933fd75c51da07756f96461f324b8173ed2fc2e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Mon, 13 Jan 2025 09:58:14 +0100 Subject: [PATCH 63/77] Change page-version attribute in external links to current (#1155) With the release of Cypher 25, the `page-version` attribute in Cypher and server doc sets will differ. It will be replaced with `current`. --- modules/ROOT/pages/administration/index.adoc | 10 ++-- .../gql-conformance/additional-cypher.adoc | 10 ++-- .../gql-conformance/supported-mandatory.adoc | 2 +- .../unsupported-mandatory.adoc | 2 +- .../tutorials/advanced-query-tuning.adoc | 6 +- .../tutorials/basic-query-tuning.adoc | 4 +- .../tutorials/shortestpath-planning.adoc | 2 +- modules/ROOT/pages/clauses/call.adoc | 12 ++-- modules/ROOT/pages/clauses/delete.adoc | 4 +- modules/ROOT/pages/clauses/index.adoc | 6 +- .../ROOT/pages/clauses/listing-functions.adoc | 10 ++-- .../pages/clauses/listing-procedures.adoc | 16 ++--- .../ROOT/pages/clauses/listing-settings.adoc | 6 +- modules/ROOT/pages/clauses/load-csv.adoc | 16 ++--- .../pages/clauses/transaction-clauses.adoc | 8 +-- modules/ROOT/pages/clauses/use.adoc | 2 +- .../constraints/managing-constraints.adoc | 6 +- modules/ROOT/pages/constraints/syntax.adoc | 8 +-- ...ions-additions-removals-compatibility.adoc | 54 ++++++++--------- modules/ROOT/pages/functions/graph.adoc | 8 +-- modules/ROOT/pages/functions/index.adoc | 4 +- modules/ROOT/pages/functions/scalar.adoc | 2 +- .../ROOT/pages/functions/user-defined.adoc | 6 +- modules/ROOT/pages/genai-integrations.adoc | 4 +- .../managing-indexes.adoc | 6 +- .../using-indexes.adoc | 2 +- .../semantic-indexes/full-text-indexes.adoc | 12 ++-- .../semantic-indexes/vector-indexes.adoc | 32 +++++----- modules/ROOT/pages/indexes/syntax.adoc | 8 +-- .../ROOT/pages/introduction/cypher-aura.adoc | 4 +- .../ROOT/pages/introduction/cypher-neo4j.adoc | 20 +++---- .../pages/introduction/cypher-overview.adoc | 2 +- modules/ROOT/pages/introduction/index.adoc | 4 +- modules/ROOT/pages/patterns/reference.adoc | 2 +- .../planning-and-tuning/execution-plans.adoc | 2 +- .../operators/operators-detail.adoc | 8 +-- .../planning-and-tuning/query-tuning.adoc | 6 +- .../runtimes/reference.adoc | 60 +++++++++---------- modules/ROOT/pages/query-caches/index.adoc | 8 +-- .../query-caches/unified-query-caches.adoc | 4 +- .../subqueries-in-transactions.adoc | 4 +- modules/ROOT/pages/syntax/naming.adoc | 2 +- modules/ROOT/pages/syntax/parameters.adoc | 4 +- modules/ROOT/pages/values-and-types/maps.adoc | 2 +- .../ROOT/pages/values-and-types/temporal.adoc | 2 +- 45 files changed, 201 insertions(+), 201 deletions(-) diff --git a/modules/ROOT/pages/administration/index.adoc b/modules/ROOT/pages/administration/index.adoc index cac8d8e33..fa9d6119b 100644 --- a/modules/ROOT/pages/administration/index.adoc +++ b/modules/ROOT/pages/administration/index.adoc @@ -1,6 +1,6 @@ = Administration -The pages previously in this chapter have been moved to the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/[Operations Manual]. +The pages previously in this chapter have been moved to the link:{neo4j-docs-base-uri}/operations-manual/current/[Operations Manual]. More specific information about the content relocation is listed in the table: @@ -9,13 +9,13 @@ More specific information about the content relocation is listed in the table: | Content | New location in Operations Manual -| Database management | link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/[Database administration] +| Database management | link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/[Database administration] -| Alias management | link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/aliases/manage-aliases-standard-databases/[Managing aliases] +| Alias management | link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/aliases/manage-aliases-standard-databases/[Managing aliases] -| Server management | link:{neo4j-docs-base-uri}/operations-manual/{page-version}/clustering/[Managing servers in a cluster] +| Server management | link:{neo4j-docs-base-uri}/operations-manual/current/clustering/[Managing servers in a cluster] -| Access control | link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/[Authentication and authorization] +| Access control | link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/[Authentication and authorization] |=== diff --git a/modules/ROOT/pages/appendix/gql-conformance/additional-cypher.adoc b/modules/ROOT/pages/appendix/gql-conformance/additional-cypher.adoc index 6e7f49ec1..ae7fe27a0 100644 --- a/modules/ROOT/pages/appendix/gql-conformance/additional-cypher.adoc +++ b/modules/ROOT/pages/appendix/gql-conformance/additional-cypher.adoc @@ -656,23 +656,23 @@ For more information, see xref:planning-and-tuning/query-tuning.adoc[Query optio == Administration [NOTE] -The documentation for Cypher's administration commands is located in Neo4j's link:{neo4j-docs-base-uri}/operations-manual/{page-version}/[Operation Manual]. +The documentation for Cypher's administration commands is located in Neo4j's link:{neo4j-docs-base-uri}/operations-manual/current/[Operation Manual]. [options="header", cols="2a,5a"] |=== | Cypher feature | Description -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/[Database management] +| link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/[Database management] | Commands to `CREATE`, `SHOW`, `ALTER`, and `DROP` standard and composite databases. -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/aliases/manage-aliases-standard-databases/[Alias management] +| link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/aliases/manage-aliases-standard-databases/[Alias management] | Commands to `CREATE`, `SHOW`, `ALTER`, and `DROP` database aliases. -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/clustering/[Server management] +| link:{neo4j-docs-base-uri}/operations-manual/current/clustering/[Server management] | Commands to administer servers in a cluster and the databases allocated to them. -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/[Authentication and authorization] +| link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/[Authentication and authorization] | Commands to manage users, roles, and privileges. |=== \ No newline at end of file diff --git a/modules/ROOT/pages/appendix/gql-conformance/supported-mandatory.adoc b/modules/ROOT/pages/appendix/gql-conformance/supported-mandatory.adoc index 6a8299b0e..4551dd8f6 100644 --- a/modules/ROOT/pages/appendix/gql-conformance/supported-mandatory.adoc +++ b/modules/ROOT/pages/appendix/gql-conformance/supported-mandatory.adoc @@ -155,7 +155,7 @@ This is currently not available in Cypher. | | | GQL defines the `SESSION_USER` value expression, which enables accessing a user’s username within a query. -In Cypher, current user details can be seen using the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/manage-users/#access-control-current-users[`SHOW CURRENT USER` command]. +In Cypher, current user details can be seen using the link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/manage-users/#access-control-current-users[`SHOW CURRENT USER` command]. | 20.7 | diff --git a/modules/ROOT/pages/appendix/gql-conformance/unsupported-mandatory.adoc b/modules/ROOT/pages/appendix/gql-conformance/unsupported-mandatory.adoc index 98c143dcb..12f5fca56 100644 --- a/modules/ROOT/pages/appendix/gql-conformance/unsupported-mandatory.adoc +++ b/modules/ROOT/pages/appendix/gql-conformance/unsupported-mandatory.adoc @@ -28,7 +28,7 @@ Neo4j offers session management through the link:{neo4j-docs-base-uri}/create-ap | GQL defines the following transaction commands: `START TRANSACTION`, `COMMIT`, and `ROLLBACK`. Neo4j offers transaction management through the link:{neo4j-docs-base-uri}/create-applications[driver] transaction API. -Cypher Shell also offers specific link:{neo4j-docs-base-uri}/operations-manual/{page-version}/tools/cypher-shell/#cypher-shell-commands[commands] to manage transactions. +Cypher Shell also offers specific link:{neo4j-docs-base-uri}/operations-manual/current/tools/cypher-shell/#cypher-shell-commands[commands] to manage transactions. | 11.1 | Graph expressions diff --git a/modules/ROOT/pages/appendix/tutorials/advanced-query-tuning.adoc b/modules/ROOT/pages/appendix/tutorials/advanced-query-tuning.adoc index 9db47e053..5d5816465 100644 --- a/modules/ROOT/pages/appendix/tutorials/advanced-query-tuning.adoc +++ b/modules/ROOT/pages/appendix/tutorials/advanced-query-tuning.adoc @@ -16,7 +16,7 @@ Let's explain how to use these features with a more advanced query tuning exampl [NOTE] ==== If you are upgrading an existing store, it may be necessary to drop and re-create existing indexes. -For information on native index support and upgrade considerations regarding indexes, see link:{neo4j-docs-base-uri}/operations-manual/{page-version}/performance/index-configuration[Operations Manual -> Performance -> Index configuration]. +For information on native index support and upgrade considerations regarding indexes, see link:{neo4j-docs-base-uri}/operations-manual/current/performance/index-configuration[Operations Manual -> Performance -> Index configuration]. ==== @@ -540,8 +540,8 @@ It assumes that your current work directory is the __ directory of t [NOTE] ==== -* For the default directory of other installations see, link:{neo4j-docs-base-uri}/operations-manual/{page-version}/configuration/file-locations[Operations Manual -> File locations]. -* The import location can be configured with link:{neo4j-docs-base-uri}/operations-manual/{page-version}/configuration/configuration-settings#config_server.directories.import[Operations Manual -> `server.directories.import`]. +* For the default directory of other installations see, link:{neo4j-docs-base-uri}/operations-manual/current/configuration/file-locations[Operations Manual -> File locations]. +* The import location can be configured with link:{neo4j-docs-base-uri}/operations-manual/current/configuration/configuration-settings#config_server.directories.import[Operations Manual -> `server.directories.import`]. ==== == Importing the data diff --git a/modules/ROOT/pages/appendix/tutorials/basic-query-tuning.adoc b/modules/ROOT/pages/appendix/tutorials/basic-query-tuning.adoc index 170ac0111..faa961fe0 100644 --- a/modules/ROOT/pages/appendix/tutorials/basic-query-tuning.adoc +++ b/modules/ROOT/pages/appendix/tutorials/basic-query-tuning.adoc @@ -525,8 +525,8 @@ It assumes that your current work directory is the __ directory of t [NOTE] ==== -* For the default directory of other installations see, link:{neo4j-docs-base-uri}/operations-manual/{page-version}/configuration/file-locations[Operations Manual -> File locations]. -* The import location can be configured with link:{neo4j-docs-base-uri}/operations-manual/{page-version}/configuration/configuration-settings#config_server.directories.import[Operations Manual -> `server.directories.import`]. +* For the default directory of other installations see, link:{neo4j-docs-base-uri}/operations-manual/current/configuration/file-locations[Operations Manual -> File locations]. +* The import location can be configured with link:{neo4j-docs-base-uri}/operations-manual/current/configuration/configuration-settings#config_server.directories.import[Operations Manual -> `server.directories.import`]. ==== == Importing the data diff --git a/modules/ROOT/pages/appendix/tutorials/shortestpath-planning.adoc b/modules/ROOT/pages/appendix/tutorials/shortestpath-planning.adoc index 96887c531..40df8bc60 100644 --- a/modules/ROOT/pages/appendix/tutorials/shortestpath-planning.adoc +++ b/modules/ROOT/pages/appendix/tutorials/shortestpath-planning.adoc @@ -20,7 +20,7 @@ When the exhaustive search is planned, it is still only executed when the fast a The fast algorithm is always executed first, since it is possible that it can find a valid path even though that could not be guaranteed at planning time. Please note that falling back to the exhaustive search may prove to be a very time consuming strategy in some cases; such as when there is no shortest path between two nodes. -Therefore, in these cases, it is recommended to set `cypher.forbid_exhaustive_shortestpath` to `true`, as explained in link:{neo4j-docs-base-uri}/operations-manual/{page-version}/configuration/configuration-settings#config_dbms.cypher.forbid_exhaustive_shortestpath[Operations Manual -> Configuration settings]. +Therefore, in these cases, it is recommended to set `cypher.forbid_exhaustive_shortestpath` to `true`, as explained in link:{neo4j-docs-base-uri}/operations-manual/current/configuration/configuration-settings#config_dbms.cypher.forbid_exhaustive_shortestpath[Operations Manual -> Configuration settings]. == Shortest path -- fast algorithm diff --git a/modules/ROOT/pages/clauses/call.adoc b/modules/ROOT/pages/clauses/call.adoc index 30b0ed1b9..3001023a0 100644 --- a/modules/ROOT/pages/clauses/call.adoc +++ b/modules/ROOT/pages/clauses/call.adoc @@ -12,9 +12,9 @@ For information about how to list procedures, see xref:clauses/listing-procedure [NOTE] Neo4j comes with a number of built-in procedures. -For a list of these, see link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures[Operations Manual -> Procedures]. +For a list of these, see link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures[Operations Manual -> Procedures]. Users can also develop custom procedures and deploy to the database. -See link:{neo4j-docs-base-uri}/java-reference/{page-version}/extending-neo4j/procedures#extending-neo4j-procedures[Java Reference -> User-defined procedures] for details. +See link:{neo4j-docs-base-uri}/java-reference/current/extending-neo4j/procedures#extending-neo4j-procedures[Java Reference -> User-defined procedures] for details. [[example-graph]] == Example graph @@ -42,7 +42,7 @@ CREATE (andy:Developer {name: 'Andy', born: 1991}), .`CALL` a procedure without arguments ==== -This example calls the built-in procedure link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_labels[`db.labels()`], which lists all labels used in the database. +This example calls the built-in procedure link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_db_labels[`db.labels()`], which lists all labels used in the database. .Query [source, cypher] @@ -72,7 +72,7 @@ Omission of parentheses is available only in a so-called standalone procedure ca ==== -This example calls the procedure link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_dbms_checkconfigvalue[`dbms.checkConfigValue()`], which checks the validity of a configuration setting value, using literal arguments. +This example calls the procedure link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_dbms_checkconfigvalue[`dbms.checkConfigValue()`], which checks the validity of a configuration setting value, using literal arguments. .Query [source, cypher] @@ -204,7 +204,7 @@ RETURN count(*) AS results ==== `YIELD` can be used to filter for specific results. -This requires knowing the names of the arguments within a procedure's signature, which can either be found in the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/[Operations Manual -> Procedures] or returned by a `SHOW PROCEDURES` query. +This requires knowing the names of the arguments within a procedure's signature, which can either be found in the link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/[Operations Manual -> Procedures] or returned by a `SHOW PROCEDURES` query. .Find the argument names of `db.propertyKeys` [source, cypher] @@ -269,7 +269,7 @@ Similar to xref:clauses/optional-match.adoc[`OPTIONAL MATCH`] any empty rows pro .Difference between using `CALL` and `OPTIONAL CALL` ==== -This query uses the link:{neo4j-docs-base-uri}/apoc/{page-version}/overview/apoc.neighbors/apoc.neighbors.tohop[`apoc.neighbors.tohop()`] procedure (part of Neo4j's link:{neo4j-docs-base-uri}/apoc/{page-version}/[APOC Core library]), which returns all nodes connected by the given relationship type within the specified distance (1 hop, in this case) and direction. +This query uses the link:{neo4j-docs-base-uri}/apoc/current/overview/apoc.neighbors/apoc.neighbors.tohop[`apoc.neighbors.tohop()`] procedure (part of Neo4j's link:{neo4j-docs-base-uri}/apoc/current/[APOC Core library]), which returns all nodes connected by the given relationship type within the specified distance (1 hop, in this case) and direction. .Regular procedure `CALL` [source, cypher] diff --git a/modules/ROOT/pages/clauses/delete.adoc b/modules/ROOT/pages/clauses/delete.adoc index 2d87d05f9..b90a2f007 100644 --- a/modules/ROOT/pages/clauses/delete.adoc +++ b/modules/ROOT/pages/clauses/delete.adoc @@ -13,7 +13,7 @@ This can be done by either explicitly deleting specific relationships, or by usi [NOTE] While the `DELETE` clause renders the deleted objects no longer accessible, the space occupied by the deleted nodes and relationships remain on the disk and is reserved for future transactions creating data. -For information about how to clear and reuse the space occupied by deleted objects, see link:{neo4j-docs-base-uri}/operations-manual/{page-version}/performance/space-reuse/[Operations Manual -> Space reuse]. +For information about how to clear and reuse the space occupied by deleted objects, see link:{neo4j-docs-base-uri}/operations-manual/current/performance/space-reuse/[Operations Manual -> Space reuse]. == Example graph @@ -120,7 +120,7 @@ Deleted 1 node, deleted 1 relationship [NOTE] ==== The `DETACH DELETE` clause may not be permitted to users with restricted security privileges. -For more information, see link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/access-control#detach-delete-restricted-user[Operations Manual -> Fine-grained access control]. +For more information, see link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/access-control#detach-delete-restricted-user[Operations Manual -> Fine-grained access control]. ==== diff --git a/modules/ROOT/pages/clauses/index.adoc b/modules/ROOT/pages/clauses/index.adoc index 77165c7d0..89e88c90b 100644 --- a/modules/ROOT/pages/clauses/index.adoc +++ b/modules/ROOT/pages/clauses/index.adoc @@ -279,6 +279,6 @@ m| xref::constraints/syntax.adoc[CREATE \| SHOW \| DROP CONSTRAINT] Cypher includes commands to manage databases, aliases, servers, and role-based access control. To learn more about each of these, see: -* link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration[Operations Manual -> Database administration] -* link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/[Operations Manual -> Authentication and authorization] -* link:{neo4j-docs-base-uri}/operations-manual/{page-version}/clustering/[Operations Manual -> Clustering] +* link:{neo4j-docs-base-uri}/operations-manual/current/database-administration[Operations Manual -> Database administration] +* link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/[Operations Manual -> Authentication and authorization] +* link:{neo4j-docs-base-uri}/operations-manual/current/clustering/[Operations Manual -> Clustering] diff --git a/modules/ROOT/pages/clauses/listing-functions.adoc b/modules/ROOT/pages/clauses/listing-functions.adoc index 325b72685..59ce2a0e9 100644 --- a/modules/ROOT/pages/clauses/listing-functions.adoc +++ b/modules/ROOT/pages/clauses/listing-functions.adoc @@ -55,13 +55,13 @@ m| BOOLEAN m| rolesExecution a| List of roles permitted to execute this function. -Is `null` without the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/dbms-administration#access-control-dbms-administration-role-management[`SHOW ROLE`] privilege. +Is `null` without the link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/dbms-administration#access-control-dbms-administration-role-management[`SHOW ROLE`] privilege. m| LIST m| rolesBoostedExecution a| List of roles permitted to use boosted mode when executing this function. -Is `null` without the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/dbms-administration#access-control-dbms-administration-role-management[`SHOW ROLE`] privilege. +Is `null` without the link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/dbms-administration#access-control-dbms-administration-role-management[`SHOW ROLE`] privilege. m| LIST m| isDeprecated @@ -81,7 +81,7 @@ m| STRING [NOTE] ==== -More details about the syntax descriptions can be found link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/syntax/#administration-syntax-reading[here]. +More details about the syntax descriptions can be found link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/syntax/#administration-syntax-reading[here]. ==== List functions, either all or only built-in or user-defined:: @@ -124,7 +124,7 @@ SHOW [ALL|BUILT IN|USER DEFINED] FUNCTION[S] EXECUTABLE BY username [RETURN field[, ...] [ORDER BY field[, ...]] [SKIP n] [LIMIT n]] ---- -Required privilege link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/dbms-administration#access-control-dbms-administration-user-management[`SHOW USER`]. +Required privilege link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/dbms-administration#access-control-dbms-administration-user-management[`SHOW USER`]. This command cannot be used for LDAP users. [NOTE] @@ -363,7 +363,7 @@ SHOW FUNCTIONS EXECUTABLE BY CURRENT USER YIELD * 6+d|Rows: 10 |=== -Notice that the two `roles` columns are empty due to missing the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/dbms-administration#access-control-dbms-administration-role-management[`SHOW ROLE`] privilege. +Notice that the two `roles` columns are empty due to missing the link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/dbms-administration#access-control-dbms-administration-role-management[`SHOW ROLE`] privilege. Also note that the following columns are not present in the table: * `signature` diff --git a/modules/ROOT/pages/clauses/listing-procedures.adoc b/modules/ROOT/pages/clauses/listing-procedures.adoc index 686113050..60f0cfd8c 100644 --- a/modules/ROOT/pages/clauses/listing-procedures.adoc +++ b/modules/ROOT/pages/clauses/listing-procedures.adoc @@ -53,13 +53,13 @@ m| BOOLEAN m| rolesExecution a| List of roles permitted to execute this procedure. -Is `null` without the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/dbms-administration#access-control-dbms-administration-role-management[`SHOW ROLE`] privilege. +Is `null` without the link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/dbms-administration#access-control-dbms-administration-role-management[`SHOW ROLE`] privilege. m| LIST m| rolesBoostedExecution a| List of roles permitted to use boosted mode when executing this procedure. -Is `null` without the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/dbms-administration#access-control-dbms-administration-role-management[`SHOW ROLE`] privilege. +Is `null` without the link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/dbms-administration#access-control-dbms-administration-role-management[`SHOW ROLE`] privilege. m| LIST m| isDeprecated @@ -84,7 +84,7 @@ The deprecation information for procedures is returned both in the `isDeprecated [NOTE] ==== -More details about the syntax descriptions can be found link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/syntax/#administration-syntax-reading[here]. +More details about the syntax descriptions can be found link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/syntax/#administration-syntax-reading[here]. ==== List all procedures:: @@ -127,7 +127,7 @@ SHOW PROCEDURE[S] EXECUTABLE BY username [RETURN field[, ...] [ORDER BY field[, ...]] [SKIP n] [LIMIT n]] ---- -Requires the privilege link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/dbms-administration#access-control-dbms-administration-user-management[`SHOW USER`]. +Requires the privilege link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/dbms-administration#access-control-dbms-administration-user-management[`SHOW USER`]. This command cannot be used for LDAP users. [NOTE] @@ -246,7 +246,7 @@ SHOW PROCEDURES |=== The above table only displays the first 15 results of the query. -For a full list of all built-in procedures in Neo4j, visit the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures#/#_list_of_procedures[Operations Manual -> List of procedures]. +For a full list of all built-in procedures in Neo4j, visit the link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures#/#_list_of_procedures[Operations Manual -> List of procedures]. == Listing procedures with filtering on output columns @@ -285,7 +285,7 @@ WHERE admin |=== The above table only displays the first 15 results of the query. -For a full list of all procedures which require `admin` privileges in Neo4j, visit the {neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures#/#_list_of_procedures[Operations Manual -> List of procedures]. +For a full list of all procedures which require `admin` privileges in Neo4j, visit the {neo4j-docs-base-uri}/operations-manual/current/reference/procedures#/#_list_of_procedures[Operations Manual -> List of procedures]. == Listing procedures with other filtering @@ -401,7 +401,7 @@ SHOW PROCEDURES EXECUTABLE BY CURRENT USER YIELD * |=== The above table only displays the first 15 results of the query. -Note that the two `roles` columns are empty due to missing the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/dbms-administration#access-control-dbms-administration-role-management[`SHOW ROLE`] privilege. +Note that the two `roles` columns are empty due to missing the link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/dbms-administration#access-control-dbms-administration-role-management[`SHOW ROLE`] privilege. Also note that the following columns are not present in the table: * `mode` @@ -416,7 +416,7 @@ Also note that the following columns are not present in the table: The second option for using the `EXECUTABLE` clause is to filter the list to only contain procedures executable by a specific user. The below example shows the procedures available to the user `jake`, who has been granted the `EXECUTE PROCEDURE dbms.*` privilege by the `admin` of the database. -(More information about `DBMS EXECUTE` privilege administration can be found in the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/dbms-administration/#access-control-dbms-administration-execute[Operations Manual -> The `DBMS EXECUTE` privileges]). +(More information about `DBMS EXECUTE` privilege administration can be found in the link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/dbms-administration/#access-control-dbms-administration-execute[Operations Manual -> The `DBMS EXECUTE` privileges]). .Query [source, cypher, role=test-result-skip] diff --git a/modules/ROOT/pages/clauses/listing-settings.adoc b/modules/ROOT/pages/clauses/listing-settings.adoc index 95bea97a7..3f3b719a4 100644 --- a/modules/ROOT/pages/clauses/listing-settings.adoc +++ b/modules/ROOT/pages/clauses/listing-settings.adoc @@ -37,7 +37,7 @@ m| STRING m| isDynamic a| Whether the value of the setting can be updated dynamically, without restarting the server. -For dynamically updating a setting value, see link:{neo4j-docs-base-uri}/operations-manual/{page-version}/configuration/dynamic-settings/[Update dynamic settings]. +For dynamically updating a setting value, see link:{neo4j-docs-base-uri}/operations-manual/current/configuration/dynamic-settings/[Update dynamic settings]. label:default-output[] m| BOOLEAN @@ -73,7 +73,7 @@ m| BOOLEAN [NOTE] ==== -More details about the syntax descriptions can be found link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/syntax/#administration-syntax-reading[here]. +More details about the syntax descriptions can be found link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/syntax/#administration-syntax-reading[here]. ==== List settings:: @@ -174,7 +174,7 @@ SHOW SETTINGS |=== The above table only displays the first 10 results of the query. -For a full list of all available settings in Neo4j, refer to link:{neo4j-docs-base-uri}/operations-manual/{page-version}/configuration/configuration-settings[Configuration settings]. +For a full list of all available settings in Neo4j, refer to link:{neo4j-docs-base-uri}/operations-manual/current/configuration/configuration-settings[Configuration settings]. == Listing settings with filtering on output columns diff --git a/modules/ROOT/pages/clauses/load-csv.adoc b/modules/ROOT/pages/clauses/load-csv.adoc index 740ae67b7..084e738ff 100644 --- a/modules/ROOT/pages/clauses/load-csv.adoc +++ b/modules/ROOT/pages/clauses/load-csv.adoc @@ -22,7 +22,7 @@ Local paths are resolved relative to the Neo4j installation folder. [NOTE] ==== -Loading CSV files requires link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/load-privileges/[load privileges]. +Loading CSV files requires link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/load-privileges/[load privileges]. ==== == Import CSV data into Neo4j @@ -76,10 +76,10 @@ When using `+file:///+` URLs, spaces and other non-alphanumeric characters must ==== Configuration settings for file URLs -link:{neo4j-docs-base-uri}/operations-manual/{page-version}/configuration/configuration-settings#config_dbms.security.allow_csv_import_from_file_urls[dbms.security.allow_csv_import_from_file_urls]:: +link:{neo4j-docs-base-uri}/operations-manual/current/configuration/configuration-settings#config_dbms.security.allow_csv_import_from_file_urls[dbms.security.allow_csv_import_from_file_urls]:: This setting determines whether `+file:///+` URLs are allowed. -link:{neo4j-docs-base-uri}/operations-manual/{page-version}/configuration/configuration-settings#config_server.directories.import[server.directories.import]:: +link:{neo4j-docs-base-uri}/operations-manual/current/configuration/configuration-settings#config_server.directories.import[server.directories.import]:: This setting sets the root directory relative to which `+file:///+` URLs are parsed. @@ -93,9 +93,9 @@ It also follows redirects, except those changing the protocol (for security reas [IMPORTANT] ==== It is strongly recommended to permit resource loading only over secure protocols such as HTTPS instead of insecure protocols like HTTP. -This can be done by limiting the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/load-privileges/#access-control-load-cidr/[load privileges] to only trusted sources that use secure protocols. +This can be done by limiting the link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/load-privileges/#access-control-load-cidr/[load privileges] to only trusted sources that use secure protocols. If allowing an insecure protocol is absolutely unavoidable, Neo4j takes measures internally to enhance the security of these requests within their limitations. -However, this means that insecure URLs on virtual hosts will not function unless you add the JVM argument `-Dsun.net.http.allowRestrictedHeaders=true` to the configuration setting link:{neo4j-docs-base-uri}/operations-manual/{page-version}/configuration/configuration-settings/#config_server.jvm.additional/[`server.jvm.additional`]. +However, this means that insecure URLs on virtual hosts will not function unless you add the JVM argument `-Dsun.net.http.allowRestrictedHeaders=true` to the configuration setting link:{neo4j-docs-base-uri}/operations-manual/current/configuration/configuration-settings/#config_server.jvm.additional/[`server.jvm.additional`]. ==== @@ -1081,8 +1081,8 @@ You may discover if this is the case by link:https://neo4j.com/docs/cypher-manua To help handle larger volumes of transactions, there are a few memory configuration settings you can tweak: -* link:{neo4j-docs-base-uri}/operations-manual/{page-version}/configuration/configuration-settings/#config_server.memory.heap.initial_size[`server.memory.heap.initial_size`] and link:{neo4j-docs-base-uri}/operations-manual/{page-version}/configuration/configuration-settings/#config_server.memory.heap.max_size[`server.memory.heap.max_size`]: set to at least 4G. -* link:{neo4j-docs-base-uri}/operations-manual/{page-version}/configuration/configuration-settings/#config_server.memory.pagecache.size[`server.memory.pagecache.size`]: ideally, a value large enough to keep the whole database in memory. +* link:{neo4j-docs-base-uri}/operations-manual/current/configuration/configuration-settings/#config_server.memory.heap.initial_size[`server.memory.heap.initial_size`] and link:{neo4j-docs-base-uri}/operations-manual/current/configuration/configuration-settings/#config_server.memory.heap.max_size[`server.memory.heap.max_size`]: set to at least 4G. +* link:{neo4j-docs-base-uri}/operations-manual/current/configuration/configuration-settings/#config_server.memory.pagecache.size[`server.memory.pagecache.size`]: ideally, a value large enough to keep the whole database in memory. // As a rule of thumb, you can create or update one million records in a single transaction per 2 GB of heap. //// @@ -1150,7 +1150,7 @@ With increasing amounts of data, it is more efficient to create _all_ nodes firs There are a few other tools to get CSV data into Neo4j. -1. *The link:{neo4j-docs-base-uri}/operations-manual/{page-version}/tools/neo4j-admin/neo4j-admin-import/[`neo4j-admin database import`] command* is the most efficient way of importing large CSV files. +1. *The link:{neo4j-docs-base-uri}/operations-manual/current/tools/neo4j-admin/neo4j-admin-import/[`neo4j-admin database import`] command* is the most efficient way of importing large CSV files. 2. Use a link:https://neo4j.com/docs/create-applications/[*language library*] to parse CSV data and run creation Cypher queries against a Neo4j database. Created as an extension library to provide common procedures and functions to developers. This library is especially helpful for complex transformations and data manipulations. diff --git a/modules/ROOT/pages/clauses/transaction-clauses.adoc b/modules/ROOT/pages/clauses/transaction-clauses.adoc index 333ce8b62..bd2a93ccc 100644 --- a/modules/ROOT/pages/clauses/transaction-clauses.adoc +++ b/modules/ROOT/pages/clauses/transaction-clauses.adoc @@ -209,7 +209,7 @@ The `SHOW TRANSACTIONS` command can be combined with multiple `SHOW TRANSACTIONS [NOTE] ==== -More details about the syntax descriptions can be found link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/syntax/#administration-syntax-reading[here]. +More details about the syntax descriptions can be found link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/syntax/#administration-syntax-reading[here]. ==== List transactions on the current server:: @@ -230,7 +230,7 @@ Transaction IDs must be supplied as one or more comma-separated quoted `STRING` When using the `RETURN` clause, the `YIELD` clause is mandatory and must not be omitted. ==== -A user with the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/database-administration/#access-control-database-administration-transaction[`SHOW TRANSACTION`] privilege can view the currently executing transactions in accordance with the privilege grants. +A user with the link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/database-administration/#access-control-database-administration-transaction[`SHOW TRANSACTION`] privilege can view the currently executing transactions in accordance with the privilege grants. All users may view all of their own currently executing transactions. @@ -371,7 +371,7 @@ The `TERMINATE TRANSACTIONS` command can be combined with multiple `SHOW TRANSAC [NOTE] ==== -More details about the syntax descriptions can be found link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/syntax/#administration-syntax-reading[here]. +More details about the syntax descriptions can be found link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/syntax/#administration-syntax-reading[here]. ==== Terminate transactions by ID on the current server:: @@ -396,7 +396,7 @@ Transaction IDs must be supplied as one or more comma-separated quoted `STRING` When using the `WHERE` or `RETURN` clauses, the `YIELD` clause is mandatory and must not be omitted. ==== -A user with the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/database-administration/#access-control-database-administration-transaction[`TERMINATE TRANSACTION`] privilege can terminate transactions in accordance with the privilege grants. +A user with the link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/database-administration/#access-control-database-administration-transaction[`TERMINATE TRANSACTION`] privilege can terminate transactions in accordance with the privilege grants. All users may terminate their own currently executing transactions. diff --git a/modules/ROOT/pages/clauses/use.adoc b/modules/ROOT/pages/clauses/use.adoc index 7433484ce..3a75add21 100644 --- a/modules/ROOT/pages/clauses/use.adoc +++ b/modules/ROOT/pages/clauses/use.adoc @@ -24,7 +24,7 @@ Where `` refers to the name or alias of a database in the DBMS. [[query-use-syntax-composite]] === Composite database syntax -When running queries against a link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/composite-databases/concepts/[composite database], the `USE` clause can also appear as the first clause of: +When running queries against a link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/composite-databases/concepts/[composite database], the `USE` clause can also appear as the first clause of: * Union parts: + diff --git a/modules/ROOT/pages/constraints/managing-constraints.adoc b/modules/ROOT/pages/constraints/managing-constraints.adoc index c64eecaf3..2975482a9 100644 --- a/modules/ROOT/pages/constraints/managing-constraints.adoc +++ b/modules/ROOT/pages/constraints/managing-constraints.adoc @@ -22,7 +22,7 @@ If a name is not explicitly given, a unique name will be auto-generated. [NOTE] -Creating a constraint requires the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/database-administration/#access-control-database-administration-constraints[`CREATE CONSTRAINT` privilege]. +Creating a constraint requires the link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/database-administration/#access-control-database-administration-constraints[`CREATE CONSTRAINT` privilege]. [NOTE] Adding constraints is an atomic operation that can take a while -- all existing data has to be scanned before a Neo4j DBMS can use a constraint. @@ -1418,7 +1418,7 @@ One of the output columns from `SHOW CONSTRAINTS` is the name of the constraint. This can be used to drop the constraint with the xref::constraints/managing-constraints.adoc#drop-constraint[`DROP CONSTRAINT` command]. [NOTE] -Listing constraints requires the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/database-administration/#access-control-database-administration-constraints[`SHOW CONSTRAINTS` privilege]. +Listing constraints requires the link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/database-administration/#access-control-database-administration-constraints[`SHOW CONSTRAINTS` privilege]. .List all constraints with default output columns ====== @@ -1656,7 +1656,7 @@ Constraints are dropped using the `DROP CONSTRAINT` command. For the full command syntax to drop constraints, see xref:constraints/syntax.adoc#drop-constraint[Syntax -> DROP CONSTRAINT]. [NOTE] -Dropping a constraint requires the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/database-administration/#access-control-database-administration-constraints[`DROP CONSTRAINT` privilege]. +Dropping a constraint requires the link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/database-administration/#access-control-database-administration-constraints[`DROP CONSTRAINT` privilege]. [[drop-constraint-by-name]] === Drop a constraint by name diff --git a/modules/ROOT/pages/constraints/syntax.adoc b/modules/ROOT/pages/constraints/syntax.adoc index 77b63b930..fcb83e9dc 100644 --- a/modules/ROOT/pages/constraints/syntax.adoc +++ b/modules/ROOT/pages/constraints/syntax.adoc @@ -6,7 +6,7 @@ This page contains the syntax for creating, listing, and dropping the constraints available in Neo4j. -More details about the syntax can be found in the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/syntax/[Operations Manual -> Cypher syntax for administration commands]. +More details about the syntax can be found in the link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/syntax/[Operations Manual -> Cypher syntax for administration commands]. [[constraints-syntax-create]] == CREATE CONSTRAINT @@ -17,7 +17,7 @@ This name must be unique among both indexes and constraints. If a name is not explicitly given, a unique name will be auto-generated. [NOTE] -Creating a constraint requires the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/database-administration/#access-control-database-administration-constraints[`CREATE CONSTRAINT` privilege]. +Creating a constraint requires the link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/database-administration/#access-control-database-administration-constraints[`CREATE CONSTRAINT` privilege]. The `CREATE CONSTRAINT` command is optionally idempotent. This means its default behavior is to throw an error if an attempt is made to create the same constraint twice. @@ -189,7 +189,7 @@ If only specific columns are required, use `SHOW CONSTRAINTS YIELD field[, ...]` The `SHOW CONSTRAINTS` clause can also be filtered using the xref:clauses/where.adoc[`WHERE`] clause. [NOTE] -Listing constraints requires the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/database-administration/#access-control-database-administration-constraints[`SHOW CONSTRAINTS` privilege]. +Listing constraints requires the link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/database-administration/#access-control-database-administration-constraints[`SHOW CONSTRAINTS` privilege]. .Syntax to list constraints with default return columns @@ -296,7 +296,7 @@ Constraints are dropped using the `DROP` CONSTRAINT command. Dropping a constraint is done by specifying the name of the constraint. [NOTE] -Dropping a constraint requires the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/database-administration/#access-control-database-administration-constraints[`DROP CONSTRAINT` privilege]. +Dropping a constraint requires the link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/database-administration/#access-control-database-administration-constraints[`DROP CONSTRAINT` privilege]. .Syntax for dropping a constraint by name diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index 8e31d613c..309887365 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -122,7 +122,7 @@ CALL db.schema.nodeTypeProperties() YIELD propertyTypes RETURN propertyTypes; CALL db.schema.relTypeProperties() YIELD propertyTypes RETURN propertyTypes; ---- a| -The column `propertyTypes` returned by the procedures link:{neo4j-docs-base-uri}/operations-manual/{page-version}/procedures/#procedure_db_schema_nodetypeproperties[`db.schema.nodeTypeProperties()`] and link:{neo4j-docs-base-uri}/operations-manual/{page-version}/procedures/#procedure_db_schema_reltypeproperties[`db.schema.relTypeProperties()`] previously returned a list of strings representing the potential Java types for a given property. +The column `propertyTypes` returned by the procedures link:{neo4j-docs-base-uri}/operations-manual/current/procedures/#procedure_db_schema_nodetypeproperties[`db.schema.nodeTypeProperties()`] and link:{neo4j-docs-base-uri}/operations-manual/current/procedures/#procedure_db_schema_reltypeproperties[`db.schema.relTypeProperties()`] previously returned a list of strings representing the potential Java types for a given property. It now returns a list of strings representing the possible Cypher Types the given property has. For all available Cypher types, see the section on xref::values-and-types/property-structural-constructed.adoc#types-synonyms[types and their synonyms]. @@ -169,7 +169,7 @@ CREATE DATABASE db OPTIONS { seedRestoreUntil: ... } ---- | The option `seedRestoreUntil` can now be specified in the `CREATE DATABASE` `OPTIONS` map. This allows a database to be seeded up to a specific date or transaction ID. -For more information, see link:{neo4j-docs-base-uri}/operations-manual/{page-version}/clustering/databases/#cluster-seed-uri[Operations Manual -> Clustering -> Seed from URI]. +For more information, see link:{neo4j-docs-base-uri}/operations-manual/current/clustering/databases/#cluster-seed-uri[Operations Manual -> Clustering -> Seed from URI]. |=== [[cypher-deprecations-additions-removals-2025.01]] @@ -308,7 +308,7 @@ CALL db.schema.nodeTypeProperties() YIELD propertyTypes RETURN propertyTypes; CALL db.schema.relTypeProperties() YIELD propertyTypes RETURN propertyTypes; ---- a| -The column `propertyTypes` currently returned by the procedures link:{neo4j-docs-base-uri}/operations-manual/{page-version}/procedures/#procedure_db_schema_nodetypeproperties[`db.schema.nodeTypeProperties()`] and link:{neo4j-docs-base-uri}/operations-manual/{page-version}/procedures/#procedure_db_schema_reltypeproperties[`db.schema.relTypeProperties()`] produces a list of strings representing the potential Java types for a given property. +The column `propertyTypes` currently returned by the procedures link:{neo4j-docs-base-uri}/operations-manual/current/procedures/#procedure_db_schema_nodetypeproperties[`db.schema.nodeTypeProperties()`] and link:{neo4j-docs-base-uri}/operations-manual/current/procedures/#procedure_db_schema_reltypeproperties[`db.schema.relTypeProperties()`] produces a list of strings representing the potential Java types for a given property. In an upcoming major release of Neo4j, this will be updated to represent the possible Cypher types for that property instead. For all available Cypher types, see the section on xref::values-and-types/property-structural-constructed.adoc#types-synonyms[types and their synonyms]. @@ -321,7 +321,7 @@ CREATE DATABASE db OPTIONS { seedCredentials: ..., seedConfig: ... } ---- | The `CREATE DATABASE` option `seedCredentials` has been deprecated. For seeding from cloud storage, it is recommended to use `CloudSeedProvider` which will read cloud credentials and configuration from standard locations. -For further information, see link:{neo4j-docs-base-uri}/operations-manual/{page-version}/clustering/databases/#cloud-seed-provider[Managing databases in a cluster -> CloudSeedProvider]. +For further information, see link:{neo4j-docs-base-uri}/operations-manual/current/clustering/databases/#cloud-seed-provider[Managing databases in a cluster -> CloudSeedProvider]. a| label:functionality[] @@ -334,7 +334,7 @@ CREATE DATABASE db OPTIONS { storeFormat: 'high_limit' } ---- | The `standard` and `high_limit` store formats have been deprecated. Creating databases with these formats is therefore also deprecated. -For more information on the deprecation of these formats, see link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-internals/store-formats/#format-deprecations[Store formats -> Format deprecations]. +For more information on the deprecation of these formats, see link:{neo4j-docs-base-uri}/operations-manual/current/database-internals/store-formats/#format-deprecations[Store formats -> Format deprecations]. a| label:functionality[] @@ -367,7 +367,7 @@ USE graph.byElementId("4:c0a65d96-4993-4b0c-b036-e7ebd9174905:0") MATCH (n) RETURN n ---- -| xref:functions/graph.adoc#functions-graph-by-elementid[`graph.byElementId()`] can now be used on both link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/[standard and composite databases]. +| xref:functions/graph.adoc#functions-graph-by-elementid[`graph.byElementId()`] can now be used on both link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/[standard and composite databases]. Previously it could only be used on composite databases. a| @@ -381,7 +381,7 @@ CREATE DATABASE foo TOPOLOGY $p PRIMARIES $s SECONDARIES ---- ALTER DATABASE foo SET TOPOLOGY $p PRIMARIES $s SECONDARIES ---- -| The link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/standard-databases/create-databases/[`CREATE DATABASE`] and link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/standard-databases/alter-databases/[`ALTER DATABASE`] commands now accept parameters for `TOPOLOGY` configuration. +| The link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/standard-databases/create-databases/[`CREATE DATABASE`] and link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/standard-databases/alter-databases/[`ALTER DATABASE`] commands now accept parameters for `TOPOLOGY` configuration. a| label:functionality[] @@ -390,7 +390,7 @@ label:updated[] ---- GRANT READ {*} ON GRAPH * FOR (n) WHERE n.createdAt > date('2024-10-25') TO regularUsers ---- -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/property-based-access-control/[Property-based access control] now supports xref:values-and-types/spatial.adoc[spatial] and xref:values-and-types/temporal.adoc[temporal] values. +| link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/property-based-access-control/[Property-based access control] now supports xref:values-and-types/spatial.adoc[spatial] and xref:values-and-types/temporal.adoc[temporal] values. a| @@ -471,7 +471,7 @@ label:deprecated[] ---- CREATE DATABASE db OPTIONS { existingDataSeedInstance: ... } ---- -| The `CREATE DATABASE` option `existingDataSeedInstance` has been deprecated and replaced with the option link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/standard-databases/create-databases/#manage-databases-create-database-options[`existingDataSeedServer`]. The functionality is unchanged. +| The `CREATE DATABASE` option `existingDataSeedInstance` has been deprecated and replaced with the option link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/standard-databases/create-databases/#manage-databases-create-database-options[`existingDataSeedServer`]. The functionality is unchanged. |=== === Updated features @@ -489,7 +489,7 @@ label:updated[] CREATE (n:Label {property: 'name'}), ()-[r:REL_TYPE]->() ---- -| Neo4j's link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-internals/store-formats/#store-format-overview[block format] now implements xref:appendix/gql-conformance/index.adoc[GQL's] limit on the maximum length of identifiers. +| Neo4j's link:{neo4j-docs-base-uri}/operations-manual/current/database-internals/store-formats/#store-format-overview[block format] now implements xref:appendix/gql-conformance/index.adoc[GQL's] limit on the maximum length of identifiers. The maximum limit is set to 16,383 characters in an identifier. This means that node labels, relationship types, and property keys cannot include more than 16,383 characters. @@ -509,7 +509,7 @@ label:new[] ---- CREATE DATABASE db OPTIONS { existingDataSeedServer: ... } ---- -| The option link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/standard-databases/create-databases/#manage-databases-create-database-options[`existingDataSeedServer`] has been added to `CREATE DATABASE`. The functionality is the same as the deprecated option `existingDataSeedServer`, which this replaces. +| The option link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/standard-databases/create-databases/#manage-databases-create-database-options[`existingDataSeedServer`] has been added to `CREATE DATABASE`. The functionality is the same as the deprecated option `existingDataSeedServer`, which this replaces. |=== [[cypher-deprecations-additions-removals-5.24]] @@ -601,7 +601,7 @@ DROP [COMPOSITE] DATABASE ... [RESTRICT \| CASCADE ALIAS[ES]] | Added the ability to drop database aliases while deleting a database. This will affect local database aliases targeting the database and constituent database aliases belonging to the composite database. -For more information, see link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/standard-databases/delete-databases/#delete-databases-with-aliases[Delete a database with local database aliases targeting it] and link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/composite-databases/delete-composite-databases/#composite-databases-delete-with-aliases[Delete a composite database with constituent database aliases]. +For more information, see link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/standard-databases/delete-databases/#delete-databases-with-aliases[Delete a database with local database aliases targeting it] and link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/composite-databases/delete-composite-databases/#composite-databases-delete-with-aliases[Delete a composite database with constituent database aliases]. a| label:functionality[] @@ -629,7 +629,7 @@ SET AUTH 'native' { SET PASSWORD CHANGE REQUIRED } ---- -| Added the ability set which link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/auth-providers[auth providers] apply to a user (Enterprise Edition). +| Added the ability set which link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/auth-providers[auth providers] apply to a user (Enterprise Edition). Administration of the native (username / password) auth via the new syntax is also now supported (Community Edition). @@ -644,7 +644,7 @@ SET AUTH 'externalProviderName' { SET ID 'userIdForExternalProvider' } ---- -| Added the ability add and remove user link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/auth-providers[auth providers] via the `ALTER USER` command. +| Added the ability add and remove user link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/auth-providers[auth providers] via the `ALTER USER` command. Setting the native (username / password) auth provider via this new syntax is also supported (Community Edition), but removing any auth provider or setting a non-native auth provider is only supported in Enterprise Edition. @@ -667,7 +667,7 @@ label:new[] + SET AUTH ---- a| -New privilege that allows a user to modify user link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/auth-providers[auth providers]. +New privilege that allows a user to modify user link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/auth-providers[auth providers]. This is a sub-privilege of the `ALTER USER` privilege. Like all `GRANT`/`DENY` commands this is only available in Enterprise Edition. @@ -817,7 +817,7 @@ GRANT TRAVERSE ON GRAPH * FOR (n:Email) WHERE n.classification IS NULL TO regula ---- DENY MATCH {*} ON GRAPH * FOR (n) WHERE n.classification <> 'UNCLASSIFIED' TO regularUsers ---- -| Introduction of link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/property-based-access-control[property-based access control] for read privileges. The ability to read, traverse and match nodes based on node property values is now supported in Enterprise Edition. +| Introduction of link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/property-based-access-control[property-based access control] for read privileges. The ability to read, traverse and match nodes based on node property values is now supported in Enterprise Edition. a| label:functionality[] @@ -1249,7 +1249,7 @@ GRANT LOAD ON CIDR "127.0.0.1/32" TO role DENY LOAD ON CIDR "::1/128" TO role ---- | Added the ability to grant or deny `LOAD` privilege on a CIDR range. -For more information, see the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/load-privileges/#access-control-load-cidr[Operations Manual -> The CIDR privilege]. +For more information, see the link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/load-privileges/#access-control-load-cidr[Operations Manual -> The CIDR privilege]. |=== @@ -1482,7 +1482,7 @@ CALL cdc.query(from, selectors) ---- | Introduction of the Change Data Capture (CDC) feature. -For details, see link:{neo4j-docs-base-uri}/cdc/{page-version}/[Change Data Capture]. +For details, see link:{neo4j-docs-base-uri}/cdc/current/[Change Data Capture]. a| label:functionality[] @@ -2102,7 +2102,7 @@ label:new[] `server.tag` a| New functionality to change tags at runtime via `ALTER SERVER`. -More information can be found in the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/clustering/servers#alter-server-options[Operations Manual -> `ALTER SERVER` options]. +More information can be found in the link:{neo4j-docs-base-uri}/operations-manual/current/clustering/servers#alter-server-options[Operations Manual -> `ALTER SERVER` options]. a| label:functionality[] @@ -4776,7 +4776,7 @@ EXECUTE ---- a| New Cypher commands for administering privileges for executing procedures and user defined functions. -See link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/dbms-administration/#access-control-dbms-administration-execute[The DBMS `EXECUTE` privileges]. +See link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/dbms-administration/#access-control-dbms-administration-execute[The DBMS `EXECUTE` privileges]. a| label:syntax[] @@ -5044,28 +5044,28 @@ New support for `YIELD` and `WHERE` clauses to allow filtering results. a| label:functionality[] label:new[] + -link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/database-administration/#access-control-database-administration-transaction[TRANSACTION MANAGEMENT] privileges +link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/database-administration/#access-control-database-administration-transaction[TRANSACTION MANAGEMENT] privileges a| New Cypher commands for administering transaction management. a| label:functionality[] label:new[] + -DBMS link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/dbms-administration/#access-control-dbms-administration-user-management[USER MANAGEMENT] privileges +DBMS link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/dbms-administration/#access-control-dbms-administration-user-management[USER MANAGEMENT] privileges a| New Cypher commands for administering user management. a| label:functionality[] label:new[] + -DBMS link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/dbms-administration/#access-control-dbms-administration-database-management[DATABASE MANAGEMENT] privileges +DBMS link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/dbms-administration/#access-control-dbms-administration-database-management[DATABASE MANAGEMENT] privileges a| New Cypher commands for administering database management. a| label:functionality[] label:new[] + -DBMS link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/dbms-administration/#access-control-dbms-administration-privilege-management[PRIVILEGE MANAGEMENT] privileges +DBMS link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/dbms-administration/#access-control-dbms-administration-privilege-management[PRIVILEGE MANAGEMENT] privileges a| New Cypher commands for administering privilege management. @@ -5438,21 +5438,21 @@ This Neo4j Enterprise Edition only feature involves a new runtime that has many a| label:functionality[] label:new[] + -link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/standard-databases/manage-databases/[Multi-database administration] +link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/standard-databases/manage-databases/[Multi-database administration] a| New Cypher commands for administering multiple databases. a| label:functionality[] label:new[] + -link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/[Access control] +link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/[Access control] a| New Cypher commands for administering role-based access control. a| label:functionality[] label:new[] + -link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/manage-privileges/[Fine-grained security] +link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/manage-privileges/[Fine-grained security] a| New Cypher commands for administering dbms, database, graph and sub-graph access control. diff --git a/modules/ROOT/pages/functions/graph.adoc b/modules/ROOT/pages/functions/graph.adoc index 57545af0f..2bec760c9 100644 --- a/modules/ROOT/pages/functions/graph.adoc +++ b/modules/ROOT/pages/functions/graph.adoc @@ -16,7 +16,7 @@ .Considerations |=== -| `graph.names()` is only supported on link:{neo4j-docs-base-uri}/operations-manual/{page-version}/composite-databases[composite databases]. +| `graph.names()` is only supported on link:{neo4j-docs-base-uri}/operations-manual/current/composite-databases[composite databases]. |=== .+graph.names()+ @@ -71,8 +71,8 @@ The names of all graphs on the current composite database are returned. .Considerations |=== -| `graph.propertiesByName()` is only supported on link:{neo4j-docs-base-uri}/operations-manual/{page-version}/composite-databases[composite databases]. -| The properties in the returned `MAP` are set on the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/aliases/manage-aliases-standard-databases/[alias]that adds the graph as a constituent of a composite database. +| `graph.propertiesByName()` is only supported on link:{neo4j-docs-base-uri}/operations-manual/current/composite-databases[composite databases]. +| The properties in the returned `MAP` are set on the link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/aliases/manage-aliases-standard-databases/[alias]that adds the graph as a constituent of a composite database. |=== .+graph.propertiesByName()+ @@ -194,7 +194,7 @@ Returns all nodes from all graphs on the current composite database. |=== | If the constituent database is not a standard database in the DBMS, an error will be thrown. | `graph.byElementId()` is only supported in the xref:clauses/use.adoc[`USE`] clause. -| `graph.byElementId()` is supported on both link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/[standard and composite databases]. +| `graph.byElementId()` is supported on both link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/[standard and composite databases]. | On a standard database, a `USE` clause with `graph.byElementId()` cannot be combined with other `USE` clauses unless the subsequent `USE` clauses reference the same element id. |=== diff --git a/modules/ROOT/pages/functions/index.adoc b/modules/ROOT/pages/functions/index.adoc index b077f3af1..b445ec420 100644 --- a/modules/ROOT/pages/functions/index.adoc +++ b/modules/ROOT/pages/functions/index.adoc @@ -748,12 +748,12 @@ There are two main types of functions that can be developed and used: | Scalar | For each row the function takes parameters and returns a result. | xref::functions/user-defined.adoc#query-functions-udf[Using UDF] -| link:{neo4j-docs-base-uri}/java-reference/{page-version}/extending-neo4j/functions#extending-neo4j-functions[Extending Neo4j (UDF)] +| link:{neo4j-docs-base-uri}/java-reference/current/extending-neo4j/functions#extending-neo4j-functions[Extending Neo4j (UDF)] | Aggregating | Consumes many rows and produces an aggregated result. | xref::functions/user-defined.adoc#query-functions-user-defined-aggregation[Using aggregating UDF] -| link:{neo4j-docs-base-uri}/java-reference/{page-version}/extending-neo4j/aggregation-functions#extending-neo4j-aggregation-functions[Extending Neo4j (Aggregating UDF)] +| link:{neo4j-docs-base-uri}/java-reference/current/extending-neo4j/aggregation-functions#extending-neo4j-aggregation-functions[Extending Neo4j (Aggregating UDF)] |=== diff --git a/modules/ROOT/pages/functions/scalar.adoc b/modules/ROOT/pages/functions/scalar.adoc index 66774ae1c..385bb6dc1 100644 --- a/modules/ROOT/pages/functions/scalar.adoc +++ b/modules/ROOT/pages/functions/scalar.adoc @@ -383,7 +383,7 @@ It is therefore recommended to use application-generated IDs instead. [NOTE] ==== -On a link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/composite-databases/concepts/[composite database], the `id()` function should be used with caution. +On a link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/composite-databases/concepts/[composite database], the `id()` function should be used with caution. It is recommended to use xref:functions/scalar.adoc#functions-elementid[`elementId()`] instead. When called in database-specific subqueries, the resulting ID value for a node or relationship is local to that database. diff --git a/modules/ROOT/pages/functions/user-defined.adoc b/modules/ROOT/pages/functions/user-defined.adoc index 6b3fb5209..c56b2e9a8 100644 --- a/modules/ROOT/pages/functions/user-defined.adoc +++ b/modules/ROOT/pages/functions/user-defined.adoc @@ -15,12 +15,12 @@ There are two main types of functions that can be developed and used: | Scalar | For each row the function takes parameters and returns a result. | xref::functions/user-defined.adoc#query-functions-udf[Using UDF] -| link:{neo4j-docs-base-uri}/java-reference/{page-version}/extending-neo4j/functions#extending-neo4j-functions[Extending Neo4j (UDF)] +| link:{neo4j-docs-base-uri}/java-reference/current/extending-neo4j/functions#extending-neo4j-functions[Extending Neo4j (UDF)] | Aggregating | Consumes many rows and produces an aggregated result. | xref::functions/user-defined.adoc#query-functions-user-defined-aggregation[Using aggregating UDF] -| link:{neo4j-docs-base-uri}/java-reference/{page-version}/extending-neo4j/aggregation-functions#extending-neo4j-aggregation-functions[Extending Neo4j (Aggregating UDF)] +| link:{neo4j-docs-base-uri}/java-reference/current/extending-neo4j/aggregation-functions#extending-neo4j-aggregation-functions[Extending Neo4j (Aggregating UDF)] |=== @@ -30,7 +30,7 @@ There are two main types of functions that can be developed and used: For each incoming row the function takes parameters and returns a single result. -For developing and deploying user-defined functions in Neo4j, see link:{neo4j-docs-base-uri}/java-reference/{page-version}/extending-neo4j/functions#extending-neo4j-functions[Extending Neo4j -> User-defined functions]. +For developing and deploying user-defined functions in Neo4j, see link:{neo4j-docs-base-uri}/java-reference/current/extending-neo4j/functions#extending-neo4j-functions[Extending Neo4j -> User-defined functions]. .Call a user-defined function diff --git a/modules/ROOT/pages/genai-integrations.adoc b/modules/ROOT/pages/genai-integrations.adoc index 13ff3ed3d..a8c233e70 100644 --- a/modules/ROOT/pages/genai-integrations.adoc +++ b/modules/ROOT/pages/genai-integrations.adoc @@ -22,7 +22,7 @@ The GenAI plugin is enabled by default in Neo4j Aura. The plugin needs to be installed on self-managed instances. This is done by moving the `neo4j-genai.jar` file from `/products` to `/plugins` in the Neo4j home directory, or, if you are using Docker, by starting the Docker container with the extra parameter `--env NEO4J_PLUGINS='["genai"]'`. -For more information, see link:{neo4j-docs-base-uri}/operations-manual/{page-version}/configuration/plugins/[Operations Manual -> Configure plugins]. +For more information, see link:{neo4j-docs-base-uri}/operations-manual/current/configuration/plugins/[Operations Manual -> Configure plugins]. [[example-graph]] @@ -36,7 +36,7 @@ The graph contains 28863 nodes and 332522 relationships. There are 9083 `Movie` nodes with a `plot` and `title` property. To recreate the graph, download and import this link:https://github.com/neo4j-graph-examples/recommendations/blob/main/data/recommendations-embeddings-50.dump[dump file] to an empty Neo4j database. -Dump files can be imported for both link:{neo4j-docs-base-uri}/aura/auradb/importing/import-database/[Aura] and link:{neo4j-docs-base-uri}/operations-manual/{page-version}/backup-restore/restore-dump/[on-prem] instances. +Dump files can be imported for both link:{neo4j-docs-base-uri}/aura/auradb/importing/import-database/[Aura] and link:{neo4j-docs-base-uri}/operations-manual/current/backup-restore/restore-dump/[on-prem] instances. [NOTE] The embeddings on this are generated using link:https://platform.openai.com/docs/guides/embeddings[OpenAI] (model `text-embedding-ada-002`), producing 1536-dimensional vectors. diff --git a/modules/ROOT/pages/indexes/search-performance-indexes/managing-indexes.adoc b/modules/ROOT/pages/indexes/search-performance-indexes/managing-indexes.adoc index 4e8f43cdd..7780bc811 100644 --- a/modules/ROOT/pages/indexes/search-performance-indexes/managing-indexes.adoc +++ b/modules/ROOT/pages/indexes/search-performance-indexes/managing-indexes.adoc @@ -38,7 +38,7 @@ However, not all indexes have available configuration settings. In those cases, nothing needs to be specified and the `OPTIONS` map should be omitted from the query. [TIP] -Creating an index requires link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/database-administration/#access-control-database-administration-index[the `CREATE INDEX` privilege]. +Creating an index requires link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/database-administration/#access-control-database-administration-index[the `CREATE INDEX` privilege]. [NOTE] An index cannot be used while its `state` is `POPULATING`, which occurs immediately after it is created. @@ -782,7 +782,7 @@ There already exists a constraint called 'bookRecommendations'. Listing indexes can be done with `SHOW INDEXES`. [TIP] -Listing indexes requires link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/database-administration/#access-control-database-administration-index[the `SHOW INDEX` privilege]. +Listing indexes requires link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/database-administration/#access-control-database-administration-index[the `SHOW INDEX` privilege]. [discrete] [[listing-indexes-examples]] @@ -1027,7 +1027,7 @@ With `IF EXISTS`, no error is thrown and nothing happens should the index not ex Instead, an informational notification is returned detailing that the index does not exist. [TIP] -Dropping an index requires link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/authentication-authorization/database-administration/#access-control-database-administration-index[the `DROP INDEX` privilege]. +Dropping an index requires link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/authentication-authorization/database-administration/#access-control-database-administration-index[the `DROP INDEX` privilege]. [discrete] [[drop-indexes-examples]] diff --git a/modules/ROOT/pages/indexes/search-performance-indexes/using-indexes.adoc b/modules/ROOT/pages/indexes/search-performance-indexes/using-indexes.adoc index 01fb04891..cf7cdd732 100644 --- a/modules/ROOT/pages/indexes/search-performance-indexes/using-indexes.adoc +++ b/modules/ROOT/pages/indexes/search-performance-indexes/using-indexes.adoc @@ -28,7 +28,7 @@ image::using_indexes_example_graph.svg[width="600",role="middle"] In total, the graph contains 69165 nodes (of which 188 have the label `PointOfInterest`) and 152077 `ROUTE` relationships. To recreate the graph, download and import the link:https://github.com/neo4j-graph-examples/openstreetmap/blob/main/data/openstreetmap-50.dump[5.0 dump file] to an empty Neo4j database. -Dump files can be imported for both link:{neo4j-docs-base-uri}/aura/auradb/importing/import-database/[Aura] and link:{neo4j-docs-base-uri}/operations-manual/{page-version}/backup-restore/restore-dump/[on-prem] instances. +Dump files can be imported for both link:{neo4j-docs-base-uri}/aura/auradb/importing/import-database/[Aura] and link:{neo4j-docs-base-uri}/operations-manual/current/backup-restore/restore-dump/[on-prem] instances. [[token-lookup-indexes]] == Token lookup indexes diff --git a/modules/ROOT/pages/indexes/semantic-indexes/full-text-indexes.adoc b/modules/ROOT/pages/indexes/semantic-indexes/full-text-indexes.adoc index 50c08ee63..ff18a4f06 100644 --- a/modules/ROOT/pages/indexes/semantic-indexes/full-text-indexes.adoc +++ b/modules/ROOT/pages/indexes/semantic-indexes/full-text-indexes.adoc @@ -42,7 +42,7 @@ Instead, an informational notification is returned showing the existing index wh The index name can also be given as a parameter, `CREATE FULLTEXT INDEX $name FOR ...`. [TIP] -Creating a full-text index requires the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/database-administration/#access-control-database-administration-index[`CREATE INDEX` privilege]. +Creating a full-text index requires the link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/database-administration/#access-control-database-administration-index[`CREATE INDEX` privilege]. When creating a full-text index, you need to specify the labels/relationship types and property names it should apply to. @@ -91,10 +91,10 @@ Removing stop words can help reduce the size of stored data and thereby improve In some cases, using different analyzers for the indexed values and query string is more appropriate. For example, if handling `STRING` values written in Swedish, it may be beneficial to select the `swedish` analyzer, which knows how to tokenize Swedish words, and will avoid indexing Swedish stop words. -The link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_index_fulltext_listavailableanalyzers[`db.index.fulltext.listAvailableAnalyzers()`] procedure shows all available analyzers. +The link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_db_index_fulltext_listavailableanalyzers[`db.index.fulltext.listAvailableAnalyzers()`] procedure shows all available analyzers. Neo4j also supports the use of custom analyzers. -For more information, see the link:{neo4j-docs-base-uri}/java-reference/{page-version}/extending-neo4j/full-text-analyzer-provider[Java Reference Manual -> Full-text index analyzer providers]. +For more information, see the link:{neo4j-docs-base-uri}/java-reference/current/extending-neo4j/full-text-analyzer-provider[Java Reference Manual -> Full-text index analyzer providers]. [[configuration-settings]] === Configuration settings @@ -128,13 +128,13 @@ The possible values for the `fulltext.analyzer` setting can be listed with the ` <2> The `fulltext.eventually_consistent` setting, if set to `true`, will put the index in an _eventually consistent_ update mode. This means that updates will be applied in a background thread "as soon as possible", instead of during a transaction commit, which is true for other indexes. -For more information on how to configure full-text indexes, refer to the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/performance/index-configuration#index-configuration-fulltext[Operations Manual -> Indexes to support full-text search]. +For more information on how to configure full-text indexes, refer to the link:{neo4j-docs-base-uri}/operations-manual/current/performance/index-configuration#index-configuration-fulltext[Operations Manual -> Indexes to support full-text search]. [[query-full-text-indexes]] == Query full-text indexes Unlike xref:indexes/search-performance-indexes/managing-indexes.adoc[search-performance indexes], full-text indexes are not automatically used by the xref:planning-and-tuning/execution-plans.adoc[Cypher query planner]. -To query a full-text index, use either the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_index_fulltext_querynodes[`db.index.fulltext.queryNodes`] or the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_index_fulltext_relationships[`db.index.fulltext.queryRelationships`] procedure. +To query a full-text index, use either the link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_db_index_fulltext_querynodes[`db.index.fulltext.queryNodes`] or the link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_db_index_fulltext_relationships[`db.index.fulltext.queryRelationships`] procedure. [NOTE] An index cannot be used while its `state` is `POPULATING`, which occurs immediately after it is created. @@ -390,7 +390,7 @@ The procedures for full-text indexes are listed in the table below: * Full-text indexes can be queried using the Lucene query language. * Full-text indexes are kept up to date automatically, as nodes and relationships are added, removed, and modified. * Full-text indexes will automatically populate newly created indexes with the existing data in a store. -* Full-text indexes can be checked by the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/tools/neo4j-admin/consistency-checker[consistency checker], and they can be rebuilt if there is a problem with them. +* Full-text indexes can be checked by the link:{neo4j-docs-base-uri}/operations-manual/current/tools/neo4j-admin/consistency-checker[consistency checker], and they can be rebuilt if there is a problem with them. * Newly created full-text indexes get automatically populated with the existing data in the database. * Full-text indexes can support any number of properties in a single index. * Full-text indexes are created, dropped, and updated transactionally, and are automatically replicated throughout a cluster. diff --git a/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc b/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc index cbce11432..6322ff0ce 100644 --- a/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc +++ b/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc @@ -27,7 +27,7 @@ image::vector_index_graph.svg[width="600",role="middle"] The graph contains 28863 nodes and 332522 relationships. To recreate the graph, download and import this link:https://github.com/neo4j-graph-examples/recommendations/blob/main/data/recommendations-embeddings-50.dump[dump file] to an empty Neo4j database. -Dump files can be imported for both link:{neo4j-docs-base-uri}/aura/auradb/importing/import-database/[Aura] and link:{neo4j-docs-base-uri}/operations-manual/{page-version}/backup-restore/restore-dump/[on-prem] instances. +Dump files can be imported for both link:{neo4j-docs-base-uri}/aura/auradb/importing/import-database/[Aura] and link:{neo4j-docs-base-uri}/operations-manual/current/backup-restore/restore-dump/[on-prem] instances. [NOTE] The dump file used to load the dataset contains embeddings generated by https://openai.com/[OpenAI], using the model `text-embedding-ada-002`. @@ -81,7 +81,7 @@ The index name must be unique among both indexes and constraints. + A newly created index is not immediately available but is created in the background. [TIP] -Creating indexes requires link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/database-administration/#access-control-database-administration-index[the `CREATE INDEX` privilege]. +Creating indexes requires link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/database-administration/#access-control-database-administration-index[the `CREATE INDEX` privilege]. .Create vector index for `Movie` nodes on the `embedding` property [source, cypher] @@ -182,7 +182,7 @@ Default value::: `100` [[query-vector-index]] == Query vector indexes -To query a node vector index, use the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_index_vector_queryNodes[`db.index.vector.queryNodes`] procedure. +To query a node vector index, use the link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_db_index_vector_queryNodes[`db.index.vector.queryNodes`] procedure. [NOTE] An index cannot be used while its `state` is `POPULATING`, which occurs immediately after it is created. @@ -228,7 +228,7 @@ Note that all movies returned have a plot centred around criminal family organiz The `score` results are returned in _descending order_, where the best matching result entry is put first (in this case, `The Godfather` has a similarity score of `1.0`, which is to be expected as the index was queried with this specific property). If the query vector itself is not wanted, adding the predicate `WHERE score < 1` removes identical vectors. -To query a relationship vector index, use the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_index_vector_queryRelationships[`db.index.vector.queryRelationships`] procedure. +To query a relationship vector index, use the link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_db_index_vector_queryRelationships[`db.index.vector.queryRelationships`] procedure. .Signature for `db.index.vector.queryRelationships` [source,syntax] @@ -245,7 +245,7 @@ Use xref:functions/vector.adoc[] to compute the similarity score between two spe == Performance suggestions Vector indexes can take advantage of the incubated Java 20 Vector API for noticeable speed improvements. -If you are using a compatible version of Java, you can add the following setting to your link:{neo4j-docs-base-uri}/operations-manual/{page-version}/configuration/configuration-settings/#config_server.jvm.additional[configuration settings]: +If you are using a compatible version of Java, you can add the following setting to your link:{neo4j-docs-base-uri}/operations-manual/current/configuration/configuration-settings/#config_server.jvm.additional[configuration settings]: .Configuration settings [source,config] @@ -260,7 +260,7 @@ To list all vector indexes in a database, use the `SHOW VECTOR INDEXES` command. This is the same xref:indexes/search-performance-indexes/managing-indexes.adoc#list-indexes[`SHOW` command as for other indexes], with the index type filtering on `VECTOR`. [TIP] -Listing indexes requires link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/database-administration/#access-control-database-administration-index[the `SHOW INDEX` privilege]. +Listing indexes requires link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/database-administration/#access-control-database-administration-index[the `SHOW INDEX` privilege]. .Show all vector indexes ==== @@ -331,7 +331,7 @@ A vector index is dropped by using the xref:indexes/search-performance-indexes/m The index name can also be given as a parameter when dropping an index: `DROP INDEX $name`. [TIP] -Dropping indexes requires link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/authentication-authorization/database-administration/#access-control-database-administration-index[the `DROP INDEX` privilege]. +Dropping indexes requires link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/authentication-authorization/database-administration/#access-control-database-administration-index[the `DROP INDEX` privilege]. .Drop a vector index [source, cypher] @@ -466,30 +466,30 @@ image::euclidean_similarity_equation.svg["The Euclidean of vector v and vector u | Usage | Procedure | Description | Create node vector index. -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_index_vector_createnodeindex[`db.index.vector.createNodeIndex`] +| link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_db_index_vector_createnodeindex[`db.index.vector.createNodeIndex`] | Create a vector index for the specified label and property with the given vector dimension using the given similarity function. Replaced by the `CREATE VECTOR INDEX` command. | Use node vector index. -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_index_vector_queryNodes[`db.index.vector.queryNodes`] +| link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_db_index_vector_queryNodes[`db.index.vector.queryNodes`] | Query the given node vector index. Returns the requested number of approximate nearest neighbor nodes and their similarity score, ordered by score. | Use relationship vector index. -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_index_vector_queryRelationships[`db.index.vector.queryRelationships`] +| link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_db_index_vector_queryRelationships[`db.index.vector.queryRelationships`] | Query the given relationship vector index. Returns the requested number of approximate nearest neighbor relationships and their similarity score, ordered by score. | Set node vector property. -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_create_setNodeVectorProperty[`db.create.setNodeVectorProperty`] -| Update a given node property with the given vector in a more space-efficient way than directly using xref:clauses/set.adoc#set-set-a-property[`SET`]. Replaces link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_create_setVectorProperty[`db.create.setVectorProperty`]. label:beta[] +| link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_db_create_setNodeVectorProperty[`db.create.setNodeVectorProperty`] +| Update a given node property with the given vector in a more space-efficient way than directly using xref:clauses/set.adoc#set-set-a-property[`SET`]. Replaces link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_db_create_setVectorProperty[`db.create.setVectorProperty`]. label:beta[] | Set node vector property. -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_create_setVectorProperty[`db.create.setVectorProperty`] -| Replaced by link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_create_setNodeVectorProperty[`db.create.setNodeVectorProperty`]. label:deprecated[] label:beta[] +| link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_db_create_setVectorProperty[`db.create.setVectorProperty`] +| Replaced by link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_db_create_setNodeVectorProperty[`db.create.setNodeVectorProperty`]. label:deprecated[] label:beta[] | Set relationship vector property. -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_create_setRelationshipVectorProperty[`db.create.setRelationshipVectorProperty`] +| link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_db_create_setRelationshipVectorProperty[`db.create.setRelationshipVectorProperty`] | Update a given relationship property with the given vector in a more space-efficient way than directly using xref:clauses/set.adoc#set-set-a-property[`SET`]. label:beta[] |=== @@ -523,7 +523,7 @@ The following table lists the known issues and, if fixed, the version in which t |=== | Known issues | Fixed in -| The creation of a vector index using the legacy procedure link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_index_vector_createnodeindex[`db.index.vector.createNodeIndex`] may fail with an error in Neo4j 5.18 and later if the database was last written to with a version prior to Neo4j 5.11, and the legacy procedure is the first write operation used on the newer version. +| The creation of a vector index using the legacy procedure link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_db_index_vector_createnodeindex[`db.index.vector.createNodeIndex`] may fail with an error in Neo4j 5.18 and later if the database was last written to with a version prior to Neo4j 5.11, and the legacy procedure is the first write operation used on the newer version. In Neo4j 5.20, the error was clarified. [TIP] -- diff --git a/modules/ROOT/pages/indexes/syntax.adoc b/modules/ROOT/pages/indexes/syntax.adoc index 0678c7d98..c121708d8 100644 --- a/modules/ROOT/pages/indexes/syntax.adoc +++ b/modules/ROOT/pages/indexes/syntax.adoc @@ -4,7 +4,7 @@ This page contains the syntax for creating, listing, and dropping the indexes available in Neo4j. It also contains the signatures for the procedures necessary to call in order to use full-text and vector indexes. -More details about the syntax can be found in the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/syntax/[Operations Manual -> Cypher syntax for administration commands]. +More details about the syntax can be found in the link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/syntax/[Operations Manual -> Cypher syntax for administration commands]. [[create-index]] == CREATE INDEX @@ -32,7 +32,7 @@ However, not all indexes have available configuration settings. In those cases, nothing needs to be specified and the `OPTIONS` map should be omitted from the query. [TIP] -Creating an index requires link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/database-administration/#access-control-database-administration-index[the `CREATE INDEX` privilege]. +Creating an index requires link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/database-administration/#access-control-database-administration-index[the `CREATE INDEX` privilege]. [[create-range-index]] === Range indexes @@ -226,7 +226,7 @@ For more information, see xref:indexes/semantic-indexes/vector-indexes.adoc#crea == SHOW INDEX [TIP] -Listing indexes requires link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/database-administration/#access-control-database-administration-index[the `SHOW INDEX` privilege]. +Listing indexes requires link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/database-administration/#access-control-database-administration-index[the `SHOW INDEX` privilege]. .List indexes in the database (either all or filtered on index type) [source, syntax] @@ -304,7 +304,7 @@ With `IF EXISTS`, no error is thrown and nothing happens should the index not ex Instead, an informational notification is returned detailing that the index does not exist. [TIP] -Dropping indexes requires link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/database-administration/#access-control-database-administration-index[the `DROP INDEX` privilege]. +Dropping indexes requires link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/database-administration/#access-control-database-administration-index[the `DROP INDEX` privilege]. .Drop an index of any index type [source,syntax] diff --git a/modules/ROOT/pages/introduction/cypher-aura.adoc b/modules/ROOT/pages/introduction/cypher-aura.adoc index bd117c999..380ea527f 100644 --- a/modules/ROOT/pages/introduction/cypher-aura.adoc +++ b/modules/ROOT/pages/introduction/cypher-aura.adoc @@ -36,12 +36,12 @@ For example, it is not possible to create, alter, or drop databases using Aura, Additionally, some Cypher features are exclusive to AuraDB Business Critical and AuraDB Virtual Dedicated Cloud tiers. These primarily fall under database administration and role-based access control capabilities. -For more information, see the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/[Operations Manual -> Database administration] and the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/[Operations Manual -> Authentication and authorization]. +For more information, see the link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/[Operations Manual -> Database administration] and the link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/[Operations Manual -> Authentication and authorization]. == Aura and the Cypher Cheat Sheet Each different tier of Aura has a customized version of the Cypher Cheat Sheet which only shows the features of Cypher available for the chosen tier. -The Cypher Cheat Sheet can be accessed link:{neo4j-docs-base-uri}/cypher-cheat-sheet/{page-version}/auradb-enterprise/[here]. +The Cypher Cheat Sheet can be accessed link:{neo4j-docs-base-uri}/cypher-cheat-sheet/current/auradb-enterprise/[here]. You can select your desired Aura tier and Neo4j version by using the dropdown menus provided. Note that the default tier is AuraDB Virtual Dedicated Cloud. diff --git a/modules/ROOT/pages/introduction/cypher-neo4j.adoc b/modules/ROOT/pages/introduction/cypher-neo4j.adoc index 5d3482c59..5572a502b 100644 --- a/modules/ROOT/pages/introduction/cypher-neo4j.adoc +++ b/modules/ROOT/pages/introduction/cypher-neo4j.adoc @@ -16,7 +16,7 @@ Cypher works almost identically between the two editions, but there are key area |=== | Feature | Enterprise Edition | Community Edition -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/[Multi-database] +| link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/[Multi-database] a| Any number of user databases. a| @@ -24,9 +24,9 @@ Only `system` and one user database. | Role-based security a| -User, role, and privilege management for flexible link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/manage-privileges/[access control] and link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/manage-privileges/[sub-graph access control]. +User, role, and privilege management for flexible link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/manage-privileges/[access control] and link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/manage-privileges/[sub-graph access control]. a| -link:{neo4j-docs-base-uri}/operations-manual/{page-version}authentication-authorization/manage-users[Multi-user management]. +link:{neo4j-docs-base-uri}/operations-manual/currentauthentication-authorization/manage-users[Multi-user management]. All users have full access rights. | Constraints @@ -55,7 +55,7 @@ Normally there is only one graph within each database, and many administrative c Cypher queries executed in a session may declare which graph they apply to, or use a default, given by the session. Composite databases can contain multiple graphs, by means of aliases to other databases. Queries submitted to composite databases may refer to multiple graphs within the same query. -For more information, see link:{neo4j-docs-base-uri}/operations-manual/{page-version}/composite-databases/[Operations manual -> Composite databases]. +For more information, see link:{neo4j-docs-base-uri}/operations-manual/current/composite-databases/[Operations manual -> Composite databases]. *Database*:: A database is a storage and retrieval mechanism for collecting data in a defined space on disk and in memory. @@ -70,12 +70,12 @@ A fresh installation of Neo4j includes two databases: * `system` - the system database described above, containing meta-data on the DBMS and security configuration. * `neo4j` - the default database, named using the config option `dbms.default_database=neo4j`. -For more information about the _system_ database, see the sections on link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/[Database management] and link:{neo4j-docs-base-uri}/operations-manual/{page-version}/authentication-authorization/[Access control]. +For more information about the _system_ database, see the sections on link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/[Database management] and link:{neo4j-docs-base-uri}/operations-manual/current/authentication-authorization/[Access control]. === Query considerations Most of the time Cypher queries are reading or updating queries, which are run against a graph. -There are also link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/syntax[administrative commands] that apply to a database, or to the entire DBMS. +There are also link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/syntax[administrative commands] that apply to a database, or to the entire DBMS. Administrative commands cannot be run in a session connected to a normal user database, but instead need to be run within a session connected to the `system` database. Administrative commands execute on the `system` database. If an administrative command is submitted to a user database, it is rerouted to the system database. @@ -92,7 +92,7 @@ In short, an updating query always either fully succeeds or does not succeed at [NOTE] ==== A query that makes a large number of updates consequently uses large amounts of memory since the transaction holds changes in memory. -For memory configuration in Neo4j, see the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/performance/memory-configuration[Neo4j Operations Manual -> Memory configuration]. +For memory configuration in Neo4j, see the link:{neo4j-docs-base-uri}/operations-manual/current/performance/memory-configuration[Neo4j Operations Manual -> Memory configuration]. ==== === Explicit and implicit transactions @@ -119,9 +119,9 @@ Explicit transactions cannot be managed directly from queries, they must be mana For examples of the API, or the commands used to start and commit transactions, refer to the API or tool-specific documentation: * For information on using transactions with a Neo4j driver, see _The session API_ in the link:{docs-base-uri}[Neo4j Driver manuals]. -* For information on using transactions over the HTTP API, see the link:{neo4j-docs-base-uri}/http-api/{page-version}/actions#http-api-actions[HTTP API documentation -> Using the HTTP API]. -* For information on using transactions within the embedded Core API, see the link:{neo4j-docs-base-uri}/java-reference/{page-version}/java-embedded/cypher-java#cypher-java[Java Reference -> Executing Cypher queries from Java]. -* For information on using transactions within the Neo4j Browser or Cypher-shell, see the link:{neo4j-docs-base-uri}/browser-manual/current/reference-commands/[Neo4j Browser documentation] or the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/tools/cypher-shell/#cypher-shell-commands[Cypher-shell documentation]. +* For information on using transactions over the HTTP API, see the link:{neo4j-docs-base-uri}/http-api/current/actions#http-api-actions[HTTP API documentation -> Using the HTTP API]. +* For information on using transactions within the embedded Core API, see the link:{neo4j-docs-base-uri}/java-reference/current/java-embedded/cypher-java#cypher-java[Java Reference -> Executing Cypher queries from Java]. +* For information on using transactions within the Neo4j Browser or Cypher-shell, see the link:{neo4j-docs-base-uri}/browser-manual/current/reference-commands/[Neo4j Browser documentation] or the link:{neo4j-docs-base-uri}/operations-manual/current/tools/cypher-shell/#cypher-shell-commands[Cypher-shell documentation]. When writing procedures or using Neo4j embedded, remember that all iterators returned from an execution result should be either fully exhausted or closed. This ensures that the resources bound to them are properly released. diff --git a/modules/ROOT/pages/introduction/cypher-overview.adoc b/modules/ROOT/pages/introduction/cypher-overview.adoc index ebaac533c..865cde7bf 100644 --- a/modules/ROOT/pages/introduction/cypher-overview.adoc +++ b/modules/ROOT/pages/introduction/cypher-overview.adoc @@ -82,4 +82,4 @@ RETURN actor.name Neo4j supports the APOC (Awesome Procedures on Cypher) Core library. The APOC Core library provides access to user-defined procedures and functions which extend the use of the Cypher query language into areas such as data integration, graph algorithms, and data conversion. -For more details, visit the link:{neo4j-docs-base-uri}/apoc/{page-version}[APOC Core page]. +For more details, visit the link:{neo4j-docs-base-uri}/apoc/current[APOC Core page]. diff --git a/modules/ROOT/pages/introduction/index.adoc b/modules/ROOT/pages/introduction/index.adoc index 3026c693d..01fef1f03 100644 --- a/modules/ROOT/pages/introduction/index.adoc +++ b/modules/ROOT/pages/introduction/index.adoc @@ -13,10 +13,10 @@ Cypher is Neo4j’s declarative query language, allowing users to unlock the ful The Cypher Manual aims to be as instructive as possible to readers from a variety of backgrounds and professions, such as developers, administrators, and academic researchers. -If you are new to Cypher and Neo4j, you can visit the link:{neo4j-docs-base-uri}/getting-started/{page-version}/cypher-intro/[Getting Started Guide -> Introduction to Cypher] chapter. +If you are new to Cypher and Neo4j, you can visit the link:{neo4j-docs-base-uri}/getting-started/current/cypher-intro/[Getting Started Guide -> Introduction to Cypher] chapter. Additionally, https://graphacademy.neo4j.com/[Neo4j GraphAcademy] has a variety of free courses tailored for all levels of experience. -For a reference of all available Cypher features, see the link:{neo4j-docs-base-uri}/cypher-cheat-sheet/{page-version}/[Cypher Cheat Sheet]. +For a reference of all available Cypher features, see the link:{neo4j-docs-base-uri}/cypher-cheat-sheet/current/[Cypher Cheat Sheet]. For a downloadable PDF version of the Cypher Manual, visit the link:{neo4j-docs-base-uri}/resources/docs-archive/#_cypher_query_language[Neo4j documentation archive]. diff --git a/modules/ROOT/pages/patterns/reference.adoc b/modules/ROOT/pages/patterns/reference.adoc index ac4754169..c1f61415c 100644 --- a/modules/ROOT/pages/patterns/reference.adoc +++ b/modules/ROOT/pages/patterns/reference.adoc @@ -1371,7 +1371,7 @@ They are similar to `SHORTEST 1` and `ALL SHORTEST`, but with several difference * The path pattern is passed as an argument to the functions. * The path pattern is limited to a single relationship pattern. -* To return results where the first and last node in the path are the same requires a change to the configuration setting link:{neo4j-docs-base-uri}/operations-manual/{page-version}/configuration/configuration-settings/#config_dbms.cypher.forbid_shortestpath_common_nodes[`dbms.cypher.forbid_shortestpath_common_nodes`]. +* To return results where the first and last node in the path are the same requires a change to the configuration setting link:{neo4j-docs-base-uri}/operations-manual/current/configuration/configuration-settings/#config_dbms.cypher.forbid_shortestpath_common_nodes[`dbms.cypher.forbid_shortestpath_common_nodes`]. * The minimum path length, also called the lower bound of the variable-length relationship pattern, should be 0 or 1. Both functions will continue to be available, but they are not xref:appendix/gql-conformance/index.adoc[GQL conformant]. diff --git a/modules/ROOT/pages/planning-and-tuning/execution-plans.adoc b/modules/ROOT/pages/planning-and-tuning/execution-plans.adoc index 031723c36..ec6c0cb5c 100644 --- a/modules/ROOT/pages/planning-and-tuning/execution-plans.adoc +++ b/modules/ROOT/pages/planning-and-tuning/execution-plans.adoc @@ -91,7 +91,7 @@ MATCH (:Station { name: 'Denmark Hill' })<-[:CALLS_AT]-(d:Stop) RETURN count(*) ---- -This is the resulting execution planfootnote:[The format of the execution plans displayed in this section are those generated when using link:{neo4j-docs-base-uri}/operations-manual/{page-version}/tools/cypher-shell[Cypher Shell]. +This is the resulting execution planfootnote:[The format of the execution plans displayed in this section are those generated when using link:{neo4j-docs-base-uri}/operations-manual/current/tools/cypher-shell[Cypher Shell]. The execution plans generated by link:{neo4j-docs-base-uri}/browser-manual/current[Neo4j Browser] use a different format.]: [role="queryplan"] diff --git a/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc b/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc index fa208f2c2..128729768 100644 --- a/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc +++ b/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc @@ -1507,7 +1507,7 @@ Total database accesses: 37 The `DirectedUnionRelationshipTypesScan` operator fetches all relationships and their start and end nodes with at least one of the provided types from the relationship type index. [NOTE] -As the block storage format becomes the default, this operator will cease to be used in generating plans. Please refer to link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-internals/store-formats[Operations Manual -> Store formats] for futher details on the various store formats available. +As the block storage format becomes the default, this operator will cease to be used in generating plans. Please refer to link:{neo4j-docs-base-uri}/operations-manual/current/database-internals/store-formats[Operations Manual -> Store formats] for futher details on the various store formats available. .DirectedUnionRelationshipTypesScan ====== @@ -1552,7 +1552,7 @@ The `PartitionedDirectedUnionRelationshipTypeScan` is a variant of the xref:plan It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. [NOTE] -As the block storage format becomes the default, this operator will cease to be used in generating plans. Please refer to link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-internals/store-formats[Operations Manual -> Store formats] for futher details on the various store formats available. +As the block storage format becomes the default, this operator will cease to be used in generating plans. Please refer to link:{neo4j-docs-base-uri}/operations-manual/current/database-internals/store-formats[Operations Manual -> Store formats] for futher details on the various store formats available. .PartitionedDirectedUnionRelationshipTypesScan ====== @@ -1598,7 +1598,7 @@ Total database accesses: 25 The `UndirectedUnionRelationshipTypesScan` operator fetches all relationships and their start and end nodes with at least one of the provided types from the relationship type index. [NOTE] -As the block storage format becomes the default, this operator will cease to be used in generating plans. Please refer to link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-internals/store-formats[Operations Manual -> Store formats] for futher details on the various store formats available. +As the block storage format becomes the default, this operator will cease to be used in generating plans. Please refer to link:{neo4j-docs-base-uri}/operations-manual/current/database-internals/store-formats[Operations Manual -> Store formats] for futher details on the various store formats available. .UndirectedUnionRelationshipTypeScan ====== @@ -1642,7 +1642,7 @@ The `PartitionedUndirectedUnionRelationshipTypeScan` is a variant of the xref:pl It allows the index to be partitioned into different segments where each segment can be scanned independently in parallel. [NOTE] -As the block storage format becomes the default, this operator will cease to be used in generating plans. Please refer to link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-internals/store-formats[Operations Manual -> Store formats] for futher details on the various store formats available. +As the block storage format becomes the default, this operator will cease to be used in generating plans. Please refer to link:{neo4j-docs-base-uri}/operations-manual/current/database-internals/store-formats[Operations Manual -> Store formats] for futher details on the various store formats available. .PartitionedUndirectedUnionRelationshipTypesScan ====== diff --git a/modules/ROOT/pages/planning-and-tuning/query-tuning.adoc b/modules/ROOT/pages/planning-and-tuning/query-tuning.adoc index 4a596f9c4..5d077bec4 100644 --- a/modules/ROOT/pages/planning-and-tuning/query-tuning.adoc +++ b/modules/ROOT/pages/planning-and-tuning/query-tuning.adoc @@ -248,8 +248,8 @@ This setting is experimental, and using it in a production environment is discou Cypher replanning occurs in the following circumstances: * When the query is not in the cache. -This can either be when the server is first started or restarted, if the cache has recently been cleared, or if link:{neo4j-docs-base-uri}/operations-manual/{page-version}/configuration/configuration-settings#config_server.db.query_cache_size[server.db.query_cache_size] was exceeded. -* When the time has past the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/configuration/configuration-settings#config_dbms.cypher.min_replan_interval[dbms.cypher.min_replan_interval] value, and the database statistics have changed more than the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/configuration/configuration-settings#config_dbms.cypher.statistics_divergence_threshold[dbms.cypher.statistics_divergence_threshold] value. +This can either be when the server is first started or restarted, if the cache has recently been cleared, or if link:{neo4j-docs-base-uri}/operations-manual/current/configuration/configuration-settings#config_server.db.query_cache_size[server.db.query_cache_size] was exceeded. +* When the time has past the link:{neo4j-docs-base-uri}/operations-manual/current/configuration/configuration-settings#config_dbms.cypher.min_replan_interval[dbms.cypher.min_replan_interval] value, and the database statistics have changed more than the link:{neo4j-docs-base-uri}/operations-manual/current/configuration/configuration-settings#config_dbms.cypher.statistics_divergence_threshold[dbms.cypher.statistics_divergence_threshold] value. There may be situations where xref::planning-and-tuning/execution-plans.adoc[Cypher query planning] can occur at a non-ideal time. For example, when a query must be as fast as possible and a valid plan is already in place. @@ -328,4 +328,4 @@ Avoiding the inference of multiple labels improves accuracy for nodes with sever // In general, inferring more information should improve the estimation and thereby the planner's decisions. // Should this not be the case, this setting provides the means to disable inference. -If this query option is not provided, then the value set in link:{neo4j-docs-base-uri}/operations-manual/{page-version}/configuration/configuration-settings/#config_dbms.cypher.infer_schema_parts[Operations Manual -> Configuration settings -> dbms.cypher.infer_schema_parts] will be used. +If this query option is not provided, then the value set in link:{neo4j-docs-base-uri}/operations-manual/current/configuration/configuration-settings/#config_dbms.cypher.infer_schema_parts[Operations Manual -> Configuration settings -> dbms.cypher.infer_schema_parts] will be used. diff --git a/modules/ROOT/pages/planning-and-tuning/runtimes/reference.adoc b/modules/ROOT/pages/planning-and-tuning/runtimes/reference.adoc index 0b8033ca1..9f6b492f4 100644 --- a/modules/ROOT/pages/planning-and-tuning/runtimes/reference.adoc +++ b/modules/ROOT/pages/planning-and-tuning/runtimes/reference.adoc @@ -27,7 +27,7 @@ For a full list of all available Cypher write clauses, see the xref:clauses/inde It is not possible to use the parallel runtime if a change has been made to the state of a transaction. -For example, the following transaction (initiated on link:{neo4j-docs-base-uri}/operations-manual/{page-version}/tools/cypher-shell[Cypher Shell]) will be rolled back, because executing a Cypher query will make changes to the state of a transaction. +For example, the following transaction (initiated on link:{neo4j-docs-base-uri}/operations-manual/current/tools/cypher-shell[Cypher Shell]) will be rolled back, because executing a Cypher query will make changes to the state of a transaction. .Step 1: Initiate a new transaction and change its state by creating a node [source, cypher, role=test-skip] @@ -49,7 +49,7 @@ RETURN 42 An error occurred while in an open transaction. The transaction will be rolled back and terminated. Error: The parallel runtime is not supported if there are changes in the transaction state. Use another runtime. ---- -For more information about transactions in Neo4j, see the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-internals/transaction-management[Operations Manual -> Transaction management]. +For more information about transactions in Neo4j, see the link:{neo4j-docs-base-uri}/operations-manual/current/database-internals/transaction-management[Operations Manual -> Transaction management]. [[configuration-settings]] == Configuration settings @@ -73,7 +73,7 @@ m| 0 Setting `server.cypher.parallel.worker_limit` to a negative number `-n` where `n` is greater than the total number of cores will disable the parallel runtime. -For more information about configuration settings in Neo4j, see the link:{neo4j-docs-base-uri}/operations-manual/{page-version}/configuration[Operations Manual -> Configuration.] +For more information about configuration settings in Neo4j, see the link:{neo4j-docs-base-uri}/operations-manual/current/configuration[Operations Manual -> Configuration.] [[aura]] == Aura @@ -103,7 +103,7 @@ Procedures and functions that read the database are supported by the parallel ru Apart from this, there are two categories of procedures and functions to keep in mind when using the parallel runtime. The first can be categorized as _updating procedures_. -These are procedures that update the graph with write queries, such as the Neo4j procedures link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_createlabel[db.createLabel] and link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_createproperty[db.createProperty]. +These are procedures that update the graph with write queries, such as the Neo4j procedures link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_db_createlabel[db.createLabel] and link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_db_createproperty[db.createProperty]. If such procedures are called in a query run on the parallel runtime, the query will fail. The second can be categorized as _non-thread-safe_ procedures and functions. @@ -129,66 +129,66 @@ Instead the query will automatically run on the pipelined runtime. | Procedure -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_awaitindex[db.awaitIndex] +| link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_db_awaitindex[db.awaitIndex] -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_awaitindexes[db.awaitIndexes] +| link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_db_awaitindexes[db.awaitIndexes] -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_checkpoint[db.checkpoint] +| link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_db_checkpoint[db.checkpoint] -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_info[db.info] +| link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_db_info[db.info] -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_labels[db.labels] +| link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_db_labels[db.labels] -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_listlocks[db.listLocks] +| link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_db_listlocks[db.listLocks] -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_ping[db.ping] +| link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_db_ping[db.ping] -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_propertykeys[db.propertyKeys] +| link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_db_propertykeys[db.propertyKeys] -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_prepareforreplanning[db.prepareForReplanning] +| link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_db_prepareforreplanning[db.prepareForReplanning] -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_relationshiptypes[db.relationshipTypes] +| link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_db_relationshiptypes[db.relationshipTypes] -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_resampleindex[db.resampleIndex] +| link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_db_resampleindex[db.resampleIndex] -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_resampleoutdatedindexes[db.resampleOutdatedIndexes] +| link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_db_resampleoutdatedindexes[db.resampleOutdatedIndexes] -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_schema_nodetypeproperties[db.schema.nodeTypeProperties] +| link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_db_schema_nodetypeproperties[db.schema.nodeTypeProperties] -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_schema_reltypeproperties[db.schema.relTypeProperties] +| link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_db_schema_reltypeproperties[db.schema.relTypeProperties] -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_db_schema_visualization[db.schema.visualization] +| link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_db_schema_visualization[db.schema.visualization] -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_dbms_checkconfigvalue[dbms.checkConfigValue] +| link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_dbms_checkconfigvalue[dbms.checkConfigValue] -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_dbms_listactivelocks[dbms.listActiveLocks] +| link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_dbms_listactivelocks[dbms.listActiveLocks] -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_dbms_listpools[dbms.listPools] +| link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_dbms_listpools[dbms.listPools] -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_dbms_scheduler_failedjobs[dbms.scheduler.failedJobs] +| link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_dbms_scheduler_failedjobs[dbms.scheduler.failedJobs] -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_dbms_scheduler_groups[dbms.scheduler.groups] +| link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_dbms_scheduler_groups[dbms.scheduler.groups] -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_dbms_scheduler_jobs[dbms.scheduler.jobs] +| link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_dbms_scheduler_jobs[dbms.scheduler.jobs] -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_dbms_upgrade[dbms.upgrade] +| link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_dbms_upgrade[dbms.upgrade] -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/reference/procedures/#procedure_dbms_upgradestatus[dbms.upgradeStatus] +| link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_dbms_upgradestatus[dbms.upgradeStatus] |=== [[apoc]] === APOC -The link:{neo4j-docs-base-uri}/apoc/{page-version}/[APOC library] contains procedures and functions which extend the use of Cypher. +The link:{neo4j-docs-base-uri}/apoc/current/[APOC library] contains procedures and functions which extend the use of Cypher. There are a number of APOC procedures and functions that are not considered thread-safe, and *cannot* be run on the parallel runtime. -For information about these, refer to the pages of the individual link:{neo4j-docs-base-uri}/apoc/{page-version}/overview/[procedures and functions] in the APOC Manual. +For information about these, refer to the pages of the individual link:{neo4j-docs-base-uri}/apoc/current/overview/[procedures and functions] in the APOC Manual. [[user-defined-functions]] === User-defined functions User-defined functions are simpler forms of procedures that return a single value and are read-only. -To learn more about user-defined functions in Neo4j, see the link:{neo4j-docs-base-uri}/java-reference/{page-version}/extending-neo4j/functions/[Java Reference Manual -> User-defined functions]. +To learn more about user-defined functions in Neo4j, see the link:{neo4j-docs-base-uri}/java-reference/current/extending-neo4j/functions/[Java Reference Manual -> User-defined functions]. Similar to Neo4j and APOC procedures, any user-defined function that starts a new transaction by executing a Cypher query is not considered thread-safe and will not be supported by the parallel runtime (this includes all user-defined aggregating functions). diff --git a/modules/ROOT/pages/query-caches/index.adoc b/modules/ROOT/pages/query-caches/index.adoc index fb2bde480..57cc4d906 100644 --- a/modules/ROOT/pages/query-caches/index.adoc +++ b/modules/ROOT/pages/query-caches/index.adoc @@ -16,7 +16,7 @@ For more information, see xref:query-caches/unified-query-caches.adoc[Unifying q == Configure caches The following is a summary of the query cache configurations. -For more information, see link:{neo4j-docs-base-uri}/operations-manual/{page-version}/configuration/configuration-settings/[Operations Manual -> Configuration settings]. +For more information, see link:{neo4j-docs-base-uri}/operations-manual/current/configuration/configuration-settings/[Operations Manual -> Configuration settings]. .Query cache configurations [options="header", width="100%", cols="4m,3a,1m"] @@ -25,15 +25,15 @@ For more information, see link:{neo4j-docs-base-uri}/operations-manual/{page-ver | Description | Default -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/configuration/configuration-settings/#config_server.memory.query_cache.sharing_enabled[server.memory.query_cache.sharing_enabled] +| link:{neo4j-docs-base-uri}/operations-manual/current/configuration/configuration-settings/#config_server.memory.query_cache.sharing_enabled[server.memory.query_cache.sharing_enabled] | label:enterprise-edition[Enterprise only] Enable sharing cache space between different databases. With this option turned on, databases will share cache space, but not cache entries. | false -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/configuration/configuration-settings/#config_server.memory.query_cache.shared_cache_num_entries[server.memory.query_cache.shared_cache_num_entries] +| link:{neo4j-docs-base-uri}/operations-manual/current/configuration/configuration-settings/#config_server.memory.query_cache.shared_cache_num_entries[server.memory.query_cache.shared_cache_num_entries] |label:enterprise-edition[Enterprise only] The number of cached queries for all databases. This setting is only deciding cache size when `server.memory.query_cache.sharing_enabled` is set to `true`. | 1000 -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/configuration/configuration-settings/#config_server.memory.query_cache.per_db_cache_num_entries[server.memory.query_cache.per_db_cache_num_entries] +| link:{neo4j-docs-base-uri}/operations-manual/current/configuration/configuration-settings/#config_server.memory.query_cache.per_db_cache_num_entries[server.memory.query_cache.per_db_cache_num_entries] | The number of cached queries per database. This setting is only deciding cache size when `server.memory.query_cache.sharing_enabled` is set to `false`. | 1000 diff --git a/modules/ROOT/pages/query-caches/unified-query-caches.adoc b/modules/ROOT/pages/query-caches/unified-query-caches.adoc index 74aa3f86a..20c7a1ca8 100644 --- a/modules/ROOT/pages/query-caches/unified-query-caches.adoc +++ b/modules/ROOT/pages/query-caches/unified-query-caches.adoc @@ -12,12 +12,12 @@ To enable the unified query caches, set the option `server.memory.query_cache.sh | Description | Default -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/configuration/configuration-settings/#config_server.memory.query_cache.sharing_enabled[server.memory.query_cache.sharing_enabled] +| link:{neo4j-docs-base-uri}/operations-manual/current/configuration/configuration-settings/#config_server.memory.query_cache.sharing_enabled[server.memory.query_cache.sharing_enabled] | label:enterprise-edition[Enterprise only] Enable sharing cache space between different databases. With this option turned on, databases will share cache space, but not cache entries. | false -| link:{neo4j-docs-base-uri}/operations-manual/{page-version}/configuration/configuration-settings/#config_server.memory.query_cache.shared_cache_num_entries[server.memory.query_cache.shared_cache_num_entries] +| link:{neo4j-docs-base-uri}/operations-manual/current/configuration/configuration-settings/#config_server.memory.query_cache.shared_cache_num_entries[server.memory.query_cache.shared_cache_num_entries] | label:enterprise-edition[Enterprise only] The number of cached queries for all databases. This setting is only deciding cache size when `server.memory.query_cache.sharing_enabled` is set to `true`. | 1000 diff --git a/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc b/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc index 6202cb5f8..c6f0e495d 100644 --- a/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc +++ b/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc @@ -215,7 +215,7 @@ For larger data sets, you might want to use larger batch sizes, such as `10000 R [[composite-databases]] == Composite databases -`CALL { ... } IN TRANSACTIONS` can be used with link:{neo4j-docs-base-uri}/operations-manual/{page-version}/composite-databases[composite databases]. +`CALL { ... } IN TRANSACTIONS` can be used with link:{neo4j-docs-base-uri}/operations-manual/current/composite-databases[composite databases]. Even though composite databases allow accessing multiple graphs in a single query, only one graph can be modified in a single transaction. `CALL { ... } IN TRANSACTIONS` offers a way of constructing queries which modify multiple graphs. @@ -655,7 +655,7 @@ Use the xref:subqueries/subqueries-in-transactions.adoc#status-report[status rep When a write transaction occurs, Neo4j takes locks to preserve data consistency while updating. For example, when creating or deleting a relationship, a write lock is taken on both the specific relationship and its connected nodes. -A deadlock happens when two transactions are blocked by each other because they are attempting to concurrently modify a node or a relationship that is locked by the other transaction (for more information about locks and deadlocks in Neo4j, see link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-internals/concurrent-data-access/#_locks[Operations Manual -> Concurrent data access]. +A deadlock happens when two transactions are blocked by each other because they are attempting to concurrently modify a node or a relationship that is locked by the other transaction (for more information about locks and deadlocks in Neo4j, see link:{neo4j-docs-base-uri}/operations-manual/current/database-internals/concurrent-data-access/#_locks[Operations Manual -> Concurrent data access]. A deadlock may occur when using `CALL { ... } IN CONCURRENT TRANSACTIONS` if the transactions for two or more batches try to take the same locks in an order that results in a circular dependency between them. If so, the impacted transactions are always rolled back, and an error is thrown unless the query is appended with `ON ERROR CONTINUE` or `ON ERROR BREAK`. diff --git a/modules/ROOT/pages/syntax/naming.adoc b/modules/ROOT/pages/syntax/naming.adoc index 6960d1491..23108b2f3 100644 --- a/modules/ROOT/pages/syntax/naming.adoc +++ b/modules/ROOT/pages/syntax/naming.adoc @@ -69,7 +69,7 @@ Here are the recommended naming conventions: [[identifier-length-limit]] == Length limit of identifiers -Neo4j's link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-internals/store-formats/#store-format-overview[block format] implements xref:appendix/gql-conformance/index.adoc[GQL's] limit on the maximum length of identifiers. +Neo4j's link:{neo4j-docs-base-uri}/operations-manual/current/database-internals/store-formats/#store-format-overview[block format] implements xref:appendix/gql-conformance/index.adoc[GQL's] limit on the maximum length of identifiers. The maximum limit is set to 16,383 characters in an identifier. This means that node labels, relationship types, and property keys cannot include more than 16,383 characters. diff --git a/modules/ROOT/pages/syntax/parameters.adoc b/modules/ROOT/pages/syntax/parameters.adoc index 9c6920570..f31186f4f 100644 --- a/modules/ROOT/pages/syntax/parameters.adoc +++ b/modules/ROOT/pages/syntax/parameters.adoc @@ -32,11 +32,11 @@ Setting parameters when running a query is dependent on the client environment. For example: * To set a parameter in Cypher Shell use `+:param name => 'Joe'+`. - For more information refer to link:{neo4j-docs-base-uri}/operations-manual/{page-version}/tools/cypher-shell#cypher-shell-parameters[Operations Manual -> Cypher Shell - Query Parameters]. + For more information refer to link:{neo4j-docs-base-uri}/operations-manual/current/tools/cypher-shell#cypher-shell-parameters[Operations Manual -> Cypher Shell - Query Parameters]. * For Neo4j Browser use the same syntax as Cypher Shell, `+:param name => 'Joe'+`. * When using drivers, the syntax is dependent on the language choice. See the examples in _Transactions_ in the link:{docs-base-uri}[Neo4j Driver manuals]. -* For usage via the Neo4j HTTP API, see the link:{neo4j-docs-base-uri}/http-api/{page-version}/index#http-api[HTTP API documentation]. +* For usage via the Neo4j HTTP API, see the link:{neo4j-docs-base-uri}/http-api/current/index#http-api[HTTP API documentation]. We provide below a comprehensive list of examples of parameter usage. In these examples, parameters are given in JSON; the exact manner in which they are to be submitted depends upon the driver being used. diff --git a/modules/ROOT/pages/values-and-types/maps.adoc b/modules/ROOT/pages/values-and-types/maps.adoc index 8d50aae27..a3e005a04 100644 --- a/modules/ROOT/pages/values-and-types/maps.adoc +++ b/modules/ROOT/pages/values-and-types/maps.adoc @@ -17,7 +17,7 @@ The behavior of the `[]` operator with respect to `null` is detailed xref::value == Literal maps The key names in a map must be literals. -If returned through an link:{neo4j-docs-base-uri}/http-api/{page-version}[HTTP API call], a JSON object will be returned. +If returned through an link:{neo4j-docs-base-uri}/http-api/current[HTTP API call], a JSON object will be returned. If returned in Java, an object of type `java.util.Map` will be returned. diff --git a/modules/ROOT/pages/values-and-types/temporal.adoc b/modules/ROOT/pages/values-and-types/temporal.adoc index 1c514ccad..96ca806ee 100644 --- a/modules/ROOT/pages/values-and-types/temporal.adoc +++ b/modules/ROOT/pages/values-and-types/temporal.adoc @@ -62,7 +62,7 @@ See xref::values-and-types/temporal.adoc#cypher-temporal-specify-time-zone[speci The named time zone form uses the rules of the IANA time zone database to manage _daylight savings time_ (DST). -The default time zone of the database can be configured using the configuration option link:{neo4j-docs-base-uri}/operations-manual/{page-version}/configuration/configuration-settings#config_db.temporal.timezone[`db.temporal.timezone`]. +The default time zone of the database can be configured using the configuration option link:{neo4j-docs-base-uri}/operations-manual/current/configuration/configuration-settings#config_db.temporal.timezone[`db.temporal.timezone`]. This configuration option influences the creation of temporal types for the following functions: * Getting the current date and time without specifying a time zone. From ef1b7bed8899f50317dbd45db1ec9020f3007d8e Mon Sep 17 00:00:00 2001 From: Hannes Voigt <30618026+hvub@users.noreply.github.com> Date: Mon, 13 Jan 2025 11:26:09 +0100 Subject: [PATCH 64/77] Keyword priority (#1130) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Docs update regarding https://github.com/neo-technology/neo4j/pull/28493 (plus a little clarification w.r.t. variable scope in subqueries). --------- Co-authored-by: Richard Sill <156673635+rsill-neo4j@users.noreply.github.com> Co-authored-by: Jens Pryce-Åklundh <112686610+JPryce-Aklundh@users.noreply.github.com> --- modules/ROOT/content-nav.adoc | 2 +- .../unsupported-mandatory.adoc | 2 +- modules/ROOT/pages/syntax/index.adoc | 2 +- modules/ROOT/pages/syntax/keywords.adoc | 394 ++++++++++++++++++ modules/ROOT/pages/syntax/reserved.adoc | 117 ------ modules/ROOT/pages/syntax/variables.adoc | 8 +- 6 files changed, 404 insertions(+), 121 deletions(-) create mode 100644 modules/ROOT/pages/syntax/keywords.adoc delete mode 100644 modules/ROOT/pages/syntax/reserved.adoc diff --git a/modules/ROOT/content-nav.adoc b/modules/ROOT/content-nav.adoc index 35d451b4d..d6ea0bd0d 100644 --- a/modules/ROOT/content-nav.adoc +++ b/modules/ROOT/content-nav.adoc @@ -116,7 +116,7 @@ ** xref:syntax/parsing.adoc[] ** xref:syntax/naming.adoc[] ** xref:syntax/variables.adoc[] -** xref:syntax/reserved.adoc[] +** xref:syntax/keywords.adoc[] ** xref:syntax/parameters.adoc[] ** xref:syntax/operators.adoc[] ** xref:syntax/comments.adoc[] diff --git a/modules/ROOT/pages/appendix/gql-conformance/unsupported-mandatory.adoc b/modules/ROOT/pages/appendix/gql-conformance/unsupported-mandatory.adoc index 12f5fca56..c81f453a5 100644 --- a/modules/ROOT/pages/appendix/gql-conformance/unsupported-mandatory.adoc +++ b/modules/ROOT/pages/appendix/gql-conformance/unsupported-mandatory.adoc @@ -41,5 +41,5 @@ Cypher Shell also offers specific link:{neo4j-docs-base-uri}/operations-manual/c | 21.3 | , , and | GQL specifies a list of link:https://standards.iso.org/iso-iec/39075/ed-1/en/ISO_IEC_39075(en).bnf.txt[reserved words] that cannot be used for unquoted variable names, labels, and property names. -Cypher also specifies a list of xref:syntax/reserved.adoc[reserved keywords], but it differs from GQL's. +Cypher also specifies a list of xref:syntax/keywords.adoc[reserved keywords], but it differs from GQL's. |=== \ No newline at end of file diff --git a/modules/ROOT/pages/syntax/index.adoc b/modules/ROOT/pages/syntax/index.adoc index 498839606..04a664be0 100644 --- a/modules/ROOT/pages/syntax/index.adoc +++ b/modules/ROOT/pages/syntax/index.adoc @@ -8,7 +8,7 @@ Further information can be found in the following sections: * xref::syntax/parsing.adoc[Parsing] * xref::syntax/naming.adoc[Naming rules and recommendations] * xref::syntax/variables.adoc[Variables] -* xref::syntax/reserved.adoc[Reserved keywords] +* xref::syntax/keywords.adoc[Keywords] * xref::syntax/parameters.adoc[Parameters] * xref::syntax/operators.adoc[Operators] * xref::syntax/comments.adoc[Comments] diff --git a/modules/ROOT/pages/syntax/keywords.adoc b/modules/ROOT/pages/syntax/keywords.adoc new file mode 100644 index 000000000..aafb711f2 --- /dev/null +++ b/modules/ROOT/pages/syntax/keywords.adoc @@ -0,0 +1,394 @@ +:description: This section contains a list of reserved keywords in Cypher. + +[[cypher-keywords]] += Keywords + +Keywords are words with a predefined meaning in Cypher. + +Keywords are not recommended to be used as identifiers in the following contexts: + +* Variables +* Labels +* Relationship types +* Function names +* Procedure names + +If a snippet of Cypher can both be a keyword and an unquoted identifier, it is interpreted as a keyword. + +For instance in the following, `true` could be the variable `true` or the Boolean literal value `true`. Since `true` is a keyword, the query returns a single Boolean `true` value. + +.Query +[source, cypher, role=test-result-skip] +---- +WITH 123 AS true +RETURN true AS x +---- + +.Result +[role="queryresult",options="header,footer",cols="1* Date: Tue, 14 Jan 2025 09:52:05 +0100 Subject: [PATCH 65/77] clairfy Yield (#1159) --- modules/ROOT/pages/clauses/call.adoc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/ROOT/pages/clauses/call.adoc b/modules/ROOT/pages/clauses/call.adoc index 3001023a0..caa311fca 100644 --- a/modules/ROOT/pages/clauses/call.adoc +++ b/modules/ROOT/pages/clauses/call.adoc @@ -189,6 +189,8 @@ CALL db.labels() YIELD * If the procedure has deprecated return columns, those columns are also returned. Note that `YIELD *` is only valid in standalone procedure calls. +Variables must be explicitly named in a `YIELD` clause if other clauses than a single procedure `CALL` are present. +This restriction simplifies query logic and protects against output variables from the procedure accidentally clashing with other query variables. For example, the following is not valid: .Not allowed @@ -204,7 +206,7 @@ RETURN count(*) AS results ==== `YIELD` can be used to filter for specific results. -This requires knowing the names of the arguments within a procedure's signature, which can either be found in the link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/[Operations Manual -> Procedures] or returned by a `SHOW PROCEDURES` query. +This requires knowing the names of the arguments within a procedure's signature, which can either be found in the link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/[Operations Manual -> Procedures] or in the `signature` column returned by a `SHOW PROCEDURES` command (see example below). .Find the argument names of `db.propertyKeys` [source, cypher] From 56dcdcc5c2eaea55ad1d65acef3adfdc8d34a6c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Tue, 14 Jan 2025 11:42:12 +0100 Subject: [PATCH 66/77] Alias to new keywords page (#1160) --- modules/ROOT/pages/syntax/keywords.adoc | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/ROOT/pages/syntax/keywords.adoc b/modules/ROOT/pages/syntax/keywords.adoc index aafb711f2..4e7a24477 100644 --- a/modules/ROOT/pages/syntax/keywords.adoc +++ b/modules/ROOT/pages/syntax/keywords.adoc @@ -1,4 +1,5 @@ :description: This section contains a list of reserved keywords in Cypher. +:page-aliases: syntax/reserved.adoc [[cypher-keywords]] = Keywords From cea05463a7271602c8425fe7c79dfdc46e34ec4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Wed, 15 Jan 2025 11:30:15 +0100 Subject: [PATCH 67/77] Property type rephrase (#1163) --- .../pages/values-and-types/property-structural-constructed.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ROOT/pages/values-and-types/property-structural-constructed.adoc b/modules/ROOT/pages/values-and-types/property-structural-constructed.adoc index 10756b55d..cf097a282 100644 --- a/modules/ROOT/pages/values-and-types/property-structural-constructed.adoc +++ b/modules/ROOT/pages/values-and-types/property-structural-constructed.adoc @@ -13,7 +13,7 @@ This section will first provide a brief overview of each type, and then go into A property type value is one that can be stored as a node or relationship property. -The following data types are included in the property types category: `BOOLEAN`, `DATE`, `DURATION`, `FLOAT`, `INTEGER`, `LIST`, `LOCAL DATETIME`, `LOCAL TIME`, `POINT`, `STRING`, `ZONED DATETIME`, and `ZONED TIME`. +Property types are the most primitive types in Cypher and include the following: `BOOLEAN`, `DATE`, `DURATION`, `FLOAT`, `INTEGER`, `LIST`, `LOCAL DATETIME`, `LOCAL TIME`, `POINT`, `STRING`, `ZONED DATETIME`, and `ZONED TIME`. * Property types can be returned from Cypher queries. * Property types can be used as xref::syntax/parameters.adoc[parameters]. From c3eb5f69c5b8c1d4a6256e0a7c5bb90a2bb5ce48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Thu, 16 Jan 2025 08:58:38 +0100 Subject: [PATCH 68/77] Fix failing query plans (#1166) --- .../operators/operators-detail.adoc | 236 +++++++++--------- 1 file changed, 123 insertions(+), 113 deletions(-) diff --git a/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc b/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc index 128729768..075335dd6 100644 --- a/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc +++ b/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc @@ -4093,30 +4093,32 @@ Runtime version {neo4j-version} Batch size 128 -+------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | 0 | me, friend | 2 | 34 | 136 | 0 | | | | -| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +Filter | 1 | friend:Person | 2 | 34 | 68 | | | | | -| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +NullifyMetadata | 9 | | 2 | 34 | 0 | | | | | -| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +Repeat(Trail) | 2 | (me) (...){1, 2} (friend) | 2 | 34 | 0 | 29792 | 0/0 | 1.696 | Fused in Pipeline 2 | -| |\ +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| | +Filter | 3 | NOT anon_5 = anon_3 AND (NOT cache[a.name] = cache[c.name] AND NOT cache[b.name] = cache[c.name]) AN | 1 | 34 | 92 | | | | | -| | | | | D isRepeatTrailUnique(anon_5) | | | | | | | | -| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +Expand(All) | 4 | (b)-[anon_5:FRIENDS_WITH]-(c) | 3 | 92 | 138 | | | | | -| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +Filter | 5 | NOT cache[a.name] = cache[b.name] AND isRepeatTrailUnique(anon_3) | 5 | 46 | 198 | | | | | -| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +Expand(All) | 6 | (a)-[anon_3:FRIENDS_WITH]-(b) | 10 | 66 | 100 | | | | | -| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +Argument | 7 | a | 15 | 34 | 0 | 15672 | 2/0 | 3.245 | Fused in Pipeline 1 | -| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +NodeByLabelScan | 8 | me:Person | 14 | 14 | 15 | 376 | 1/0 | 0.107 | In Pipeline 0 | -+------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++--------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++--------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | me, friend | 3 | 34 | 136 | 0 | | | | +| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +Filter | 1 | friend:Person | 3 | 34 | 68 | | | | | +| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +NullifyMetadata | 10 | | 3 | 34 | 0 | | | | | +| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +Repeat(Trail) | 2 | (me) (...){1, 2} (friend) | 3 | 34 | 0 | 30000 | 0/0 | 5.379 | Fused in Pipeline 2 | +| |\ +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| | +Filter | 3 | NOT anon_5 = anon_3 AND (NOT cache[a.name] = cache[c.name] AND NOT cache[b.name] = cache[c.name]) AN | 6 | 34 | 92 | | | | | +| | | | | D isRepeatTrailUnique(anon_5) | | | | | | | | +| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Expand(All) | 4 | (b)-[anon_5:FRIENDS_WITH]-(c) | 26 | 92 | 138 | | | | | +| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Filter | 5 | NOT cache[a.name] = cache[b.name] AND isRepeatTrailUnique(anon_3) | 15 | 46 | 132 | | | | | +| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Expand(All) | 6 | (a)-[anon_3:FRIENDS_WITH]-(b) | 31 | 66 | 100 | | | | | +| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +CacheProperties | 7 | cache[a.name] | 18 | 34 | 68 | | | | | +| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Argument | 8 | a | 18 | 34 | 0 | 15880 | 2/0 | 5.556 | Fused in Pipeline 1 | +| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +NodeByLabelScan | 9 | me:Person | 14 | 14 | 15 | 376 | 1/0 | 0.727 | In Pipeline 0 | ++--------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ Total database accesses: 747, total allocated memory: 45832 ---- @@ -4152,30 +4154,32 @@ Runtime version {neo4j-version} Batch size 128 -+------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | 0 | me, friend | 2 | 34 | 136 | 0 | | | | -| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +Filter | 1 | friend:Person | 2 | 34 | 68 | | | | | -| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +NullifyMetadata | 9 | | 2 | 34 | 0 | | | | | -| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +Repeat(Trail) | 2 | (me) (...){1, 2} (friend) | 2 | 34 | 0 | 29792 | 0/0 | 1.696 | Fused in Pipeline 2 | -| |\ +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| | +Filter | 3 | NOT anon_5 = anon_3 AND (NOT cache[a.name] = cache[c.name] AND NOT cache[b.name] = cache[c.name]) AN | 1 | 34 | 92 | | | | | -| | | | | D isRepeatTrailUnique(anon_5) | | | | | | | | -| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +Expand(All) | 4 | (b)-[anon_5:FRIENDS_WITH]-(c) | 3 | 92 | 138 | | | | | -| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +Filter | 5 | NOT cache[a.name] = cache[b.name] AND isRepeatTrailUnique(anon_3) | 5 | 46 | 198 | | | | | -| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +Expand(All) | 6 | (a)-[anon_3:FRIENDS_WITH]-(b) | 10 | 66 | 100 | | | | | -| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +Argument | 7 | a | 15 | 34 | 0 | 15672 | 2/0 | 3.245 | Fused in Pipeline 1 | -| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +NodeByLabelScan | 8 | me:Person | 14 | 14 | 15 | 376 | 1/0 | 0.107 | In Pipeline 0 | -+------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++--------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++--------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | me, friend | 3 | 34 | 136 | 0 | | | | +| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +Filter | 1 | friend:Person | 3 | 34 | 68 | | | | | +| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +NullifyMetadata | 10 | | 3 | 34 | 0 | | | | | +| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +Repeat(Trail) | 2 | (me) (...){1, 2} (friend) | 3 | 34 | 0 | 30000 | 0/0 | 5.379 | Fused in Pipeline 2 | +| |\ +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| | +Filter | 3 | NOT anon_5 = anon_3 AND (NOT cache[a.name] = cache[c.name] AND NOT cache[b.name] = cache[c.name]) AN | 6 | 34 | 92 | | | | | +| | | | | D isRepeatTrailUnique(anon_5) | | | | | | | | +| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Expand(All) | 4 | (b)-[anon_5:FRIENDS_WITH]-(c) | 26 | 92 | 138 | | | | | +| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Filter | 5 | NOT cache[a.name] = cache[b.name] AND isRepeatTrailUnique(anon_3) | 15 | 46 | 132 | | | | | +| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Expand(All) | 6 | (a)-[anon_3:FRIENDS_WITH]-(b) | 31 | 66 | 100 | | | | | +| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +CacheProperties | 7 | cache[a.name] | 18 | 34 | 68 | | | | | +| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Argument | 8 | a | 18 | 34 | 0 | 15880 | 2/0 | 5.556 | Fused in Pipeline 1 | +| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +NodeByLabelScan | 9 | me:Person | 14 | 14 | 15 | 376 | 1/0 | 0.727 | In Pipeline 0 | ++--------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ Total database accesses: 747, total allocated memory: 45832 ---- @@ -4379,25 +4383,27 @@ Runtime SLOTTED Runtime version {neo4j-version} -+-------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | -+-------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+ -| +ProduceResults | 0 | `other.name` | 15 | 24 | 0 | 0 | 0/0 | -| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ -| +Projection | 1 | other.name AS `other.name` | 15 | 24 | 24 | | 0/0 | -| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ -| +Filter | 2 | NOT anon_2 = anon_0 | 15 | 24 | 0 | | 0/0 | -| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ -| +TriadicSelection | 3 | WHERE NOT (me)--(other) | 15 | 48 | 0 | | 0/0 | -| |\ +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ -| | +Expand(All) | 4 | (anon_1)-[anon_2:FRIENDS_WITH]-(other) | 16 | 48 | 72 | | 0/0 | -| | | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ -| | +Argument | 5 | anon_1, anon_0 | 24 | 24 | 0 | | 0/0 | -| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ -| +Expand(All) | 6 | (me)-[anon_0:FRIENDS_WITH]-(anon_1) | 24 | 24 | 38 | | 2/0 | -| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ -| +NodeByLabelScan | 7 | me:Person | 14 | 14 | 15 | | 1/0 | -+-------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+ ++--------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | ++--------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+ +| +ProduceResults | 0 | `other.name` | 35 | 24 | 0 | 0 | 0/0 | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ +| +Projection | 1 | cache[other.name] AS `other.name` | 35 | 24 | 0 | | 0/0 | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ +| +TriadicSelection | 2 | WHERE NOT (me)--(other) | 35 | 24 | 0 | | 0/0 | +| |\ +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ +| | +CacheProperties | 3 | cache[other.name] | 16 | 24 | 24 | | 0/0 | +| | | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ +| | +Filter | 4 | NOT anon_2 = anon_0 | 16 | 24 | 0 | | 0/0 | +| | | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ +| | +Expand(All) | 5 | (anon_1)-[anon_2:FRIENDS_WITH]-(other) | 16 | 48 | 72 | | 0/0 | +| | | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ +| | +Argument | 6 | anon_1, anon_0 | 24 | 24 | 0 | | 0/0 | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ +| +Expand(All) | 7 | (me)-[anon_0:FRIENDS_WITH]-(anon_1) | 24 | 24 | 38 | | 2/0 | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ +| +NodeByLabelScan | 8 | me:Person | 14 | 14 | 15 | | 1/0 | ++--------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+ Total database accesses: 246, total allocated memory: 64 ---- @@ -4438,29 +4444,31 @@ Runtime version {neo4j-version} Batch size 128 -+------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | 0 | `other.name` | 15 | 24 | 0 | 0 | 0/0 | 0.230 | | -| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | -| +Projection | 1 | other.name AS `other.name` | 15 | 24 | 48 | | 0/0 | 0.424 | | -| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | -| +Filter | 2 | NOT anon_2 = anon_0 | 15 | 24 | 0 | | 0/0 | 0.731 | | -| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | -| +TriadicFilter | 10 | WHERE NOT (me)--(other) | 15 | 48 | 0 | 7216 | 0/0 | 0.690 | In Pipeline 3 | -| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +Apply | 9 | | 16 | 48 | 0 | | 0/0 | | | -| |\ +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| | +Expand(All) | 4 | (anon_1)-[anon_2:FRIENDS_WITH]-(other) | 16 | 48 | 72 | | | | | -| | | +----+----------------------------------------+----------------+------+---------+----------------+ | | | -| | +Argument | 5 | anon_1, anon_0 | 24 | 24 | 0 | 4464 | 0/0 | 1.143 | Fused in Pipeline 2 | -| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +TriadicBuild | 8 | (me)--(anon_1) | 24 | 24 | 0 | 1080 | 0/0 | 5.317 | In Pipeline 1 | -| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +Expand(All) | 6 | (me)-[anon_0:FRIENDS_WITH]-(anon_1) | 24 | 24 | 38 | | | | | -| | +----+----------------------------------------+----------------+------+---------+----------------+ | | | -| +NodeByLabelScan | 7 | me:Person | 14 | 14 | 15 | 376 | 3/0 | 2.444 | Fused in Pipeline 0 | -+------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++--------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++--------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | `other.name` | 35 | 24 | 0 | 0 | 0/0 | 0.180 | | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | +| +Projection | 1 | cache[other.name] AS `other.name` | 35 | 24 | 0 | | 0/0 | 0.064 | | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | +| +TriadicFilter | 11 | WHERE NOT (me)--(other) | 35 | 24 | 0 | 7512 | 0/0 | 0.303 | In Pipeline 3 | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +Apply | 10 | | 16 | 24 | 0 | | 0/0 | | | +| |\ +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| | +CacheProperties | 3 | cache[other.name] | 16 | 24 | 48 | | | | | +| | | +----+----------------------------------------+----------------+------+---------+----------------+ | | | +| | +Filter | 4 | NOT anon_2 = anon_0 | 16 | 24 | 0 | | | | | +| | | +----+----------------------------------------+----------------+------+---------+----------------+ | | | +| | +Expand(All) | 5 | (anon_1)-[anon_2:FRIENDS_WITH]-(other) | 16 | 48 | 72 | | | | | +| | | +----+----------------------------------------+----------------+------+---------+----------------+ | | | +| | +Argument | 6 | anon_1, anon_0 | 24 | 24 | 0 | 4464 | 0/0 | 0.575 | Fused in Pipeline 2 | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +TriadicBuild | 9 | (me)--(anon_1) | 24 | 24 | 0 | 1080 | 0/0 | 1.608 | In Pipeline 1 | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +Expand(All) | 7 | (me)-[anon_0:FRIENDS_WITH]-(anon_1) | 24 | 24 | 38 | | | | | +| | +----+----------------------------------------+----------------+------+---------+----------------+ | | | +| +NodeByLabelScan | 8 | me:Person | 14 | 14 | 15 | 376 | 3/0 | 0.559 | Fused in Pipeline 0 | ++--------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ Total database accesses: 256, total allocated memory: 7376 ---- @@ -4501,29 +4509,31 @@ Runtime version {neo4j-version} Batch size 128 -+------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | 0 | `other.name` | 15 | 24 | 0 | 0 | 0/0 | 0.460 | | -| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | -| +Projection | 1 | other.name AS `other.name` | 15 | 24 | 48 | | 0/0 | 0.437 | | -| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | -| +Filter | 2 | NOT anon_2 = anon_0 | 15 | 24 | 0 | | 0/0 | 0.377 | | -| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | -| +TriadicFilter | 10 | WHERE NOT (me)--(other) | 15 | 48 | 0 | 7216 | 0/0 | 0.337 | In Pipeline 3 | -| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +Apply | 9 | | 16 | 48 | 0 | | 0/0 | | | -| |\ +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| | +Expand(All) | 4 | (anon_1)-[anon_2:FRIENDS_WITH]-(other) | 16 | 48 | 72 | | | | | -| | | +----+----------------------------------------+----------------+------+---------+----------------+ | | | -| | +Argument | 5 | anon_1, anon_0 | 24 | 24 | 0 | 4464 | 0/0 | 0.608 | Fused in Pipeline 2 | -| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +TriadicBuild | 8 | (me)--(anon_1) | 24 | 24 | 0 | 1080 | 0/0 | 0.540 | In Pipeline 1 | -| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +Expand(All) | 6 | (me)-[anon_0:FRIENDS_WITH]-(anon_1) | 24 | 24 | 38 | | | | | -| | +----+----------------------------------------+----------------+------+---------+----------------+ | | | -| +NodeByLabelScan | 7 | me:Person | 14 | 14 | 15 | 376 | 3/0 | 0.459 | Fused in Pipeline 0 | -+------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++--------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++--------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | `other.name` | 35 | 24 | 0 | 0 | 0/0 | 0.198 | | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | +| +Projection | 1 | cache[other.name] AS `other.name` | 35 | 24 | 0 | | 0/0 | 0.095 | | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | +| +TriadicFilter | 11 | WHERE NOT (me)--(other) | 35 | 24 | 0 | 7512 | 0/0 | 0.176 | In Pipeline 3 | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +Apply | 10 | | 16 | 24 | 0 | | 0/0 | | | +| |\ +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| | +CacheProperties | 3 | cache[other.name] | 16 | 24 | 48 | | | | | +| | | +----+----------------------------------------+----------------+------+---------+----------------+ | | | +| | +Filter | 4 | NOT anon_2 = anon_0 | 16 | 24 | 0 | | | | | +| | | +----+----------------------------------------+----------------+------+---------+----------------+ | | | +| | +Expand(All) | 5 | (anon_1)-[anon_2:FRIENDS_WITH]-(other) | 16 | 48 | 72 | | | | | +| | | +----+----------------------------------------+----------------+------+---------+----------------+ | | | +| | +Argument | 6 | anon_1, anon_0 | 24 | 24 | 0 | 4464 | 0/0 | 0.990 | Fused in Pipeline 2 | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +TriadicBuild | 9 | (me)--(anon_1) | 24 | 24 | 0 | 1080 | 0/0 | 0.304 | In Pipeline 1 | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +Expand(All) | 7 | (me)-[anon_0:FRIENDS_WITH]-(anon_1) | 24 | 24 | 38 | | | | | +| | +----+----------------------------------------+----------------+------+---------+----------------+ | | | +| +NodeByLabelScan | 8 | me:Person | 14 | 14 | 15 | 376 | 3/0 | 0.399 | Fused in Pipeline 0 | ++--------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ Total database accesses: 256, total allocated memory: 7376 ---- From cbd3de0210aa6ebc18979011517d92c52d645f0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Thu, 16 Jan 2025 09:55:50 +0100 Subject: [PATCH 69/77] Cypher 25 antora cherry-picks (#1164, 1167, 1168) (#1169) Co-authored-by: Neil Dewhurst --- antora.yml | 3 +- modules/ROOT/pages/clauses/call.adoc | 6 +- modules/ROOT/pages/clauses/where.adoc | 2 +- modules/ROOT/pages/functions/aggregating.adoc | 2 +- .../operators/operators-detail.adoc | 172 +++++++++--------- modules/ROOT/pages/syntax/operators.adoc | 4 +- .../ROOT/pages/values-and-types/temporal.adoc | 1 - preview.yml | 7 - publish.yml | 7 - 9 files changed, 94 insertions(+), 110 deletions(-) diff --git a/antora.yml b/antora.yml index a09f496d9..000887c71 100644 --- a/antora.yml +++ b/antora.yml @@ -6,5 +6,4 @@ nav: - modules/ROOT/content-nav.adoc asciidoc: attributes: - neo4j-version: '2025.01' - neo4j-version-minor: '2025.01.00' + neo4j-version: '2025.02' diff --git a/modules/ROOT/pages/clauses/call.adoc b/modules/ROOT/pages/clauses/call.adoc index caa311fca..8c2b32451 100644 --- a/modules/ROOT/pages/clauses/call.adoc +++ b/modules/ROOT/pages/clauses/call.adoc @@ -86,7 +86,7 @@ CALL dbms.checkConfigValue('server.bolt.enabled', 'true') | "valid" | "message" | true | "requires restart" -1+d|Rows: 2 +2+d|Rows: 2 |=== ==== @@ -118,7 +118,7 @@ CALL dbms.checkConfigValue($setting, $value) | "valid" | "message" | true | "requires restart" -1+d|Rows: 2 +2+d|Rows: 2 |=== [NOTE] @@ -153,7 +153,7 @@ CALL dbms.checkConfigValue($setting, 'true') | "valid" | "message" | true | "requires restart" -1+d|Rows: 2 +2+d|Rows: 2 |=== ==== diff --git a/modules/ROOT/pages/clauses/where.adoc b/modules/ROOT/pages/clauses/where.adoc index e7b30e0ac..0ecf72c39 100644 --- a/modules/ROOT/pages/clauses/where.adoc +++ b/modules/ROOT/pages/clauses/where.adoc @@ -368,7 +368,7 @@ For more information, see the section about the xref:syntax/operators.adoc#match | 'Andy' | 'Timothy' | 'Peter' -2+|Rows: 1 +1+|Rows: 3 |=== Note that the `IS NORMALIZED` operator returns `null` when used on a non-`STRING` value. diff --git a/modules/ROOT/pages/functions/aggregating.adoc b/modules/ROOT/pages/functions/aggregating.adoc index c4d07085b..d90fd3c19 100644 --- a/modules/ROOT/pages/functions/aggregating.adoc +++ b/modules/ROOT/pages/functions/aggregating.adoc @@ -312,7 +312,7 @@ The `Guy Pearce` node will, therefore, get counted twice when not using `DISTINC | friendOfFriend.name | count(friendOfFriend) | count(ALL friendOfFriend) | count(DISTINCT friendOfFriend) | "Guy Pearce" | 2 | 2 | 1 -2+d|Rows: 1 +4+d|Rows: 1 |=== diff --git a/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc b/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc index 075335dd6..875acb6a5 100644 --- a/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc +++ b/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc @@ -299,7 +299,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -341,7 +341,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -383,7 +383,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -424,7 +424,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -463,7 +463,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -504,7 +504,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -553,7 +553,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -597,7 +597,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -647,7 +647,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -690,7 +690,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -732,7 +732,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -774,7 +774,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1276,7 +1276,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1315,7 +1315,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1357,7 +1357,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1400,7 +1400,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1440,7 +1440,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1482,7 +1482,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1527,7 +1527,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1573,7 +1573,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1618,7 +1618,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1663,7 +1663,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1713,7 +1713,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1756,7 +1756,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1798,7 +1798,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1841,7 +1841,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1892,7 +1892,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1936,7 +1936,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1980,7 +1980,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2024,7 +2024,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2068,7 +2068,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2111,7 +2111,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2155,7 +2155,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2199,7 +2199,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2242,7 +2242,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2284,7 +2284,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2327,7 +2327,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2370,7 +2370,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2421,7 +2421,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2466,7 +2466,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2512,7 +2512,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2557,7 +2557,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3191,7 +3191,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3352,7 +3352,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3410,7 +3410,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3469,7 +3469,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3522,7 +3522,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3587,7 +3587,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3648,7 +3648,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4320,7 +4320,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4636,7 +4636,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4688,7 +4688,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4735,7 +4735,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4780,7 +4780,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4825,7 +4825,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4869,7 +4869,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4911,7 +4911,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4953,7 +4953,7 @@ Planner COST Runtime SLOTTED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +-----------------+--------------------------------------+----------------+------+---------+------------------------+ | Operator | Details | Estimated Rows | Rows | DB Hits | Page Cache Hits/Misses | @@ -5006,7 +5006,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5055,7 +5055,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5098,7 +5098,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5151,7 +5151,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5201,7 +5201,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5244,7 +5244,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5286,7 +5286,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5328,7 +5328,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5377,7 +5377,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5426,7 +5426,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5474,7 +5474,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5525,7 +5525,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5570,7 +5570,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5617,7 +5617,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5663,7 +5663,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5718,7 +5718,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5762,7 +5762,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5808,7 +5808,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5859,7 +5859,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5906,7 +5906,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -6060,7 +6060,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -6108,7 +6108,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -6153,7 +6153,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -6198,7 +6198,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -6243,7 +6243,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -6289,7 +6289,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -6333,7 +6333,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -6380,7 +6380,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 diff --git a/modules/ROOT/pages/syntax/operators.adoc b/modules/ROOT/pages/syntax/operators.adoc index e1b523052..362982f21 100644 --- a/modules/ROOT/pages/syntax/operators.adoc +++ b/modules/ROOT/pages/syntax/operators.adoc @@ -605,7 +605,7 @@ RETURN "the \u212B char" IS NORMALIZED AS normalized |=== | normalized | false -2+|Rows: 1 +1+|Rows: 1 |=== Because the given `STRING` contains a non-normalized Unicode character (`\u212B`), `false` is returned. @@ -632,7 +632,7 @@ RETURN "the \u212B char" IS NOT NORMALIZED AS notNormalized |=== | notNormalized | true -2+|Rows: 1 +1+|Rows: 1 |=== Because the given `STRING` contains a non-normalized Unicode character (`\u212B`), and is not normalized, `true` is returned. diff --git a/modules/ROOT/pages/values-and-types/temporal.adoc b/modules/ROOT/pages/values-and-types/temporal.adoc index 96ca806ee..2f0384ce4 100644 --- a/modules/ROOT/pages/values-and-types/temporal.adoc +++ b/modules/ROOT/pages/values-and-types/temporal.adoc @@ -492,7 +492,6 @@ For more information, see the xref::values-and-types/temporal.adoc#cypher-tempor | | | -| |=== diff --git a/preview.yml b/preview.yml index 21a469097..b70cd4e8a 100644 --- a/preview.yml +++ b/preview.yml @@ -22,13 +22,6 @@ ui: urls: html_extension_style: indexify -antora: - extensions: - - require: "@neo4j-antora/antora-modify-sitemaps" - sitemap_version: '25' - sitemap_loc_version: 'current' - move_sitemaps_to_components: true - asciidoc: extensions: - "@neo4j-documentation/remote-include" diff --git a/publish.yml b/publish.yml index a44a20995..4ce2c6a76 100644 --- a/publish.yml +++ b/publish.yml @@ -22,13 +22,6 @@ ui: urls: html_extension_style: indexify -antora: - extensions: - - require: "@neo4j-antora/antora-modify-sitemaps" - sitemap_version: '25' - sitemap_loc_version: 'current' - move_sitemaps_to_components: true - asciidoc: extensions: - "@neo4j-documentation/remote-include" From 384542a5cccf5a998847c17ffc7416bd08cb23e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Thu, 16 Jan 2025 12:13:36 +0100 Subject: [PATCH 70/77] Clarify DETACH DELETE (#1156) --- modules/ROOT/pages/clauses/delete.adoc | 31 ++++++++++++++++++++------ modules/ROOT/pages/queries/basic.adoc | 4 +++- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/modules/ROOT/pages/clauses/delete.adoc b/modules/ROOT/pages/clauses/delete.adoc index b90a2f007..b9caafe1a 100644 --- a/modules/ROOT/pages/clauses/delete.adoc +++ b/modules/ROOT/pages/clauses/delete.adoc @@ -127,9 +127,9 @@ For more information, see link:{neo4j-docs-base-uri}/operations-manual/current/a [[delete-all-nodes-and-relationships]] == Delete all nodes and relationships -It is possible to delete all nodes and relationships in a graph. +It is possible to delete all nodes and relationships in a graph. -.Query +.Delete all nodes and relationships [source, cypher, indent=0] ---- MATCH (n) @@ -142,8 +142,25 @@ DETACH DELETE n Deleted 3 nodes, deleted 1 relationship ---- -[TIP] -==== -`DETACH DELETE` is not suitable for deleting large amounts of data, but is useful when experimenting with small example datasets. -To delete large amounts of data, instead use xref::subqueries/subqueries-in-transactions.adoc#delete-with-call-in-transactions[CALL subqueries in transactions]. -==== \ No newline at end of file +`DETACH DELETE` is useful when experimenting with small example datasets, but it is not suitable for deleting large amounts of data, nor does it delete xref:indexes/search-performance-indexes/overview.adoc[indexes] and xref:constraints/index.adoc[constraints]. + +To delete large amounts of data without deleting indexes and constraints, use xref::subqueries/subqueries-in-transactions.adoc#delete-with-call-in-transactions[CALL subqueries in transactions] instead. + +.Delete all nodes and relationships using `CALL` subqueries +[source, cypher] +---- +MATCH (n) +CALL (n) { + DETACH DELETE n +} IN TRANSACTIONS +---- + +To remove all data, including indexes and constraints, recreate the database using the following command: `CREATE OR REPLACE DATABASE name`. + +.Delete a database and recreate it +[source, cypher] +---- +CREATE OR REPLACE DATABASE neo4j +---- + +For more information, see the link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/standard-databases/create-databases/#_create_databases_with_if_not_exists_or_or_replace[Operations Manual -> Create databases with `IF NOT EXISTS` or `OR REPLACE`]. \ No newline at end of file diff --git a/modules/ROOT/pages/queries/basic.adoc b/modules/ROOT/pages/queries/basic.adoc index 0f77e4852..416eeedd6 100644 --- a/modules/ROOT/pages/queries/basic.adoc +++ b/modules/ROOT/pages/queries/basic.adoc @@ -901,4 +901,6 @@ MATCH (n) DETACH DELETE n ---- -For more information, see the section on the xref:clauses/delete.adoc[] clause. +[NOTE] +`DETACH DELETE` is not suitable for deleting large amounts of data, nor does it delete xref:indexes/search-performance-indexes/overview.adoc[indexes] and xref:constraints/index.adoc[constraints]. +For more information, and alternatives to `DETACH DELETE`, see xref:clauses/delete.adoc#delete-all-nodes-and-relationships[`DELETE` -> Delete all nodes and relationships]. From d6c403db01d119079485646b2315f04363783dda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nadja=20M=C3=BCller?= <73830555+nadja-muller@users.noreply.github.com> Date: Mon, 20 Jan 2025 15:11:44 +0100 Subject: [PATCH 71/77] add graph reference section to expressions (#1162) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * adds section about graph references to expressions * attempt to split behavior of use clauses in the docs depending on which database you're connected to --------- Co-authored-by: Jens Pryce-Åklundh <112686610+JPryce-Aklundh@users.noreply.github.com> --- modules/ROOT/pages/clauses/use.adoc | 35 ++++++++++++------- ...ions-additions-removals-compatibility.adoc | 21 +++++++++++ modules/ROOT/pages/queries/expressions.adoc | 22 ++++++++++++ 3 files changed, 66 insertions(+), 12 deletions(-) diff --git a/modules/ROOT/pages/clauses/use.adoc b/modules/ROOT/pages/clauses/use.adoc index 3a75add21..70beae342 100644 --- a/modules/ROOT/pages/clauses/use.adoc +++ b/modules/ROOT/pages/clauses/use.adoc @@ -10,22 +10,38 @@ It is supported for queries and schema commands. [[query-use-syntax]] == Syntax -The `USE` clause can only appear as the prefix of schema commands, or as the first clause of queries: - [source, syntax, role="noheader"] ---- -USE +USE ---- -Where `` refers to the name or alias of a database in the DBMS. +A graph reference can be described using: + +* Direct graph references: `USE db1`. +* The graph function xref:functions/graph.adoc#functions-graph-by-elementid[`graph.byElementId()`], to access a graph of a given element: `USE graph.byName()`. + +When connected to a composite database, a graph reference may additionally be passed with: + +* The graph function xref:functions/graph.adoc#functions-graph-byname[`graph.byName()`], which allows the graph reference to be resolved dynamically: `USE graph.byName()`. +A more detailed description of how and when a graph references needs to be quoted and/or escaped is defined xref::queries/expressions.adoc#graphreferences[here]. -[[query-use-syntax-composite]] -=== Composite database syntax +== USE clause when connected to a standard or system database -When running queries against a link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/composite-databases/concepts/[composite database], the `USE` clause can also appear as the first clause of: +All databases and aliases are valid graph reference targets except link:operations-manual/current/database-administration/aliases/manage-aliases-composite-databases/[composite databases and their constituents]. +Targeting multiple databases is not allowed, unless connected to a composite database. +=== Position of use clauses +When connected to a non-composite database, the `USE` clause can only appear as the prefix of schema commands, or as the first clause of queries. There may be multiple `USE` clauses as long as they target the same database. + +== USE clause when connected to a composite database +When executing queries against a link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/composite-databases/concepts/[composite database], the `USE` clause must only refer to graphs that are part of the current composite database. The constituents can be listed either with `RETURN graph.names()` when connected to the composite database or `SHOW DATABASES YIELD name, constituents RETURN *`. + +=== Position of use clauses +When running queries against a composite database, the `USE` clause can appear as the first clause of: + +* A query (similar to how it is used when connected to a non-composite database). * Union parts: + [source, syntax, role="noheader"] @@ -49,8 +65,6 @@ CALL () { + In subqueries, a `USE` clause may appear directly following the xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause]: `CALL () { ... }`. -When executing queries against a composite database, the `USE` clause must only refer to graphs that are part of the current composite database. - [[query-use-examples]] == Examples @@ -118,9 +132,6 @@ MATCH (n) RETURN n The xref:functions/graph.adoc#functions-graph-by-elementid[`graph.byElementId()`] function can be used in the `USE` clause to resolve a constituent graph to which a given xref:functions/scalar.adoc#functions-elementid[element id] belongs. -[NOTE] -On a standard database, a `USE` clause with `graph.byElementId()` cannot be combined with other `USE` clauses unless the subsequent `USE` clauses reference the same element id. - In the below example, it is assumed that the DBMS contains the database corresponding to the given element id. If you are connected to a composite database it needs to be a element id to a constituent database, which is a standard database in the DBMS. .Query diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index 309887365..b57d87d75 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -152,6 +152,27 @@ Several xref:clauses/transaction-clauses.adoc#query-listing-transactions[`SHOW * `startTime` and `currentQueryStartTime` now return a `ZONED DATETIME` instead of a `STRING` representation of a temporal value. * `clientAddress` and `outerTransactionId` now return `null` instead of an empty `STRING` when unavailable. * The current query-related columns — `currentQuery`, `currentQueryId`, `parameters`, `planner`, `runtime`, `indexes`, `currentQueryStartTime`, `currentQueryElapsedTime`, `currentQueryCpuTime`, `currentQueryIdleTime`, and `currentQueryStatus` — now return `null` when no query is executing. + +a| +label:functionality[] +label:updated[] +[source, cypher, role="noheader"] +---- +USE graph.byName('tom`s-database') + +USE graph.propertiesByName('database.with.dot') +---- +| xref::queries/expressions.adoc#graphreferences[Graph references] in arguments of the functions xref:functions/graph.adoc#functions-graph-byname[`graph.byName`] and xref:functions/graph.adoc#functions-graph-propertiesByName[`graph.propertiesByName`] in Cypher 25 are parsed as `` or `.` and now support escaping names. +For more information, see xref:syntax/expressions.adoc#graph-references[Cypher expressions -> Graph references. +Graph name parts that contain unsupported characters for unescaped symbolic names now require backtick quoting. +Graph name parts with special characters may require additional escaping of those characters: + +* `++USE graph.byName('`tom``s-database`')++` + +* `++USE graph.propertiesByName('database.with.dot')++` + +Note that escaping graph names within the graph functions string argument is not supported in Cypher 5. + |=== === New features diff --git a/modules/ROOT/pages/queries/expressions.adoc b/modules/ROOT/pages/queries/expressions.adoc index 7f73fb3cb..f4ba6f036 100644 --- a/modules/ROOT/pages/queries/expressions.adoc +++ b/modules/ROOT/pages/queries/expressions.adoc @@ -82,3 +82,25 @@ String literals can contain the following escape sequences: * A predicate expression (i.e. an expression returning a `BOOLEAN` value): `a.prop = 'Hello'`, `length(p) > 10`, `a.name IS NOT NULL`. * Label and relationship type expressions: `(n:A|B)`, `+()-[r:R1|R2]->()+`. * `null`. + +[[graph-references]] +== Graph references +* Database and alias names when managing link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/[databases and aliases]: `CREATE DATABASE `. +* Static graph references: `USE ` or `USE .` (for constituents of a link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/composite-databases/concepts/[composite databases]). +* Dynamic graph reference with the xref:functions/graph.adoc#functions-graph-byname[`graph.byName`] function, to access a graph of a given name: `USE graph.byName()`. +* Dynamic graph references with the xref:functions/graph.adoc#functions-graph-by-elementid[`graph.byElementId`] function, to access a graph of a given node or relationship: `USE graph.byName()`. +* Retrieving properties of a graph with the xref:functions/graph.adoc#functions-graph-propertiesByName[`graph.propertiesByName`] function: `graph.propertiesByName()`. + + +Rules on string expressions for graph references when using identifiers (static graph references, administration commands) or a string (graph.byName function): + +* Unquoted dots are separators between a composite database and its constituent. +For example, `composite.db1` represents the constituent `composite.db1` in the composite database `composite`. +To refer to a database with a dot (`.`) in its name, quote the graph reference instead: `++`composite.db1`++`. +* When resolving a graph reference within a graph function, the string argument is parsed like a static graph reference. + Thus, `USE graph.byName()` is typically equivalent to `USE `. + However, escaping rules for xref::syntax/naming.adoc#symbolic-names-escaping-rules[symbolic names] are applied to the argument. + For string literals, both the escaping rules for xref:queries/expressions.adoc#expressions-string-literals[string literals] (during query parsing) and xref::syntax/naming.adoc#symbolic-names-escaping-rules[symbolic names] (during graph reference evaluation) are applied. +For example, the graph reference in `USE graph.byName('+composite.1\\u0041+')` resolves to the constituent `composite.1a` of the composite database `composite`. + + From a4048161e38f0f43fd7394213b79cf3de090c173 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Tue, 21 Jan 2025 15:56:58 +0100 Subject: [PATCH 72/77] CALL fix for cypher 25 (#1173) --- .../ROOT/pages/subqueries/call-subquery.adoc | 108 ++++++++---------- 1 file changed, 47 insertions(+), 61 deletions(-) diff --git a/modules/ROOT/pages/subqueries/call-subquery.adoc b/modules/ROOT/pages/subqueries/call-subquery.adoc index 81edd047c..61410a123 100644 --- a/modules/ROOT/pages/subqueries/call-subquery.adoc +++ b/modules/ROOT/pages/subqueries/call-subquery.adoc @@ -31,14 +31,9 @@ CREATE (teamA:Team {name: 'Team A'}), (playerF:Player {name: 'Player F', age: 35}), (playerA)-[:PLAYS_FOR]->(teamA), (playerB)-[:PLAYS_FOR]->(teamA), - (playerC)-[:PLAYS_FOR]->(teamA), (playerD)-[:PLAYS_FOR]->(teamB), (playerE)-[:PLAYS_FOR]->(teamC), (playerF)-[:PLAYS_FOR]->(teamC), - (playerA)-[:FRIEND_OF]->(playerB), - (playerA)-[:FRIEND_OF]->(playerC), - (playerB)-[:FRIEND_OF]->(playerF), - (playerC)-[:FRIEND_OF]->(playerD), (teamA)-[:OWES {dollars: 1500}]->(teamB), (teamA)-[:OWES {dollars: 3000}]->(teamB), (teamB)-[:OWES {dollars: 1700}]->(teamC), @@ -93,7 +88,6 @@ CALL () { SET p.age = p.age + 1 RETURN p.age AS newAge } -WITH x, newAge MATCH (p:Player {name: 'Player A'}) RETURN x AS iteration, newAge, p.age AS totalAge ---- @@ -140,7 +134,7 @@ RETURN t AS team, players | players | (:Team {name: "Team A"}) -| [(:Player {name: "Player C", age: 19}), (:Player {name: "Player B", age: 23}), (:Player {name: "Player A", age: 24})] +| (:Player {name: "Player B", age: 23}), (:Player {name: "Player A", age: 24})] | (:Team {name: "Team B"}) | [(:Player {name: "Player D", age: 30})] @@ -161,7 +155,6 @@ Using a `CALL` subquery can therefore reduce the amount of heap memory required Variables from the outer scope must be explicitly imported into the inner scope of the `CALL` subquery, either by using a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause] or an xref:subqueries/call-subquery.adoc#importing-with[importing `WITH` clause] (deprecated). As the subquery is evaluated for each incoming input row, the imported variables are assigned the corresponding values from that row. - [[variable-scope-clause]] === The variable scope clause @@ -279,7 +272,7 @@ RETURN count(t) AS totalTeams, totalPlayers [NOTE] ===== -As of Neo4j 5.23, it is deprecated to use `CALL` subqueries without a variable scope clause. +`CALL` subqueries without a variable scope clause are deprecated. .Deprecated [source, cypher] @@ -423,7 +416,6 @@ RETURN largeLists ==== - [[optional-call]] == Optional subquery calls @@ -433,60 +425,60 @@ Similar to xref:clauses/optional-match.adoc[`OPTIONAL MATCH`] any empty rows pro .Difference between using `CALL` and `OPTIONAL CALL` ==== -This example, which finds the friends of each `Player` and xref:functions/aggregating.adoc#functions-count[counts] the number of friends per player, highlights the difference between using `CALL` and `OPTIONAL CALL`. +This example, which finds the team that each `Player` plays for, highlights the difference between using `CALL` and `OPTIONAL CALL`. .Regular subquery `CALL` [source, cypher] ---- MATCH (p:Player) CALL (p) { - MATCH (p)-[:FRIEND_OF]->(friend:Player) - RETURN friend + MATCH (p)-[:PLAYS_FOR]->(team:Team) + RETURN team } -RETURN p.name AS playerName, count(friend) AS numberOfFriends -ORDER BY numberOfFriends +RETURN p.name AS playerName, team.name AS team ---- -.Optional subquery `CALL` +.Result [role="queryresult",options="header,footer",cols="2*m"] |=== -| playerName | numberOfFriends +| playerName | team -| "Player B" | 1 -| "Player C" | 1 -| "Player A" | 2 +| "Player A" | "Team A" +| "Player B" | "Team A" +| "Player D" | "Team B" +| "Player E" | "Team C" +| "Player F" | "Team C" -2+d|Rows: 3 +2+d|Rows: 5 |=== -Note that no results are returned for `Player D`, `Player E`, and `Player F`, since they have no outgoing `FRIEND_OF` relationships connected to them. +Note that no results are returned for `Player C`, since they are not connected to any `Team` with a `PLAYS_FOR` relationship. .Query using regular `OPTIONAL CALL` [source, cypher] ---- MATCH (p:Player) OPTIONAL CALL (p) { - MATCH (p)-[:FRIEND_OF]->(friend:Player) - RETURN friend + MATCH (p)-[:PLAYS_FOR]->(team:Team) + RETURN team } -RETURN p.name AS playerName, count(friend) AS numberOfFriends -ORDER BY numberOfFriends +RETURN p.name AS playerName, team.name AS team ---- -Now, all `Player` nodes, regardless of whether they have any friends or not, are returned. -(Those without any outgoing `FRIEND_OF` relationships are returned with the result `0` because `count()` ignores `null` values.) +Now all `Player` nodes, regardless of whether they have any `PLAYS_FOR` relationships connected to a `Team`, are returned. +.Result .Result [role="queryresult",options="header,footer",cols="2*m"] |=== -| playerName | numberOfFriends +| playerName | team -| "Player D" | 0 -| "Player E" | 0 -| "Player F" | 0 -| "Player B" | 1 -| "Player C" | 1 -| "Player A" | 2 +| "Player A" | "Team A" +| "Player B" | "Team A" +| "Player C" | NULL +| "Player D" | "Team B" +| "Player E" | "Team C" +| "Player F" | "Team C" 2+d|Rows: 6 |=== @@ -496,8 +488,8 @@ Now, all `Player` nodes, regardless of whether they have any friends or not, are [[call-execution-order]] == Execution order of CALL subqueries -The order in which subqueries are executed is not defined. -If a query result depends on the order of execution of subqueries, an `ORDER BY` clause should precede the `CALL` clause. +The order in which rows from the outer scope are passed into subqueries is not defined. +If the results of the subquery depend on the order of these rows, use an `ORDER BY` clause before the `CALL` clause to guarantee a specific processing order for the rows. .Ordering results before `CALL` subquery ==== @@ -591,13 +583,13 @@ UNION ORDER BY p.age DESC LIMIT 1 } -RETURN p.name AS name, p.age AS age +RETURN p.name AS playerName, p.age AS age ---- .Result [role="queryresult",options="header,footer",cols="2*(p2:Player) - RETURN p2.name AS friend + MATCH (p)-[:PLAYS_FOR]->(team:Team) + RETURN team.name AS team } -RETURN p.name AS player, friend +RETURN p.name AS playerName, team ---- .Result -[role="queryresult",options="header,footer",cols="2* Date: Thu, 23 Jan 2025 08:54:04 +0100 Subject: [PATCH 73/77] Remove invalid duration field (#1174) --- modules/ROOT/pages/functions/temporal/duration.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ROOT/pages/functions/temporal/duration.adoc b/modules/ROOT/pages/functions/temporal/duration.adoc index 68f69f9d5..74503b98f 100644 --- a/modules/ROOT/pages/functions/temporal/duration.adoc +++ b/modules/ROOT/pages/functions/temporal/duration.adoc @@ -19,7 +19,7 @@ See also xref::values-and-types/temporal.adoc[Temporal values] and xref::syntax/ | *Syntax* 3+| `duration(input)` | *Description* 3+| Creates a `DURATION` value. .2+| *Arguments* | *Name* | *Type* | *Description* -| `input` | `ANY` | A map optionally containing the following keys: 'years', 'quarters', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds', 'milliseconds', 'microseconds', or 'nanoseconds'. +| `input` | `ANY` | A map optionally containing the following keys: 'years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds', 'milliseconds', 'microseconds', or 'nanoseconds'. | *Returns* 3+| `DURATION` |=== From e15dbf7549bc67d596e0e154b028d59ef23e8a97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Tue, 28 Jan 2025 14:33:18 +0100 Subject: [PATCH 74/77] Revert changes to pattern query plans (#1176) Reverts changes made here: https://github.com/neo4j/docs-cypher/pull/1166 due to a rolback in product --- .../operators/operators-detail.adoc | 236 +++++++++--------- 1 file changed, 113 insertions(+), 123 deletions(-) diff --git a/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc b/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc index 875acb6a5..5e079873e 100644 --- a/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc +++ b/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc @@ -4093,32 +4093,30 @@ Runtime version {neo4j-version} Batch size 128 -+--------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+--------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | 0 | me, friend | 3 | 34 | 136 | 0 | | | | -| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +Filter | 1 | friend:Person | 3 | 34 | 68 | | | | | -| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +NullifyMetadata | 10 | | 3 | 34 | 0 | | | | | -| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +Repeat(Trail) | 2 | (me) (...){1, 2} (friend) | 3 | 34 | 0 | 30000 | 0/0 | 5.379 | Fused in Pipeline 2 | -| |\ +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| | +Filter | 3 | NOT anon_5 = anon_3 AND (NOT cache[a.name] = cache[c.name] AND NOT cache[b.name] = cache[c.name]) AN | 6 | 34 | 92 | | | | | -| | | | | D isRepeatTrailUnique(anon_5) | | | | | | | | -| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +Expand(All) | 4 | (b)-[anon_5:FRIENDS_WITH]-(c) | 26 | 92 | 138 | | | | | -| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +Filter | 5 | NOT cache[a.name] = cache[b.name] AND isRepeatTrailUnique(anon_3) | 15 | 46 | 132 | | | | | -| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +Expand(All) | 6 | (a)-[anon_3:FRIENDS_WITH]-(b) | 31 | 66 | 100 | | | | | -| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +CacheProperties | 7 | cache[a.name] | 18 | 34 | 68 | | | | | -| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +Argument | 8 | a | 18 | 34 | 0 | 15880 | 2/0 | 5.556 | Fused in Pipeline 1 | -| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +NodeByLabelScan | 9 | me:Person | 14 | 14 | 15 | 376 | 1/0 | 0.727 | In Pipeline 0 | -+--------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | me, friend | 2 | 34 | 136 | 0 | | | | +| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +Filter | 1 | friend:Person | 2 | 34 | 68 | | | | | +| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +NullifyMetadata | 9 | | 2 | 34 | 0 | | | | | +| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +Repeat(Trail) | 2 | (me) (...){1, 2} (friend) | 2 | 34 | 0 | 30112 | 0/0 | 4.943 | Fused in Pipeline 2 | +| |\ +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| | +Filter | 3 | NOT anon_5 = anon_3 AND (NOT cache[a.name] = cache[c.name] AND NOT cache[b.name] = cache[c.name]) AN | 1 | 34 | 92 | | | | | +| | | | | D isRepeatTrailUnique(anon_5) | | | | | | | | +| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Expand(All) | 4 | (b)-[anon_5:FRIENDS_WITH]-(c) | 3 | 92 | 138 | | | | | +| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Filter | 5 | NOT cache[a.name] = cache[b.name] AND isRepeatTrailUnique(anon_3) | 5 | 46 | 198 | | | | | +| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Expand(All) | 6 | (a)-[anon_3:FRIENDS_WITH]-(b) | 10 | 66 | 100 | | | | | +| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Argument | 7 | a | 15 | 34 | 0 | 15992 | 2/0 | 5.253 | Fused in Pipeline 1 | +| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +NodeByLabelScan | 8 | me:Person | 14 | 14 | 15 | 376 | 1/0 | 1.130 | In Pipeline 0 | ++------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ Total database accesses: 747, total allocated memory: 45832 ---- @@ -4154,32 +4152,30 @@ Runtime version {neo4j-version} Batch size 128 -+--------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+--------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | 0 | me, friend | 3 | 34 | 136 | 0 | | | | -| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +Filter | 1 | friend:Person | 3 | 34 | 68 | | | | | -| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +NullifyMetadata | 10 | | 3 | 34 | 0 | | | | | -| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +Repeat(Trail) | 2 | (me) (...){1, 2} (friend) | 3 | 34 | 0 | 30000 | 0/0 | 5.379 | Fused in Pipeline 2 | -| |\ +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| | +Filter | 3 | NOT anon_5 = anon_3 AND (NOT cache[a.name] = cache[c.name] AND NOT cache[b.name] = cache[c.name]) AN | 6 | 34 | 92 | | | | | -| | | | | D isRepeatTrailUnique(anon_5) | | | | | | | | -| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +Expand(All) | 4 | (b)-[anon_5:FRIENDS_WITH]-(c) | 26 | 92 | 138 | | | | | -| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +Filter | 5 | NOT cache[a.name] = cache[b.name] AND isRepeatTrailUnique(anon_3) | 15 | 46 | 132 | | | | | -| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +Expand(All) | 6 | (a)-[anon_3:FRIENDS_WITH]-(b) | 31 | 66 | 100 | | | | | -| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +CacheProperties | 7 | cache[a.name] | 18 | 34 | 68 | | | | | -| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +Argument | 8 | a | 18 | 34 | 0 | 15880 | 2/0 | 5.556 | Fused in Pipeline 1 | -| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +NodeByLabelScan | 9 | me:Person | 14 | 14 | 15 | 376 | 1/0 | 0.727 | In Pipeline 0 | -+--------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | me, friend | 2 | 34 | 136 | 0 | | | | +| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +Filter | 1 | friend:Person | 2 | 34 | 68 | | | | | +| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +NullifyMetadata | 9 | | 2 | 34 | 0 | | | | | +| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +Repeat(Trail) | 2 | (me) (...){1, 2} (friend) | 2 | 34 | 0 | 30112 | 0/0 | 4.824 | Fused in Pipeline 2 | +| |\ +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| | +Filter | 3 | NOT anon_5 = anon_3 AND (NOT cache[a.name] = cache[c.name] AND NOT cache[b.name] = cache[c.name]) AN | 1 | 34 | 92 | | | | | +| | | | | D isRepeatTrailUnique(anon_5) | | | | | | | | +| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Expand(All) | 4 | (b)-[anon_5:FRIENDS_WITH]-(c) | 3 | 92 | 138 | | | | | +| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Filter | 5 | NOT cache[a.name] = cache[b.name] AND isRepeatTrailUnique(anon_3) | 5 | 46 | 198 | | | | | +| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Expand(All) | 6 | (a)-[anon_3:FRIENDS_WITH]-(b) | 10 | 66 | 100 | | | | | +| | | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +Argument | 7 | a | 15 | 34 | 0 | 15992 | 2/0 | 5.307 | Fused in Pipeline 1 | +| | +----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +NodeByLabelScan | 8 | me:Person | 14 | 14 | 15 | 376 | 1/0 | 0.183 | In Pipeline 0 | ++------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ Total database accesses: 747, total allocated memory: 45832 ---- @@ -4383,27 +4379,25 @@ Runtime SLOTTED Runtime version {neo4j-version} -+--------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | -+--------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+ -| +ProduceResults | 0 | `other.name` | 35 | 24 | 0 | 0 | 0/0 | -| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ -| +Projection | 1 | cache[other.name] AS `other.name` | 35 | 24 | 0 | | 0/0 | -| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ -| +TriadicSelection | 2 | WHERE NOT (me)--(other) | 35 | 24 | 0 | | 0/0 | -| |\ +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ -| | +CacheProperties | 3 | cache[other.name] | 16 | 24 | 24 | | 0/0 | -| | | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ -| | +Filter | 4 | NOT anon_2 = anon_0 | 16 | 24 | 0 | | 0/0 | -| | | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ -| | +Expand(All) | 5 | (anon_1)-[anon_2:FRIENDS_WITH]-(other) | 16 | 48 | 72 | | 0/0 | -| | | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ -| | +Argument | 6 | anon_1, anon_0 | 24 | 24 | 0 | | 0/0 | -| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ -| +Expand(All) | 7 | (me)-[anon_0:FRIENDS_WITH]-(anon_1) | 24 | 24 | 38 | | 2/0 | -| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ -| +NodeByLabelScan | 8 | me:Person | 14 | 14 | 15 | | 1/0 | -+--------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+ ++-------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | ++-------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+ +| +ProduceResults | 0 | `other.name` | 15 | 24 | 0 | 0 | 0/0 | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ +| +Projection | 1 | other.name AS `other.name` | 15 | 24 | 24 | | 0/0 | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ +| +Filter | 2 | NOT anon_2 = anon_0 | 15 | 24 | 0 | | 0/0 | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ +| +TriadicSelection | 3 | WHERE NOT (me)--(other) | 15 | 48 | 0 | | 0/0 | +| |\ +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ +| | +Expand(All) | 4 | (anon_1)-[anon_2:FRIENDS_WITH]-(other) | 16 | 48 | 72 | | 0/0 | +| | | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ +| | +Argument | 5 | anon_1, anon_0 | 24 | 24 | 0 | | 0/0 | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ +| +Expand(All) | 6 | (me)-[anon_0:FRIENDS_WITH]-(anon_1) | 24 | 24 | 38 | | 2/0 | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+ +| +NodeByLabelScan | 7 | me:Person | 14 | 14 | 15 | | 1/0 | ++-------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+ Total database accesses: 246, total allocated memory: 64 ---- @@ -4444,31 +4438,29 @@ Runtime version {neo4j-version} Batch size 128 -+--------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+--------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | 0 | `other.name` | 35 | 24 | 0 | 0 | 0/0 | 0.180 | | -| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | -| +Projection | 1 | cache[other.name] AS `other.name` | 35 | 24 | 0 | | 0/0 | 0.064 | | -| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | -| +TriadicFilter | 11 | WHERE NOT (me)--(other) | 35 | 24 | 0 | 7512 | 0/0 | 0.303 | In Pipeline 3 | -| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +Apply | 10 | | 16 | 24 | 0 | | 0/0 | | | -| |\ +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| | +CacheProperties | 3 | cache[other.name] | 16 | 24 | 48 | | | | | -| | | +----+----------------------------------------+----------------+------+---------+----------------+ | | | -| | +Filter | 4 | NOT anon_2 = anon_0 | 16 | 24 | 0 | | | | | -| | | +----+----------------------------------------+----------------+------+---------+----------------+ | | | -| | +Expand(All) | 5 | (anon_1)-[anon_2:FRIENDS_WITH]-(other) | 16 | 48 | 72 | | | | | -| | | +----+----------------------------------------+----------------+------+---------+----------------+ | | | -| | +Argument | 6 | anon_1, anon_0 | 24 | 24 | 0 | 4464 | 0/0 | 0.575 | Fused in Pipeline 2 | -| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +TriadicBuild | 9 | (me)--(anon_1) | 24 | 24 | 0 | 1080 | 0/0 | 1.608 | In Pipeline 1 | -| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +Expand(All) | 7 | (me)-[anon_0:FRIENDS_WITH]-(anon_1) | 24 | 24 | 38 | | | | | -| | +----+----------------------------------------+----------------+------+---------+----------------+ | | | -| +NodeByLabelScan | 8 | me:Person | 14 | 14 | 15 | 376 | 3/0 | 0.559 | Fused in Pipeline 0 | -+--------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | `other.name` | 15 | 24 | 0 | 0 | 0/0 | 0.172 | | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | +| +Projection | 1 | other.name AS `other.name` | 15 | 24 | 48 | | 0/0 | 0.162 | | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | +| +Filter | 2 | NOT anon_2 = anon_0 | 15 | 24 | 0 | | 0/0 | 0.134 | | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | +| +TriadicFilter | 10 | WHERE NOT (me)--(other) | 15 | 48 | 0 | 7216 | 0/0 | 0.251 | In Pipeline 3 | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +Apply | 9 | | 16 | 48 | 0 | | 0/0 | | | +| |\ +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| | +Expand(All) | 4 | (anon_1)-[anon_2:FRIENDS_WITH]-(other) | 16 | 48 | 72 | | | | | +| | | +----+----------------------------------------+----------------+------+---------+----------------+ | | | +| | +Argument | 5 | anon_1, anon_0 | 24 | 24 | 0 | 4464 | 0/0 | 0.384 | Fused in Pipeline 2 | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +TriadicBuild | 8 | (me)--(anon_1) | 24 | 24 | 0 | 1080 | 0/0 | 1.670 | In Pipeline 1 | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +Expand(All) | 6 | (me)-[anon_0:FRIENDS_WITH]-(anon_1) | 24 | 24 | 38 | | | | | +| | +----+----------------------------------------+----------------+------+---------+----------------+ | | | +| +NodeByLabelScan | 7 | me:Person | 14 | 14 | 15 | 376 | 3/0 | 0.361 | Fused in Pipeline 0 | ++------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ Total database accesses: 256, total allocated memory: 7376 ---- @@ -4509,31 +4501,29 @@ Runtime version {neo4j-version} Batch size 128 -+--------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | -+--------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +ProduceResults | 0 | `other.name` | 35 | 24 | 0 | 0 | 0/0 | 0.198 | | -| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | -| +Projection | 1 | cache[other.name] AS `other.name` | 35 | 24 | 0 | | 0/0 | 0.095 | | -| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | -| +TriadicFilter | 11 | WHERE NOT (me)--(other) | 35 | 24 | 0 | 7512 | 0/0 | 0.176 | In Pipeline 3 | -| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +Apply | 10 | | 16 | 24 | 0 | | 0/0 | | | -| |\ +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| | +CacheProperties | 3 | cache[other.name] | 16 | 24 | 48 | | | | | -| | | +----+----------------------------------------+----------------+------+---------+----------------+ | | | -| | +Filter | 4 | NOT anon_2 = anon_0 | 16 | 24 | 0 | | | | | -| | | +----+----------------------------------------+----------------+------+---------+----------------+ | | | -| | +Expand(All) | 5 | (anon_1)-[anon_2:FRIENDS_WITH]-(other) | 16 | 48 | 72 | | | | | -| | | +----+----------------------------------------+----------------+------+---------+----------------+ | | | -| | +Argument | 6 | anon_1, anon_0 | 24 | 24 | 0 | 4464 | 0/0 | 0.990 | Fused in Pipeline 2 | -| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +TriadicBuild | 9 | (me)--(anon_1) | 24 | 24 | 0 | 1080 | 0/0 | 0.304 | In Pipeline 1 | -| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +Expand(All) | 7 | (me)-[anon_0:FRIENDS_WITH]-(anon_1) | 24 | 24 | 38 | | | | | -| | +----+----------------------------------------+----------------+------+---------+----------------+ | | | -| +NodeByLabelScan | 8 | me:Person | 14 | 14 | 15 | 376 | 3/0 | 0.399 | Fused in Pipeline 0 | -+--------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline | ++------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +ProduceResults | 0 | `other.name` | 15 | 24 | 0 | 0 | 0/0 | 0.413 | | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | +| +Projection | 1 | other.name AS `other.name` | 15 | 24 | 48 | | 0/0 | 0.302 | | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | +| +Filter | 2 | NOT anon_2 = anon_0 | 15 | 24 | 0 | | 0/0 | 0.268 | | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+ | +| +TriadicFilter | 10 | WHERE NOT (me)--(other) | 15 | 48 | 0 | 7216 | 0/0 | 0.298 | In Pipeline 3 | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +Apply | 9 | | 16 | 48 | 0 | | 0/0 | | | +| |\ +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| | +Expand(All) | 4 | (anon_1)-[anon_2:FRIENDS_WITH]-(other) | 16 | 48 | 72 | | | | | +| | | +----+----------------------------------------+----------------+------+---------+----------------+ | | | +| | +Argument | 5 | anon_1, anon_0 | 24 | 24 | 0 | 4464 | 0/0 | 0.563 | Fused in Pipeline 2 | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +TriadicBuild | 8 | (me)--(anon_1) | 24 | 24 | 0 | 1080 | 0/0 | 0.403 | In Pipeline 1 | +| | +----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +Expand(All) | 6 | (me)-[anon_0:FRIENDS_WITH]-(anon_1) | 24 | 24 | 38 | | | | | +| | +----+----------------------------------------+----------------+------+---------+----------------+ | | | +| +NodeByLabelScan | 7 | me:Person | 14 | 14 | 15 | 376 | 3/0 | 0.530 | Fused in Pipeline 0 | ++------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ Total database accesses: 256, total allocated memory: 7376 ---- From 1c0c171b3b70328ec8332d53208a08ebd2dc54ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Thu, 30 Jan 2025 11:05:57 +0100 Subject: [PATCH 75/77] Better Unicode example on Parsing page (#1177) --- modules/ROOT/pages/syntax/parsing.adoc | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/modules/ROOT/pages/syntax/parsing.adoc b/modules/ROOT/pages/syntax/parsing.adoc index 93cab6d53..5e95c41f4 100644 --- a/modules/ROOT/pages/syntax/parsing.adoc +++ b/modules/ROOT/pages/syntax/parsing.adoc @@ -6,10 +6,20 @@ This page provides a general overview of how Cypher parses an input `STRING`. The Cypher parser takes an arbitrary input `STRING`. -While the syntax of Cypher is described in subsequent chapters, the following details the general rules on which characters are considered valid input. +This page details the general rules on which characters are considered valid input. == Using unicodes in Cypher + Unicodes can generally be escaped as `\uxxx`. +For example, the below query uses the Unicode `u00B0` to search for any recipe descriptions containing the degree symbol, `º`: + +.Using Unicodes in `STRING` matching +[source, cypher] +---- +MATCH (r:Recipe) +WHERE r.description CONTAINS "\u00B0" +RETURN r +---- Additional documentation on escaping rules for `STRING` literals, names and regular expressions can be found here: @@ -17,13 +27,6 @@ Additional documentation on escaping rules for `STRING` literals, names and regu * xref::syntax/naming.adoc#symbolic-names-escaping-rules[Using special characters in names] * xref::clauses/where.adoc#escaping-in-regular-expressions[Regular expressions] -The following example escapes the unicode character `A` (`\u0041`) in the keyword `MATCH`: - -[source, syntax] ----- -M\u0041TCH (m) RETURN m; ----- - The Unicode version used by Cypher depends on the running JVM version. [options="header", cols="1,2,3"] From c743e4637fe7fb14a6f65e6de58e6ee61052d396 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Thu, 30 Jan 2025 14:12:37 +0100 Subject: [PATCH 76/77] Fix tables (#1178) --- modules/ROOT/pages/clauses/call.adoc | 6 +-- modules/ROOT/pages/clauses/where.adoc | 3 +- modules/ROOT/pages/functions/aggregating.adoc | 2 +- modules/ROOT/pages/syntax/operators.adoc | 51 +++++++++++-------- .../ROOT/pages/values-and-types/temporal.adoc | 1 - 5 files changed, 37 insertions(+), 26 deletions(-) diff --git a/modules/ROOT/pages/clauses/call.adoc b/modules/ROOT/pages/clauses/call.adoc index 8c2b32451..4431598e6 100644 --- a/modules/ROOT/pages/clauses/call.adoc +++ b/modules/ROOT/pages/clauses/call.adoc @@ -86,7 +86,7 @@ CALL dbms.checkConfigValue('server.bolt.enabled', 'true') | "valid" | "message" | true | "requires restart" -2+d|Rows: 2 +2+d|Rows: 1 |=== ==== @@ -118,7 +118,7 @@ CALL dbms.checkConfigValue($setting, $value) | "valid" | "message" | true | "requires restart" -2+d|Rows: 2 +2+d|Rows: 1 |=== [NOTE] @@ -153,7 +153,7 @@ CALL dbms.checkConfigValue($setting, 'true') | "valid" | "message" | true | "requires restart" -2+d|Rows: 2 +2+d|Rows: 1 |=== ==== diff --git a/modules/ROOT/pages/clauses/where.adoc b/modules/ROOT/pages/clauses/where.adoc index 0ecf72c39..c1253b352 100644 --- a/modules/ROOT/pages/clauses/where.adoc +++ b/modules/ROOT/pages/clauses/where.adoc @@ -368,7 +368,8 @@ For more information, see the section about the xref:syntax/operators.adoc#match | 'Andy' | 'Timothy' | 'Peter' -1+|Rows: 3 + +1+d|Rows: 3 |=== Note that the `IS NORMALIZED` operator returns `null` when used on a non-`STRING` value. diff --git a/modules/ROOT/pages/functions/aggregating.adoc b/modules/ROOT/pages/functions/aggregating.adoc index d90fd3c19..af4f631f5 100644 --- a/modules/ROOT/pages/functions/aggregating.adoc +++ b/modules/ROOT/pages/functions/aggregating.adoc @@ -312,8 +312,8 @@ The `Guy Pearce` node will, therefore, get counted twice when not using `DISTINC | friendOfFriend.name | count(friendOfFriend) | count(ALL friendOfFriend) | count(DISTINCT friendOfFriend) | "Guy Pearce" | 2 | 2 | 1 -4+d|Rows: 1 +4+d|Rows: 1 |=== ====== diff --git a/modules/ROOT/pages/syntax/operators.adoc b/modules/ROOT/pages/syntax/operators.adoc index 362982f21..e010d796b 100644 --- a/modules/ROOT/pages/syntax/operators.adoc +++ b/modules/ROOT/pages/syntax/operators.adoc @@ -55,10 +55,8 @@ Even though both *'Anne'* and *'Carol'* have blue eyes, *'blue'* is only returne | +p.eyeColor+ | +"blue"+ | +"brown"+ -1+d|Rows: 2 + -Nodes created: 3 + -Properties set: 6 + -Labels added: 3 + +1+d|Rows: 2 |=== `DISTINCT` is commonly used in conjunction with xref::functions/aggregating.adoc[aggregating functions]. @@ -102,10 +100,8 @@ RETURN p.name | +p.name+ | +"Jane"+ | +"Tom"+ -1+d|Rows: 2 + -Nodes created: 2 + -Properties set: 4 + -Labels added: 2 + +1+d|Rows: 2 |=== @@ -131,10 +127,8 @@ RETURN DISTINCT restaurant.name |=== | +restaurant.name+ | +"Hungry Jo"+ -1+d|Rows: 1 + -Nodes created: 4 + -Properties set: 8 + -Labels added: 4 + +1+d|Rows: 1 |=== See xref::clauses/where.adoc#query-where-basic[Basic usage] for more details on dynamic property access. @@ -165,10 +159,8 @@ All the existing properties on the node are replaced by those provided in the ma |=== | +p.name+ | +p.age+ | +p.livesIn+ | +"Ellen"+ | ++ | +"London"+ -3+d|Rows: 1 + -Nodes created: 1 + -Properties set: 5 + -Labels added: 1 + +3+d|Rows: 1 |=== See xref::clauses/set.adoc#set-replace-properties-using-map[Replace all properties using a map and `=`] for more details on using the property replacement operator `=`. @@ -194,10 +186,8 @@ The properties on the node are updated as follows by those provided in the map: |=== | +p.name+ | +p.age+ | +p.livesIn+ | +"Ellen"+ | +20+ | +"London"+ -3+d|Rows: 1 + -Nodes created: 1 + -Properties set: 4 + -Labels added: 1 + +3+d|Rows: 1 |=== See xref::clauses/set.adoc#set-setting-properties-using-map[Mutate specific properties using a map and `+=`] for more details on using the property mutation operator `+=`. @@ -250,6 +240,7 @@ RETURN b - a AS result |=== | +result+ | +7+ + 1+d|Rows: 1 |=== @@ -292,6 +283,7 @@ RETURN one > two AS result |=== | +result+ | +true+ + 1+d|Rows: 1 |=== @@ -317,6 +309,7 @@ RETURN candidate | +candidate+ | +"John"+ | +"Jonathan"+ + 1+d|Rows: 2 |=== @@ -531,6 +524,7 @@ RETURN number | +4+ | +7+ | +9+ + 1+d|Rows: 3 |=== @@ -560,6 +554,7 @@ RETURN 'neo' + '4j' AS result |=== | +result+ | +"neo4j"+ + 1+d|Rows: 1 |=== @@ -605,6 +600,7 @@ RETURN "the \u212B char" IS NORMALIZED AS normalized |=== | normalized | false + 1+|Rows: 1 |=== @@ -632,6 +628,7 @@ RETURN "the \u212B char" IS NOT NORMALIZED AS notNormalized |=== | notNormalized | true + 1+|Rows: 1 |=== @@ -752,6 +749,7 @@ RETURN aDateTime + aDuration, aDateTime - aDuration |=== | +aDateTime + aDuration+ | +aDateTime - aDuration+ | +1996-10-11T12:31:14.000000002+ | +1972-10-11T12:31:13.999999998+ + 2+d|Rows: 1 |=== @@ -791,6 +789,7 @@ RETURN |=== | +date1+ | +date2+ | +2012-02-28+ | +2012-02-29+ + 2+d|Rows: 1 |=== @@ -812,6 +811,7 @@ RETURN duration1, duration2, duration1 + duration2, duration1 - duration2 |=== | +duration1+ | +duration2+ | +duration1 + duration2+ | +duration1 - duration2+ | +P12Y5M14DT16H13M10.000000001S+ | +P1M-14DT15H49M10S+ | +P12Y6MT32H2M20.000000001S+ | +P12Y4M28DT24M0.000000001S+ + 4+d|Rows: 1 |=== @@ -833,6 +833,7 @@ RETURN aDuration, aDuration * 2, aDuration / 3 |=== | +aDuration+ | +aDuration * 2+ | +aDuration / 3+ | +P14DT13M10.000000001S+ | +P28DT26M20.000000002S+ | +P4DT16H4M23.333333333S+ + 3+d|Rows: 1 |=== @@ -867,6 +868,7 @@ RETURN p.person.name |=== | +p.person.name+ | +"Anne"+ + 1+d|Rows: 1 |=== @@ -896,6 +898,7 @@ RETURN a[$myKey] AS result |=== | +result+ | +"Anne"+ + 1+d|Rows: 1 |=== @@ -930,6 +933,7 @@ RETURN [1,2,3,4,5] + [6,7] AS myList |=== | +myList+ | +[1,2,3,4,5,6,7]+ + 1+d|Rows: 1 |=== @@ -948,6 +952,7 @@ RETURN [1,2,3,4,5] || [6,7] AS myList |=== | myList | [1,2,3,4,5,6,7] + 1+d|Rows: 1 |=== @@ -971,6 +976,7 @@ RETURN number | +number+ | +2+ | +3+ + 1+d|Rows: 2 |=== @@ -997,6 +1003,7 @@ If the left-hand operator had been `[1, 2]` instead of `[2, 1]`, the query would |=== | +inList+ | +true+ + 1+d|Rows: 1 |=== @@ -1015,6 +1022,7 @@ However, `IN` evaluates to `false` as the right-hand operand does not contain an |=== | +inList+ | +false+ + 1+d|Rows: 1 |=== @@ -1047,6 +1055,7 @@ The square brackets will extract the elements from the start index `1`, and up t |=== | +result+ | +["John","Bill"]+ + 1+d|Rows: 1 |=== @@ -1076,6 +1085,7 @@ RETURN names[$myIndex] AS result |=== | +result+ | +"John"+ + 1+d|Rows: 1 |=== @@ -1097,6 +1107,7 @@ RETURN 3 IN l[0] AS result |=== | +result+ | +true+ + 1+d|Rows: 1 |=== diff --git a/modules/ROOT/pages/values-and-types/temporal.adoc b/modules/ROOT/pages/values-and-types/temporal.adoc index 2f0384ce4..7f82df6ce 100644 --- a/modules/ROOT/pages/values-and-types/temporal.adoc +++ b/modules/ROOT/pages/values-and-types/temporal.adoc @@ -492,7 +492,6 @@ For more information, see the xref::values-and-types/temporal.adoc#cypher-tempor | | | - |=== From 2f6394ef5f1fd8b9546e6cb5216817afb4eb9997 Mon Sep 17 00:00:00 2001 From: hvub Date: Mon, 10 Feb 2025 22:35:53 +0100 Subject: [PATCH 77/77] remove paragraph --- modules/ROOT/pages/clauses/with.adoc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/modules/ROOT/pages/clauses/with.adoc b/modules/ROOT/pages/clauses/with.adoc index 0aa2b0952..42b4cd568 100644 --- a/modules/ROOT/pages/clauses/with.adoc +++ b/modules/ROOT/pages/clauses/with.adoc @@ -25,10 +25,6 @@ Another use is to filter on aggregated values. `WITH` is used to introduce aggregates which can then be used in predicates in `WHERE`. These aggregate expressions create new bindings in the results. -`WITH` is also used to separate reading from updating of the graph. -Every part of a query must be either read-only or write-only. -When going from a writing part to a reading part, the switch must be done with a `WITH` clause. - image:graph_with_clause.svg[] ////