From c4de60d02f9357aa1c7d053fe980e40d9763270f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Mon, 14 Oct 2024 12:42:58 +0200 Subject: [PATCH 01/93] Clarify CALL subquery ambiguities (#1060) --- modules/ROOT/images/call_subquery_graph.svg | 10 +- .../ROOT/pages/subqueries/call-subquery.adoc | 102 ++++++++---------- 2 files changed, 50 insertions(+), 62 deletions(-) diff --git a/modules/ROOT/images/call_subquery_graph.svg b/modules/ROOT/images/call_subquery_graph.svg index 932cf79da..e7e2e2629 100644 --- a/modules/ROOT/images/call_subquery_graph.svg +++ b/modules/ROOT/images/call_subquery_graph.svg @@ -1,9 +1,9 @@ - - + + - - + + - + diff --git a/modules/ROOT/pages/subqueries/call-subquery.adoc b/modules/ROOT/pages/subqueries/call-subquery.adoc index 44d2001c9..0461834ce 100644 --- a/modules/ROOT/pages/subqueries/call-subquery.adoc +++ b/modules/ROOT/pages/subqueries/call-subquery.adoc @@ -30,14 +30,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), @@ -92,7 +87,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 ---- @@ -139,7 +133,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})] @@ -432,60 +426,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 |=== @@ -495,8 +489,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 ==== @@ -590,13 +584,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: Tue, 15 Oct 2024 07:49:29 +0100 Subject: [PATCH 02/93] 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 c0be0b4157761889b45b93c058d7fae55c56169f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Oct 2024 08:53:25 +0200 Subject: [PATCH 03/93] Bump express from 4.21.0 to 4.21.1 in the dev-dependencies group (#1061) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the dev-dependencies group with 1 update: [express](https://github.com/expressjs/express). Updates `express` from 4.21.0 to 4.21.1
Release notes

Sourced from express's releases.

4.21.1

What's Changed

Full Changelog: https://github.com/expressjs/express/compare/4.21.0...4.21.1

Changelog

Sourced from express's changelog.

4.21.1 / 2024-10-08

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=express&package-manager=npm_and_yarn&previous-version=4.21.0&new-version=4.21.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jens Pryce-Åklundh <112686610+JPryce-Aklundh@users.noreply.github.com> --- package-lock.json | 30 +++++++++++++++--------------- package.json | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index fb8fd9d50..7111aee2d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,7 @@ "asciidoctor-kroki": "^0.18.1" }, "devDependencies": { - "express": "^4.21.0", + "express": "^4.21.1", "nodemon": "^3.1.7" } }, @@ -760,9 +760,9 @@ } }, "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", "dev": true, "engines": { "node": ">= 0.6" @@ -933,9 +933,9 @@ } }, "node_modules/express": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", - "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", "dev": true, "dependencies": { "accepts": "~1.3.8", @@ -943,7 +943,7 @@ "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.6.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -3110,9 +3110,9 @@ } }, "cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", "dev": true }, "cookie-signature": { @@ -3234,9 +3234,9 @@ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" }, "express": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", - "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", "dev": true, "requires": { "accepts": "~1.3.8", @@ -3244,7 +3244,7 @@ "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.6.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", diff --git a/package.json b/package.json index 6fa63e771..527fcd494 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "asciidoctor-kroki": "^0.18.1" }, "devDependencies": { - "express": "^4.21.0", + "express": "^4.21.1", "nodemon": "^3.1.7" }, "overrides": { From 942baaba5d423daca860e3566316604373013374 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 04/93] 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 42f14576aaded5f0591226523d11f9f306105931 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 05/93] 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 ab80e086391779440928e4f7ddd68a4c904652e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Thu, 17 Oct 2024 10:46:35 +0200 Subject: [PATCH 06/93] Restructure Constraints section (#1041) Cheat sheet PR: https://github.com/neo4j/docs-cheat-sheet/pull/196 Ops Manual PR: https://github.com/neo4j/docs-operations/pull/1874 --------- 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 | 1826 ++++++++++ modules/ROOT/pages/constraints/syntax.adoc | 273 +- ...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, 1964 insertions(+), 3306 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..bcd24e97b --- /dev/null +++ b/modules/ROOT/pages/constraints/managing-constraints.adoc @@ -0,0 +1,1826 @@ +: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[] += 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`. label:new[Introduced in 5.7] + +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. +---- + +[NOTE] +The detailed statistics view currently says `Unique constraints added: 1`. +It will be updated to say `Node property uniqueness constraints added: 1` in a future version of Neo4j. + +====== + + +.Create a relationship property uniqueness constraint on a single property label:new[Introduced in 5.7] +====== + +.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. +---- + +[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 a future version of Neo4j. + +====== + +[[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`. label:new[Introduced in 5.7] + +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 label:new[Introduced in 5.7] +====== + +.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 label--new-5.9] +[[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. +---- + +====== + +[role=label--new-5.11] +[[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` 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]. + +[[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`. label:new[Introduced in 5.7] + +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 label:new[Introduced in 5.7] +====== + +.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`. label:new[Introduced in 5.7] + +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 label:new[Introduced in 5.7] +====== + +.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. +---- + +====== + + +[role=label--new-5.16] +[[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. +As of Neo4j 5.17, an informational notification is instead 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 UNIQUENESS', schema=()-[:SEQUEL_OF {order}]-(), ownedIndex=4 )'. +---- + +[NOTE] +The constraint type will be updated to say `RELATIONSHIP PROPERTY UNIQUENESS` in a future version of Neo4j. + +====== + +.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='UNIQUENESS', schema=(:Book {isbn}), ownedIndex=2 ) +---- + +[NOTE] +The constraint type will be updated to say `NODE PROPERTY UNIQUENESS` in a future version of Neo4j. + +====== + +.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" | "UNIQUENESS" | "NODE" | ["Book"] | ["isbn"] | "book_isbn" | NULL | +| 7 | "book_title_year" | "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" | "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_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 | ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +---- + +====== + +.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" | "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" | "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" | "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_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_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_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" | ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +---- +====== + +[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 a future version of Neo4j. +Node property uniqueness constraints will be updated to `NODE_PROPERTY_UNIQUENESS` and relationship property uniqueness constraints to `RELATIONSHIP_PROPERTY_UNIQUENESS`. + +[[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 (`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[] + +[NOTE] +`UNIQUENESS` and `RELATIONSHIP_UNIQUENESS` will be updated to say `NODE_PROPERTY_UNIQUENESS` and `RELATIONSHIP_PROPERTY_UNIQUENESS` respectively in a future version of Neo4j. +| 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[] label:new[Introduced in 5.9] +| 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. +---- + +====== + +[role=label--new-5.16] +[[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. +As of Neo4j 5.17, 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..1267b5ba9 100644 --- a/modules/ROOT/pages/constraints/syntax.adoc +++ b/modules/ROOT/pages/constraints/syntax.adoc @@ -4,13 +4,21 @@ = 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. @@ -22,17 +30,11 @@ For constraints that are backed by an index, the index provider for the backing 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]. -==== +[[create-property-uniqueness-constraints]] +=== Create property uniqueness constraints -[[constraints-syntax-create-node-unique]] -=== Node property uniqueness constraint - -This command creates a property uniqueness constraint on nodes with the specified label and properties. - -[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 label:new[Introduced in 5.7] +[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 label:new[Introduced in 5.7] +[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 label--new-5.9] +[[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"]"-() @@ -206,20 +151,19 @@ Where `` is one of the following property types: * `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]. +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 label:new[Introduced in 5.7] +[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 label:new[Introduced in 5.7] +[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. - +An index provider can be specified using the `OPTIONS` clause. -[[constraints-syntax-drop]] -== Syntax for dropping constraints +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]. -Dropping a constraint is done by specifying the name of the constraint. -[source, syntax, role="noheader", indent=0] ----- -DROP CONSTRAINT constraint_name [IF EXISTS] ----- +[[list-constraints]] +== SHOW CONSTRAINTS -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. +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] -==== -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]. -==== - - -[[constraints-syntax-list]] -== Syntax for listing constraints - -List constraints in the database, either all or filtered on constraint type. - -[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]] @@ -397,54 +318,28 @@ label:new[Introduced in 5.7] |=== +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]. -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 +[[drop-constraint]] +== DROP CONSTRAINT -| entityType -| Type of entities this constraint represents (nodes or relationship). label:default-output[] -| STRING - -| 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. +As of Neo4j 5.17, an informational notification is instead 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 d5442a8ab..a61b1f14b 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -1178,7 +1178,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` @@ -1260,7 +1260,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` @@ -1418,7 +1418,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` @@ -1568,7 +1568,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[] @@ -5030,7 +5030,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| @@ -5142,7 +5142,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 1073249259c283ec4bb4ba8b060cbf6e0fa7eab6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Thu, 17 Oct 2024 12:00:22 +0200 Subject: [PATCH 07/93] Add new label to type constraints and page alias (#1066) --- modules/ROOT/pages/constraints/index.adoc | 2 +- modules/ROOT/pages/constraints/managing-constraints.adoc | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/ROOT/pages/constraints/index.adoc b/modules/ROOT/pages/constraints/index.adoc index f906e317b..7e5341bba 100644 --- a/modules/ROOT/pages/constraints/index.adoc +++ b/modules/ROOT/pages/constraints/index.adoc @@ -7,7 +7,7 @@ The following constraints are available in Neo4j: * *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[] +* *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:new[Introduced in 5.9] 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[] 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[]. diff --git a/modules/ROOT/pages/constraints/managing-constraints.adoc b/modules/ROOT/pages/constraints/managing-constraints.adoc index bcd24e97b..98c48b091 100644 --- a/modules/ROOT/pages/constraints/managing-constraints.adoc +++ b/modules/ROOT/pages/constraints/managing-constraints.adoc @@ -1,4 +1,5 @@ :description: Information about creating, listing, and dropping Neo4j's constraints. +:page-aliases: constraints/examples.adoc include::https://raw.githubusercontent.com/neo4j-graphacademy/courses/main/asciidoc/courses/cypher-indexes-constraints/ad.adoc[] = Create, show, and drop constraints @@ -7,7 +8,7 @@ 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-property-type-constraints[Property type constraints] label:new[Introduced in 5.9] label:enterprise-edition[] * xref:constraints/managing-constraints.adoc#create-key-constraints[Key constraints] label:enterprise-edition[] From 1085290d1b21af5672afc67f86e7b96f9c18c99f 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 08/93] 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 1a55a02ccfe50598a72139afeb11d455c7e81e49 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 09/93] 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 6d4287c79cb5d46928e89a5b308e3e31fc2dacdf 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 10/93] 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 1a428e02e518920eec94750c9411ade39226185f 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 11/93] 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 5f6f6ee3c0634807e5b784866c7389a834f76203 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 12/93] 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 98c48b091..148258f0f 100644 --- a/modules/ROOT/pages/constraints/managing-constraints.adoc +++ b/modules/ROOT/pages/constraints/managing-constraints.adoc @@ -1543,6 +1543,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" | "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 720b73285dfbdf8bee17a9e0d3621653a3e1f997 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 13/93] 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 24d12435b..015a83712 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 1aae0d50634c4417b440c69398456f741dead341 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:01:12 +0200 Subject: [PATCH 14/93] Document max identifier length (#1077) --- .../pages/appendix/gql-conformance/index.adoc | 4 ++-- .../gql-conformance/supported-optional.adoc | 5 ++++ ...ions-additions-removals-compatibility.adoc | 23 +++++++++++++++++-- modules/ROOT/pages/syntax/naming.adoc | 8 +++++++ 4 files changed, 36 insertions(+), 4 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 a61b1f14b..aed06bb68 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -36,6 +36,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"] @@ -53,8 +74,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..d4b9357c1 100644 --- a/modules/ROOT/pages/syntax/naming.adoc +++ b/modules/ROOT/pages/syntax/naming.adoc @@ -71,3 +71,11 @@ Here are the recommended naming conventions: | Relationship types | Upper-case, using underscore to separate words | `:OWNS_VEHICLE` rather than `:ownsVehicle` etc. |=== +[role=label--new-5.25] +[[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 ad1e5fd921a8b311634f7bb14ba4d67f8cb6c1df 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:25:51 +0200 Subject: [PATCH 15/93] Add missing curly bracket (#1079) --- .../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 aed06bb68..db0c05224 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -48,7 +48,7 @@ label:functionality[] label:updated[] [source, cypher, role="noheader"] ---- -CREATE (n:Label {property: 'name'}, +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. From ea86dc950b7971b4107d726868a5f1e8e7a7463d 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 16/93] 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 17/93] 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 cdec96a8ffebdd83e047247c540689349aba0cdc 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 14:58:08 +0100 Subject: [PATCH 18/93] Remove mentions of Neo4j 6.0 (#1086) --- modules/ROOT/pages/functions/scalar.adoc | 8 ++++---- modules/ROOT/pages/syntax/naming.adoc | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/modules/ROOT/pages/functions/scalar.adoc b/modules/ROOT/pages/functions/scalar.adoc index 459102044..8baa1844d 100644 --- a/modules/ROOT/pages/functions/scalar.adoc +++ b/modules/ROOT/pages/functions/scalar.adoc @@ -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). +As a result, any new subtypes introduced after the release of Neo4j 5.13 will not be returned by the `valueType()` function until the next major release of Neo4j. -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. +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. -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: +With this in mind, the below list contains all supported types (as of Neo4j 5.13) displayed by the `valueType()` function until the next major release of Neo4j: * Predefined types ** `NOTHING` diff --git a/modules/ROOT/pages/syntax/naming.adoc b/modules/ROOT/pages/syntax/naming.adoc index d4b9357c1..6038ca3db 100644 --- a/modules/ROOT/pages/syntax/naming.adoc +++ b/modules/ROOT/pages/syntax/naming.adoc @@ -51,7 +51,8 @@ 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. +Several special characters have been deprecated and will require escaping in the next major release of Neo4j. +For the comprehensive list of deprecated characters, see the xref::deprecations-additions-removals-compatibility.adoc#cypher-deprecations-additions-removals-5.15[deprecations page]. ==== == Scoping and namespace rules From e594babecb00b3ad2372a0a91544790248e0c670 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/93] 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 d61392bda28e32674d48422f3e4ce22dc8862c32 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 10:32:40 +0100 Subject: [PATCH 20/93] update antora for 5.26 (#1091) --- antora.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/antora.yml b/antora.yml index ef51b64c7..b13b62440 100644 --- a/antora.yml +++ b/antora.yml @@ -7,5 +7,5 @@ nav: asciidoc: attributes: neo4j-version: '5' - neo4j-version-minor: '5.25' - neo4j-version-exact: '5.25.0' + neo4j-version-minor: '5.26' + neo4j-version-exact: '5.26.0' From dc20574e382e4ebe9676246b0e49a184425121ce 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/93] 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 2976c3666..76ae6984c 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 929d72d90..54c183b3c 100644 --- a/modules/ROOT/pages/functions/database.adoc +++ b/modules/ROOT/pages/functions/database.adoc @@ -26,11 +26,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 9404b48f5..85f7fd526 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. @@ -194,10 +200,12 @@ For more information, see xref:subqueries/call-subquery.adoc#import-variables[CA 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 8baa1844d..cc17fdc3a 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. @@ -1245,11 +1289,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 68725bd94..fef3a40d7 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 13:20:28 +0100 Subject: [PATCH 22/93] Document change in behaviour for db.schema.nodeTypeProperties() and db.schema.relTypeProperties() (#1063) 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. https://github.com/neo4j/docs-cypher/pull/1062 --------- 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 db0c05224..e161d05f1 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -16,6 +16,30 @@ 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.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 e76ca0a2886f4054d8e438b5e2a9c2a772b6aa3c Mon Sep 17 00:00:00 2001 From: Hannes Sandberg Date: Thu, 31 Oct 2024 14:16:04 +0100 Subject: [PATCH 23/93] Adding the new functionality of property-based access control to list of new features (#1070) 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 +++++++++++++++++++ 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 e161d05f1..c58331a99 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -40,6 +40,26 @@ In an upcoming major release of Neo4j, this will be updated to represent the pos For all available Cypher types, see the section on xref::values-and-types/property-structural-constructed.adoc#types-synonyms[types and their synonyms]. |=== + +=== 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 ab342a0bb3698e4a80dbed4bfef93f6ae3010fd5 Mon Sep 17 00:00:00 2001 From: Lasse Heemann <7661319+l-heemann@users.noreply.github.com> Date: Thu, 31 Oct 2024 14:48:51 +0100 Subject: [PATCH 24/93] Add entry in additions/removals about parameters in CREATE/ALTER DB TOPOLOGY (#1082) 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> --- ...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 c58331a99..e54e38a74 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -48,6 +48,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 6efbb2a78f3d30b2d5b38d3a5e31301edd35e980 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/93] Fix version exact roles (#1095) --- .../pages/appendix/tutorials/advanced-query-tuning.adoc | 6 +++--- 1 file changed, 3 insertions(+), 3 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..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,10 +936,10 @@ 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` -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`. ==== From 36159ae18d36601f8770174a42e4fdc5708dc148 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/93] 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 e54e38a74..c0f2277fe 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -26,6 +26,81 @@ Replacement syntax for deprecated and removed features are also indicated. | 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[] @@ -69,7 +144,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 546c4eb243cd191d336f9555bee62ce6950a63ff Mon Sep 17 00:00:00 2001 From: emmaholmbergohlsson Date: Tue, 5 Nov 2024 15:31:23 +0100 Subject: [PATCH 27/93] Remove use of index-provider option (#1096) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Supplying the index-provider option will no longer have any effect, and a user should not specify it. From 5.26 using the index-provider option will generate a warning. The index-provider has never controlled index behaviour in the 5.x series, and the latest provider will always be the best one. --------- Co-authored-by: Jens Pryce-Åklundh <112686610+JPryce-Aklundh@users.noreply.github.com> --- .../constraints/managing-constraints.adoc | 62 ------------------- 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(+), 131 deletions(-) diff --git a/modules/ROOT/pages/constraints/managing-constraints.adoc b/modules/ROOT/pages/constraints/managing-constraints.adoc index 148258f0f..283d567e3 100644 --- a/modules/ROOT/pages/constraints/managing-constraints.adoc +++ b/modules/ROOT/pages/constraints/managing-constraints.adoc @@ -910,7 +910,6 @@ Constraint already exists: Constraint( id=7, name='book_title_year', type='UNIQU === 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]] @@ -994,60 +993,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 @@ -1509,7 +1454,6 @@ SHOW CONSTRAINTS | 10 | "author_name" | "NODE_PROPERTY_EXISTENCE" | "NODE" | ["Author"] | ["name"] | NULL | NULL | | 3 | "book_isbn" | "UNIQUENESS" | "NODE" | ["Book"] | ["isbn"] | "book_isbn" | NULL | | 7 | "book_title_year" | "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" | @@ -1519,7 +1463,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_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 | @@ -1549,7 +1492,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" | "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" | "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" | @@ -1559,7 +1501,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_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_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_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" | @@ -1594,7 +1535,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 | @@ -1627,7 +1567,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_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 | @@ -1669,7 +1608,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_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" | diff --git a/modules/ROOT/pages/constraints/syntax.adoc b/modules/ROOT/pages/constraints/syntax.adoc index 1267b5ba9..ba695630f 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. As of Neo4j 5.17, 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 label:new[Introduced in 5.7] @@ -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 label:new[Introduced in 5.7] @@ -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 label--new-5.9] @@ -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 label:new[Introduced in 5.7] @@ -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 label:new[Introduced in 5.7] @@ -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 c0f2277fe..8f05eae70 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -26,6 +26,19 @@ Replacement syntax for deprecated and removed features are also indicated. | 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 2487e32ad..9a71c9a5b 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. As of Neo4j 5.17, an informational notification is instead 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] @@ -294,7 +292,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]] @@ -366,30 +363,13 @@ As of Neo4j 5.17, an informational notification is instead 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]] @@ -554,7 +534,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]] @@ -844,7 +824,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 @@ -887,7 +866,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 13c8334b2..fd73ea3c4 100644 --- a/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc +++ b/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc @@ -71,7 +71,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. @@ -350,9 +350,8 @@ 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`. +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 baede5cba..47183f194 100644 --- a/modules/ROOT/pages/indexes/syntax.adoc +++ b/modules/ROOT/pages/indexes/syntax.adoc @@ -27,8 +27,8 @@ As of Neo4j 5.17, an informational notification is instead returned showing the 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, as of Neo4j 5.1, 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[, …] “}”] ---- -As of Neo4j 5.18, 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. From b4fc0fe944529fa8fa0bb997c873b59e41d415db 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:43:00 +0100 Subject: [PATCH 28/93] Update README to include documenting changes to language and GQL (#1100) --- README.adoc | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/README.adoc b/README.adoc index 71281a24f..70c2df006 100644 --- a/README.adoc +++ b/README.adoc @@ -1,5 +1,14 @@ = 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 +48,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 @@ -68,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 `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. + +[[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-5.x] +== 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 5.x] + +`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 5.x, `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 d30abc01d02bad2b6fcecb84c8905ea62f6bab8f 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 29/93] 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 9a71c9a5b..bbca22600 100644 --- a/modules/ROOT/pages/indexes/search-performance-indexes/managing-indexes.adoc +++ b/modules/ROOT/pages/indexes/search-performance-indexes/managing-indexes.adoc @@ -850,24 +850,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 647bb9a65..1ec0fdd97 100644 --- a/modules/ROOT/pages/indexes/semantic-indexes/full-text-indexes.adoc +++ b/modules/ROOT/pages/indexes/semantic-indexes/full-text-indexes.adoc @@ -327,13 +327,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 fd73ea3c4..2391648ab 100644 --- a/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc +++ b/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc @@ -306,11 +306,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. @@ -351,6 +351,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 24f592c708b3a4c5714a88d687fb8fead705926d 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 30/93] 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 8f05eae70..2ca05be16 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -126,6 +126,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 9f21e0470e7feb8e8d8a6bdcaad6df76ee24881e 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 31/93] 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 df859d1cb..3b8490dfe 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 df29ec0caacf0adee6ecf5476cbb636821d2d2bf 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 32/93] 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 3db5ecef0..cd2cea108 100644 --- a/modules/ROOT/pages/functions/vector.adoc +++ b/modules/ROOT/pages/functions/vector.adoc @@ -35,6 +35,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. |=== @@ -63,6 +65,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 312d90814be75a5d410eb2ef782af5085563e7b2 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 33/93] 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 24050d9bb..ddd80f24d 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 dbbfb5cd58e7d1c02cc711eb8689c7599c7277f9 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 34/93] 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 2ca05be16..6250cc475 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -201,7 +201,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 @@ -239,7 +239,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 2d3c71b864a160977b7dd1b8ee240107b9c4d667 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 35/93] 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 6038ca3db..4f70b12f7 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 fbbc11d0fa3a2d74c86ecc635afaf5327a0a6a1b 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 36/93] 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 6250cc475..9decf9b67 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -49,8 +49,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`++ { ... }]->()` @@ -78,8 +78,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[] @@ -91,8 +91,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` @@ -107,8 +107,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` @@ -1000,9 +1000,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| @@ -1013,8 +1013,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', @@ -2682,7 +2682,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 4f70b12f7..a483e62f7 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 1abbd2c831eab1649e9a7d9322d44412b6742133 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 37/93] 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 c72457853..cf83ee2a5 100644 --- a/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc +++ b/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc @@ -665,7 +665,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 afeeb5a61d9cf0093d84d72dd217f7bf723b946c Mon Sep 17 00:00:00 2001 From: Neil Dewhurst Date: Fri, 15 Nov 2024 16:26:17 +0000 Subject: [PATCH 38/93] Replace NODES ad with developer survey (#1112) --- publish.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/publish.yml b/publish.yml index 49ad0451a..1184d3ccc 100644 --- a/publish.yml +++ b/publish.yml @@ -60,11 +60,10 @@ asciidoc: 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 + # Developer survey + page-ad-icon: ~ + page-ad-title: Neo4j Developer Survey + page-ad-description: Your input matters! Share your Feedback page-ad-underline-role: button - page-ad-underline: Register \ No newline at end of file + page-ad-underline: Start Here + page-ad-link: https://neo4j.typeform.com/to/E6yOZ2Py?utm_source=GA&utm_medium=blurb&utm_campaign=survey \ No newline at end of file From d6b2f98a70aa03e91c33bf5d85fe2209eabbd0e9 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 14:48:51 +0100 Subject: [PATCH 39/93] Dynamic labels/types (#1098) 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 | 53 ++++++- modules/ROOT/pages/clauses/load-csv.adoc | 40 +++++ modules/ROOT/pages/clauses/match.adoc | 139 +++++++++++++++++- modules/ROOT/pages/clauses/merge.adoc | 57 +++++++ modules/ROOT/pages/clauses/remove.adoc | 14 +- modules/ROOT/pages/clauses/set.adoc | 14 +- ...ions-additions-removals-compatibility.adoc | 41 +++++- 9 files changed, 425 insertions(+), 22 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 9749ac375..f2ee2cd58 100644 --- a/modules/ROOT/pages/clauses/create.adoc +++ b/modules/ROOT/pages/clauses/create.adoc @@ -205,10 +205,61 @@ Nodes created: 2 + Properties set: 4 |=== +[role=label--new-5.26] +[[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,126 @@ 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[]. +[role=label--new-5.26] +[[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 +84,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] ---- @@ -131,18 +132,19 @@ Labels removed: 1 |=== [role=label--new-5.24] -[[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 6976c8abe..d90a891d1 100644 --- a/modules/ROOT/pages/clauses/set.adoc +++ b/modules/ROOT/pages/clauses/set.adoc @@ -162,10 +162,12 @@ Properties set: 1 [role=label--new-5.24] -[[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] ---- @@ -541,15 +543,15 @@ Labels added: 1 |=== [role=label--new-5.24] -[[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 @@ -629,7 +631,7 @@ Labels added: 2 |=== [role=label--new-5.24] -[[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 9decf9b67..432f5b253 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -184,6 +184,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 @@ -319,7 +358,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 36a448629da4130dcfb91d42c82d037a56fa28ae 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 40/93] 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 2391648ab..61a986b33 100644 --- a/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc +++ b/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc @@ -258,7 +258,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 30f87f5899898a63cfc972b8afbaffa52d916d38 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 41/93] 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 bbca22600..53b35afa8 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 1ec0fdd97..f2adb3aa6 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]. @@ -134,13 +134,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 61a986b33..b5d4f9bdb 100644 --- a/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc +++ b/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc @@ -196,6 +196,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 e5de1b6261a1830863ed0d407c48047418326675 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 42/93] 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 8c0e2ebc8d476ae405b7cee8845dabc53c71152a 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:29:56 +0100 Subject: [PATCH 43/93] Document the availability of graph.byelementid on standard databases (#1120) --- .../gql-conformance/additional-cypher.adoc | 5 ++++- modules/ROOT/pages/clauses/use.adoc | 14 ++++++++++---- ...recations-additions-removals-compatibility.adoc | 12 ++++++++++++ modules/ROOT/pages/functions/graph.adoc | 14 ++++++++++++-- 4 files changed, 38 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..32f648563 100644 --- a/modules/ROOT/pages/appendix/gql-conformance/additional-cypher.adoc +++ b/modules/ROOT/pages/appendix/gql-conformance/additional-cypher.adoc @@ -206,7 +206,10 @@ 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. +As of Neo4j 5.26, it is supported on both link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/[standard and composite databases]. +On earlier versions, it is only supported on composite databases. | 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 29c744c72..1d5643469 100644 --- a/modules/ROOT/pages/clauses/use.adoc +++ b/modules/ROOT/pages/clauses/use.adoc @@ -93,7 +93,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`: @@ -114,12 +114,18 @@ USE graph.byName($graphName) MATCH (n) RETURN n ---- +[role=label--new-5.13] [[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. -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. +As of Neo4j 5.26, it is supported on both standard and composite databases (on previous versions it is only available on composite databases). + +[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 432f5b253..20a06a0cf 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -160,6 +160,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 85f7fd526..839231680 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()+ ====== @@ -183,7 +189,7 @@ For more information, see xref:subqueries/call-subquery.adoc#import-variables[CA .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` @@ -192,6 +198,10 @@ For more information, see xref:subqueries/call-subquery.adoc#import-variables[CA .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. +| As of Neo4j 5.26, `graph.byElementId()` is supported on both link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/[standard and composite databases]. +On earlier versions, it is only supported on 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 315c3eb3c503ab8ba6eb8dd4f816765b21e615f6 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 44/93] 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 20a06a0cf..12273391f 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -193,6 +193,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 1c27d4594bb1f991c1264ca11ef50be2bf7e56c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Wed, 27 Nov 2024 12:50:51 +0100 Subject: [PATCH 45/93] Add cheat sheet tags for dynamic labels/types (#1117) (Also fixes 2 minor errors) Corresponding Cheat sheet PR: https://github.com/neo4j/docs-cheat-sheet/pull/202 --- modules/ROOT/pages/clauses/create.adoc | 2 ++ modules/ROOT/pages/clauses/load-csv.adoc | 6 ++++-- modules/ROOT/pages/clauses/match.adoc | 8 +++++++- modules/ROOT/pages/clauses/merge.adoc | 2 ++ 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/modules/ROOT/pages/clauses/create.adoc b/modules/ROOT/pages/clauses/create.adoc index f2ee2cd58..5b81fd75b 100644 --- a/modules/ROOT/pages/clauses/create.adoc +++ b/modules/ROOT/pages/clauses/create.adoc @@ -235,6 +235,7 @@ This is because a relationship can only have exactly one type. ---- .Create nodes and relationships using dynamic node labels and relationship types +// tag::clauses_create_dynamic_create[] [source, cypher] ---- CREATE (greta:$($nodeLabels) {name: 'Greta Gerwig'}) @@ -243,6 +244,7 @@ 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 ---- +// end::clauses_create_dynamic_create[] .Result [role="queryresult",options="footer",cols="4* Protecting against Cypher injection]). .bands-with-headers.csv -[source, csv, filename="artists-with-headers.csv"] +[source, csv, filename="bands-with-headers.csv"] ---- Id,Label,Name 1,Band,The Beatles @@ -319,12 +319,14 @@ Id,Label,Name ---- .Query -[source, cypher, role=test-skip] +// tag::clauses_load_csv_dynamic_columns[] +[source, cypher] ---- LOAD CSV WITH HEADERS FROM 'file:///bands-with-headers.csv' AS line MERGE (n:$(line.Label) {name: line.Name}) RETURN n AS bandNodes ---- +// end::clauses_load_csv_dynamic_columns[] .Result [role="queryresult",options="header,footer",cols="1*() RETURN relationshipType, count(r) AS relationshipCount ---- +// end::clauses_match_dynamic_match_variable[] + .Result [role="queryresult",options="header,footer",cols="2*(m:Movie {title: movieTitle}) RETURN greta.name AS name, labels(greta) AS labels, type(rel) AS relType, collect(m.title) AS movies ---- +// end::clauses_merge_dynamic_merge[] .Result [role="queryresult",options="footer",cols="3* Date: Fri, 29 Nov 2024 11:39:11 +0100 Subject: [PATCH 46/93] Group all query plan operators (#1122) --- .../planning-and-tuning/execution-plans.adoc | 2 +- .../operators/operators-detail.adoc | 5139 ++++++++--------- .../planning-and-tuning/query-tuning.adoc | 2 +- 3 files changed, 2509 insertions(+), 2634 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 4f9d332ed..fb0284afc 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 [role=label--new-5.17] [[query-plan-partitioned-all-nodes-scan]] -== Partitioned All Nodes Scan -// PartitionedAllNodesScan -// New in 5.17 +=== 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-minor} 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 ---- ====== [role=label--new-5.17] -[[query-plan-partitioned-directed-relationship-index-scan]] -== Partitioned Directed Relationship Index Scan -// PartitionedDirectedRelationshipIndexScan -// New in 5.17 +[[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,33 @@ 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 | 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. +[role=label--new-5.5] +[[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 @@ -297,39 +304,36 @@ 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 ---- ====== [role=label--new-5.17] -[[query-plan-partitioned-undirected-relationship-index-scan]] -== Partitioned Undirected Relationship Index Scan -// PartitionedUndirectedRelationshipIndexScan -// New in 5.17 +[[query-plan-partitioned-intersection-node-by-labels-scan]] +=== Partitioned Intersection Node By Labels Scan -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 @@ -343,38 +347,36 @@ 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. +[role=label--new-5.21] +[[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 @@ -388,39 +390,35 @@ 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 ---- ====== -[role=label--new-5.17] -[[query-plan-partitioned-directed-relationship-index-seek]] -== Partitioned Directed Relationship Index Seek -// PartitionedDirectedRelationshipIndexSeek -// New in 5.17 +[role=label--new-5.21] +[[query-plan-partitioned-subtraction-node-by-labels-scan]] +=== Partitioned Subtraction Node By Labels Scan -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 @@ -434,38 +432,32 @@ 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 @@ -479,38 +471,35 @@ 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. +[role=label--new-5.17] +[[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 @@ -524,37 +513,42 @@ 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 | ++-----------------------------------+----+------------------------------------+----------------+------+---------+------------------------+-----------+---------------+ -[[query-plan-directed-relationship-by-element-id-seek]] -== Directed Relationship By Element Id Seek -// DirectedRelationshipByElementIdSeek +Total database accesses: 35 +---- -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. +====== +[[query-plan-node-index-contains-scan]] +=== Node Index Contains Scan -.DirectedRelationshipByElementIdSeek +//// +[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. + +.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 @@ -568,36 +562,37 @@ 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 @@ -611,37 +606,43 @@ 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 @@ -655,37 +656,37 @@ 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. +[role=label--new-5.17] +[[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 +694,42 @@ RETURN r, n1 ---- Planner COST -Runtime PIPELINED +Runtime PARALLEL 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. +[role=label--new-5.3] +[[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 @@ -751,38 +743,35 @@ 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 @@ -796,38 +785,38 @@ 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 +830,37 @@ 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 | | | | | -| | +---------------------------------------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +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 ---- ====== +[role=label--new-5.17] +[[query-plan-partitioned-node-index-seek]] +=== Partitioned Node Index Seek -[[query-plan-undirected-relationship-index-ends-with-scan]] -== Undirected Relationship Index Ends With Scan -// UndirectedRelationshipIndexEndsWithScan +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 `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. - -.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 +868,51 @@ RETURN r ---- Planner COST -Runtime PIPELINED +Runtime PARALLEL 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 | 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 +926,50 @@ 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 | -+---------------------------------------+----------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++----------------------+------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| 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 ---- ====== -[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. +[[query-plan-multi-node-index-seek]] +=== Multi Node Index Seek -.PartitionedDirectedRelationshipIndexSeekByRange +//// +[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)`. + + +.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 +977,50 @@ RETURN candidate ---- Planner COST -Runtime PARALLEL +Runtime PIPELINED 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 | -+--------------------------------------------------+----+----------------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------------+ ++---------------------+-----------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| 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 +1034,42 @@ 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 | -+-----------------------------------------+---------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++------------------------------+-----------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| 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 ---- ====== -[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. +[[query-plan-node-index-seek-by-range]] +=== Node Index Seek By Range -.PartitionedUndirectedRelationshipIndexSeekByRange +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 ====== .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 +1077,44 @@ RETURN candidate ---- Planner COST -Runtime PARALLEL +Runtime PIPELINED 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 | -+----------------------------------------------------+----+---------------------------------------------------------------------------------------+----------------+------+---------+------------------------+-----------+---------------------+ ++-----------------------+-------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| 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 ---- ====== +[role=label--new-5.17] +[[query-plan-partitioned-node-index-seek-by-range]] +=== Partitioned Node Index Seek By Range -[[query-plan-union-node-by-labels-scan]] -== Union Node By Labels Scan -// UnionNodeByLabelsScan -// New in 5.0 +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 +1122,44 @@ RETURN countryOrLocation ---- Planner COST -Runtime PIPELINED +Runtime PARALLEL 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 | 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 ---- ====== -[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. +[[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`. + + +.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 +1167,27 @@ RETURN countryOrLocation ---- Planner COST -Runtime PARALLEL +Runtime PIPELINED 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 | 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 ----- - -====== - - -[role=label--new-5.5] -[[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-minor} - -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 ----- - -====== - -[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. -====== - -.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-minor} - -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 ----- - -====== - -[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. -====== - -.Query -[source,cypher] ----- -PROFILE -MATCH (locationNotCountry:Location&!Country) -RETURN locationNotCountry ----- - -.Query Plan -[role="queryplan", subs="attributes+"] ----- -Planner COST - -Runtime PIPELINED - -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 | 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 ----- - -====== - -[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. -====== - -.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-minor} - -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 | -+-----------------------------------------+----+--------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------+ ++-----------------------------+----------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| 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: 13, total allocated memory: 262144 +Total database accesses: 1, total allocated memory: 184 ---- ====== [[query-plan-directed-all-relationships-scan]] -== Directed All Relationships Scan -//DirectedAllRelationshipsScan +=== Directed All Relationships Scan The `DirectedAllRelationshipsScan` operator fetches all relationships and their start and end nodes in the database. @@ -1392,8 +1226,7 @@ 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 +=== 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 +1265,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. ====== @@ -1470,7 +1303,7 @@ 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 +=== 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]. @@ -1510,7 +1343,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. @@ -1553,7 +1386,7 @@ 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 +=== Partitioned Directed Relationship Type Scan // PartitionedDirectedRelationshipTypeScan // New in 5.17 @@ -1598,7 +1431,7 @@ Batch size 128 [[query-plan-undirected-relationship-type-scan]] -== Undirected Relationship Type Scan +=== Undirected Relationship Type Scan // UndirectedRelationshipTypeScan The `UndirectedRelationshipTypeScan` operator fetches all relationships and their start and end nodes with a specific type from the relationship type index. @@ -1639,7 +1472,7 @@ 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 +=== Partitioned Undirected Relationship Type Scan // PartitionedUndirectedRelationshipTypeScan // New in 5.17 @@ -1683,7 +1516,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. @@ -1728,7 +1561,7 @@ 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 +=== Partitioned Directed Union Relationship Types Scan // PartitionedDirectedUnionRelationshipTypesScan // New in 5.17 @@ -1776,7 +1609,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. @@ -1821,9 +1654,7 @@ 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 +=== 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. @@ -1866,23 +1697,31 @@ Total database accesses: 37 ---- ====== -[role=label--new-5.3] -[[query-plan-node-by-elementid-seek]] -== Node By ElementId Seek -// NodeByElementIdSeek -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()]. +[[query-plan-directed-relationship-index-scan]] +=== Directed Relationship Index Scan +// DirectedRelationshipIndexScan -.NodeByElementIdSeek +//// +[source, cypher, role=test-setup] +---- +CREATE RANGE INDEX range_worksin_title FOR ()-[r:WORKS_IN]->() ON (r.title) +---- +//// + +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 @@ -1896,36 +1735,37 @@ 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()]. +[role=label--new-5.17] +[[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 +1773,41 @@ RETURN n ---- Planner COST -Runtime PIPELINED +Runtime PARALLEL 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 @@ -1984,30 +1821,27 @@ 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 ---- ====== [role=label--new-5.17] -[[query-plan-partitioned-node-by-label-scan]] -== Partitioned Node By Label Scan -// PartitionedNodeByLabelScan -// New in 5.17 +[[query-plan-partitioned-undirected-relationship-index-scan]] +=== Partitioned Undirected Relationship Index Scan -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 +1849,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 @@ -2030,45 +1865,44 @@ 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 @@ -2082,39 +1916,37 @@ 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 ---- ====== -[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. +[[query-plan-undirected-relationship-index-contains-scan]] +=== Undirected Relationship Index Contains Scan + +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 +1954,43 @@ RETURN location ---- Planner COST -Runtime PARALLEL +Runtime PIPELINED 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 @@ -2182,51 +2004,37 @@ 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 @@ -2240,45 +2048,37 @@ 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 @@ -2292,44 +2092,37 @@ 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 ---- ====== +[role=label--new-5.17] +[[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 `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 `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. -.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 +2130,43 @@ RETURN l ---- Planner COST -Runtime PIPELINED +Runtime PARALLEL 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 ---- ====== -[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. +[[query-plan-undirected-relationship-index-seek]] +=== Undirected Relationship Index Seek +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 +2174,43 @@ RETURN l ---- Planner COST -Runtime PARALLEL +Runtime PIPELINED 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 +2218,42 @@ RETURN t ---- Planner COST -Runtime PIPELINED +Runtime PARALLEL 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 @@ -2488,38 +2267,35 @@ 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 @@ -2533,37 +2309,36 @@ 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 @@ -2577,40 +2352,36 @@ 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 ---- ====== -[role=label--new-5.17] -[[query-plan-partitioned-node-index-scan]] -== Partitioned Node Index Scan -// PartitionedNodeIndexScan -// New in 5.17 +[[query-plan-undirected-relationship-by-id-seek]] +=== Undirected Relationship By Id Seek -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,47 +2389,50 @@ RETURN l ---- Planner COST -Runtime PARALLEL +Runtime PIPELINED 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}) -RETURN p, q +MATCH (candidate: Person)-[r:WORKS_IN]->(location) +WHERE r.duration > 100 +RETURN candidate ---- .Query Plan @@ -2672,17 +2446,208 @@ 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 | 0 | 0 | | | | | -| | +-------------------------------------------------------+----------------+------+---------+----------------+ | | | -| +Apply | | 1 | 0 | 0 | | | | | -| |\ +-------------------------------------------------------+----------------+------+---------+----------------+ | | | -| | +NodeIndexSeek | RANGE INDEX q:Person(name) WHERE name = p.secondName | 1 | 0 | 0 | 2152 | 0/0 | 0.219 | Fused in Pipeline 1 | -| | +-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -| +NodeIndexSeek | RANGE INDEX p:Person(name) WHERE name = $autostring_0 | 1 | 1 | 2 | 120 | 0/1 | 0.236 | In Pipeline 0 | -+------------------+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ ++---------------------------------------+----------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| 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 +---- + +====== + +[role=label--new-5.17] +[[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 +---- + +====== + +[role=label--new-5.17] +[[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 +---- + +.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 | p, q | 1 | 0 | 0 | | | | | +| | +-------------------------------------------------------+----------------+------+---------+----------------+ | | | +| +Apply | | 1 | 0 | 0 | | | | | +| |\ +-------------------------------------------------------+----------------+------+---------+----------------+ | | | +| | +NodeIndexSeek | RANGE INDEX q:Person(name) WHERE name = p.secondName | 1 | 0 | 0 | 2152 | 0/0 | 0.219 | Fused in Pipeline 1 | +| | +-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| +NodeIndexSeek | RANGE INDEX p:Person(name) WHERE name = $autostring_0 | 1 | 1 | 2 | 120 | 0/1 | 0.236 | In Pipeline 0 | ++------------------+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ Total database accesses: 2, total allocated memory: 2216 ---- @@ -2691,8 +2656,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 +2710,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,29 +2766,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] (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 `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 @@ -2832,154 +2795,35 @@ RETURN a; ---- Planner COST -Runtime PIPELINED +Runtime SLOTTED 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 | 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: 24, total allocated memory: 5472 ----- - -====== - - -[[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-minor} - -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-minor} - -+--------------------+-----------------------------------------+----------------+------+---------+------------------------+ -| 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 | -+--------------------+-----------------------------------------+----------------+------+---------+------------------------+ ++--------------------+-----------------------------------------+----------------+------+---------+------------------------+ +| 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 ---- @@ -2988,8 +2832,7 @@ Total database accesses: 165, total allocated memory: 64 [[query-plan-let-anti-semi-apply]] -== Let Anti Semi Apply -// LetAntiSemiApply +=== 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. @@ -3051,8 +2894,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. @@ -3110,8 +2952,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. @@ -3170,8 +3011,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. @@ -3232,8 +3072,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. @@ -3292,29 +3131,81 @@ 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 +Runtime SLOTTED -.Merge +Runtime version {neo4j-version-minor} + ++-----------------+-----------------------------------+----------------+------+---------+------------------------+ +| 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] (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. + .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 @@ -3328,33 +3219,33 @@ 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 @@ -3399,125 +3290,18 @@ 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 ====== - -.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 - -Runtime SLOTTED - -Runtime version {neo4j-version-minor} - -+-----------------+-----------------------------------+----------------+------+---------+------------------------+ -| 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-argument]] -== Argument -// Argument - -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. - - -.Argument -====== - -.Query -[source, cypher] ----- -PROFILE -MATCH (s:Person {name: 'me'}) -MERGE (s)-[:FRIENDS_WITH]->(s) ----- - -.Query Plan -[role="queryplan", subs="attributes+"] ----- -Planner COST - -Runtime PIPELINED - -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 | -+-----------------+----+-------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ - -Total database accesses: 15, total allocated memory: 2232 ----- - -====== - -[[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] (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. + +[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. .Query [source, cypher] @@ -3566,24 +3350,24 @@ Total database accesses: 6, total allocated memory: 4136 ====== -// --- expand operators --- - -[[query-plan-expand-all]] -== Expand All -// Expand(All) +[[query-plan-cartesian-product]] +=== Cartesian Product -Given a start node, and depending on the pattern relationship, the `Expand(All)` operator will traverse incoming or outgoing relationships. +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. -.Expand(All) +.CartesianProduct ====== .Query [source, cypher] ---- PROFILE -MATCH (p:Person {name: 'me'})-[:FRIENDS_WITH]->(fof) -RETURN fof +MATCH + (p:Person), + (t:Team) +RETURN p, t ---- .Query Plan @@ -3597,40 +3381,51 @@ 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 | 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: 7, total allocated memory: 184 +Total database accesses: 142, total allocated memory: 1816 ---- ====== -[[query-plan-expand-into]] -== Expand Into -// Expand(Into) +[[execution-plans-operators-hash-join-general]] +=== Hash joins in general -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. +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. +[[query-plan-node-hash-join]] +=== Node Hash Join + +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(Into) -====== +.NodeHashJoin +====== .Query [source, cypher] ---- PROFILE -MATCH (p:Person {name: 'me'})-[:FRIENDS_WITH]->(fof)-->(p) -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 @@ -3644,45 +3439,52 @@ 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 | `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: 13, total allocated memory: 976 +Total database accesses: 7, total allocated memory: 3888 ---- ====== -[[query-plan-optional-expand-all]] -== Optional Expand All -// OptionalExpand(All) +[[query-plan-value-hash-join]] +=== Value 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 `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). -.OptionalExpand(All) +.ValueHashJoin ====== .Query [source, cypher] ---- PROFILE -MATCH (p:Person) -OPTIONAL MATCH (p)-[works_in:WORKS_IN]->(l) - WHERE works_in.duration > 180 -RETURN p, l +MATCH + (p:Person), + (q:Person) +WHERE p.age = q.age +RETURN p, q ---- .Query Plan @@ -3696,42 +3498,46 @@ 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 | 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: 125, total allocated memory: 184 +Total database accesses: 71, total allocated memory: 664 ---- ====== -[[query-plan-optional-expand-into]] -== Optional Expand Into -// OptionalExpand(Into) +[[query-plan-node-left-right-outer-hash-join]] +=== Node Left/Right Outer Hash Join -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. + +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(Into) +.NodeRightOuterHashJoin ====== .Query [source, cypher] ---- PROFILE -MATCH (p:Person)-[works_in:WORKS_IN]->(l) -OPTIONAL MATCH (l)-->(p) -RETURN p +MATCH (a:Person) +OPTIONAL MATCH (a)-->(b:Person) +USING JOIN ON a +RETURN a.name, b.name ---- .Query Plan @@ -3745,40 +3551,58 @@ 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 | `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: 215, total allocated memory: 3440 +Total database accesses: 211, total allocated memory: 4312 ---- ====== -[[query-plan-varlength-expand-all]] -== VarLength Expand All -// VarLengthExpand(All) +[[traversal-operators]] +== Traversal operators -Given a start node, the `VarLengthExpand(All)` operator will traverse variable-length and quantified relationships. +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]. -.VarLengthExpand(All) +[[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)-[:FRIENDS_WITH *1..2]-(q:Person) -RETURN p, q +CYPHER runtime=pipelined +MATCH + (me:Person {name: 'me'}), + (other:Person) +WHERE NOT (me)-[:FRIENDS_WITH]->(other) +RETURN other.name ---- .Query Plan @@ -3792,40 +3616,54 @@ 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 | `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: 318, total allocated memory: 208 +Total database accesses: 178, total allocated memory: 6744 ---- ====== -[[query-plan-varlength-expand-into]] -== VarLength Expand Into -// VarLengthExpand(Into) +[[query-plan-optional]] +=== Optional -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. +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(Into) +.Optional ====== .Query [source, cypher] ---- PROFILE -MATCH (p:Person)-[:FRIENDS_WITH *1..2]-(p:Person) -RETURN p +MATCH (p:Person {name: 'me'}) +OPTIONAL MATCH (q:Person {name: 'Lulu'}) +RETURN p, q ---- .Query Plan @@ -3839,46 +3677,40 @@ 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 | 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 | 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: 222, total allocated memory: 192 +Total database accesses: 3, total allocated memory: 3000 ---- ====== +[[query-plan-expand-all]] +=== Expand All -[[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. - -The `VarLengthExpand(Pruning)` operator guarantees that all the end nodes produced will be unique. +Given a start node, and depending on the pattern relationship, the `Expand(All)` operator will traverse incoming or outgoing relationships. -.VarLengthExpand(Pruning) +.Expand(All) ====== + .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) +RETURN fof ---- .Query Plan @@ -3892,48 +3724,39 @@ Runtime version {neo4j-version-minor} 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 | 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: 30, total allocated memory: 480 +Total database accesses: 7, total allocated memory: 184 ---- ====== -[[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). -This is only used in cases where the individual paths are not of interest. +[[query-plan-expand-into]] +=== Expand Into -This kind of expand is only planned when: +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 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. +.Expand(Into) +====== .Query [source, cypher] ---- PROFILE -MATCH (p:Person)-[:FRIENDS_WITH *..4]-(q:Person) -RETURN DISTINCT p, q +MATCH (p:Person {name: 'me'})-[:FRIENDS_WITH]->(fof)-->(p) +RETURN fof ---- .Query Plan @@ -3947,42 +3770,44 @@ Runtime version {neo4j-version-minor} 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 | 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: 49, total allocated memory: 1200 +Total database accesses: 13, total allocated memory: 976 ---- -[role=label--new-5.9] -[[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. -.Repeat(Trail) +[[query-plan-optional-expand-all]] +=== Optional Expand All + +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`. + + +.OptionalExpand(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) +OPTIONAL MATCH (p)-[works_in:WORKS_IN]->(l) + WHERE works_in.duration > 180 +RETURN p, l ---- .Query Plan @@ -3996,53 +3821,41 @@ 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 | 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, 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: 747, total allocated memory: 45832 +Total database accesses: 125, total allocated memory: 184 ---- ====== -[role=label--new-5.9] -[[query-plan-nullify-metadata]] -== Nullify Metadata -// NullifyMetadata -`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)`. +[[query-plan-optional-expand-into]] +=== Optional Expand Into -.NullifyMetadata +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. + + +.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 @@ -4056,54 +3869,39 @@ 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 | 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-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-all]] +=== VarLength Expand All +Given a start node, the `VarLengthExpand(All)` operator will traverse variable-length and quantified relationships. -.AssertSameNode + +.VarLengthExpand(All) ====== .Query [source, cypher] ---- PROFILE -CYPHER runtime=slotted -MERGE (t:Team {name: 'Engineering', id: 42}) +MATCH (p:Person)-[:FRIENDS_WITH *1..2]-(q:Person) +RETURN p, q ---- .Query Plan @@ -4111,52 +3909,45 @@ MERGE (t:Team {name: 'Engineering', id: 42}) ---- Planner COST -Runtime SLOTTED +Runtime PIPELINED 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 | -| | +-------------------------------------------------------+----------------+------+---------+------------------------+ -| +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, 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: 318, total allocated memory: 208 ---- ====== -[role=label--new-5.8] -[[query-plan-assert-same-relationship]] -== Assert Same Relationship -// AssertSameRelationship +[[query-plan-varlength-expand-into]] +=== VarLength Expand Into -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. +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. -.AssertSameRelationship +.VarLengthExpand(Into) ====== .Query [source, cypher] ---- PROFILE -CYPHER runtime=slotted -MERGE (person)-[work:WORKS_IN {id: 0, badgeNumber: 4332}]->(location) +MATCH (p:Person)-[:FRIENDS_WITH *1..2]-(p:Person) +RETURN p ---- .Query Plan @@ -4164,51 +3955,52 @@ MERGE (person)-[work:WORKS_IN {id: 0, badgeNumber: 4332}]->(location) ---- Planner COST -Runtime SLOTTED +Runtime PIPELINED Runtime version {neo4j-version-minor} -+-------------------------------------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+------------------------+ -| 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 | 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 ---- ====== -// DropResult -- removed in 4.3 +[[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). -[[query-plan-empty-result]] -== Empty Result -// EmptyResult +This kind of expand is only planned when: -The `EmptyResult` operator eagerly loads all incoming data and discards it. +* 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. -.EmptyResult +.VarLengthExpand(Pruning) ====== - .Query [source, cypher] ---- PROFILE -CREATE (:Person) +MATCH (p:Person)-[:FRIENDS_WITH *3..4]-(q:Person) +RETURN DISTINCT p, q ---- .Query Plan @@ -4222,39 +4014,48 @@ Runtime version {neo4j-version-minor} 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 | 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: 1, total allocated memory: 184 +Total database accesses: 30, total allocated memory: 480 ---- ====== -[[query-plan-produce-results]] -== Produce Results -// ProduceResults +[[query-plan-breadth-first-varlength-expand-pruning-bfs-all]] +=== Breadth First VarLength Expand Pruning +// VarLengthExpand(Pruning,BFS) +// New in 5.0 -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. +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. +This kind of expand is only planned when: -.ProduceResults -====== +* 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. .Query [source, cypher] ---- PROFILE -MATCH (n) -RETURN n +MATCH (p:Person)-[:FRIENDS_WITH *..4]-(q:Person) +RETURN DISTINCT p, q ---- .Query Plan @@ -4268,37 +4069,42 @@ 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 | 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) | 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: 36, total allocated memory: 184 +Total database accesses: 49, total allocated memory: 1200 ---- -====== +[role=label--new-5.9] +[[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-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. - - -.LoadCSV -====== +.Repeat(Trail) +====== .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 @@ -4312,56 +4118,114 @@ 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 | -+-----------------+---------+----------------+------+---------+----------------+------------------------+-----------+---------------+ ++------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| 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 ---- ====== +[role=label--new-5.9] +[[query-plan-nullify-metadata]] +=== Nullify Metadata -[[execution-plans-operators-hash-join-general]] -== Hash joins in general +`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)`. -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. +.NullifyMetadata +====== -In query plans, the build input is always the left operator, and the probe input the right operator. +.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 +---- + +.Query Plan +[role="queryplan", subs="attributes+"] +---- +Planner COST -There are four hash join operators: +Runtime PIPELINED -* 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] +Runtime version {neo4j-version-minor} +Batch size 128 -[[query-plan-node-hash-join]] -== Node Hash Join -// NodeHashJoin ++------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +| 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 | ++------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ -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. +Total database accesses: 747, total allocated memory: 45832 +---- +====== -.NodeHashJoin +[[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. + +.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 @@ -4375,42 +4239,41 @@ 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 | `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 ---- ====== +[role=label--new-5.21] +[[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 @@ -4418,10 +4281,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 @@ -4435,47 +4296,44 @@ 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 | 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 ---- ====== +[role=label--new-5.21] +[[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 @@ -4489,33 +4347,37 @@ 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: 211, total allocated memory: 4312 +Total database accesses: 221, total allocated memory: 37983 + +---- + +//// +[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. @@ -4572,8 +4434,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. @@ -4637,8 +4498,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. @@ -4701,286 +4561,76 @@ 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-minor} - -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-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], 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] (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. - -.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-minor} - -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] (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. - -.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-minor} - -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 [role="queryplan", subs="attributes+"] ---- -Planner COST - -Runtime PIPELINED - -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 | | 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 | | | | | | | | -+---------------------+----+------------------------------------------------------------------------------------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ +Planner COST -Total database accesses: 17, total allocated memory: 4184 +Runtime PIPELINED + +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 | ++--------------------+----+--------------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+ + +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. @@ -5033,8 +4683,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. @@ -5080,8 +4729,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. @@ -5126,8 +4774,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. @@ -5170,24 +4817,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 @@ -5201,43 +4849,37 @@ 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 @@ -5251,29 +4893,25 @@ 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 ====== @@ -5312,24 +4950,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 @@ -5337,46 +4971,52 @@ LIMIT 3 ---- Planner COST -Runtime PIPELINED +Runtime SLOTTED 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 | 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 @@ -5390,44 +5030,42 @@ 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 @@ -5441,44 +5079,36 @@ 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 @@ -5492,43 +5122,46 @@ 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 @@ -5542,34 +5175,34 @@ 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 @@ -5578,9 +5211,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 @@ -5594,42 +5225,36 @@ 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 @@ -5643,39 +5268,26 @@ 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 ====== @@ -5713,14 +5325,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 +=== 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 ====== @@ -5757,16 +5366,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 @@ -5774,9 +5387,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 @@ -5790,43 +5402,141 @@ 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 +---- + +.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) +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. -.Optional +.PartialTop ====== .Query [source, cypher] ---- PROFILE -MATCH (p:Person {name: 'me'}) -OPTIONAL MATCH (q:Person {name: 'Lulu'}) -RETURN p, q +MATCH (p:Person) +WHERE p.name STARTS WITH 'P' +RETURN p +ORDER BY p.name, p.age +LIMIT 2 ---- .Query Plan @@ -5840,44 +5550,38 @@ 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 @@ -5891,45 +5595,40 @@ 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 @@ -5943,39 +5642,39 @@ 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 @@ -5989,50 +5688,48 @@ 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 ---- ====== -[role=label--new-5.21] -[[query-plan-stateful-shortest-path-into]] -== StatefulShortestPath(Into) -// StatefulShortestPath(Into) -//// -[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; ----- -//// +[[data-modification-operators]] +== Data modification operators -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. +The operators in this group modify graph data by creating, deleting, and altering nodes, relationships, and properties. -.StatefulShortestPath(Into) +[[query-plan-create]] +=== Create + +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 @@ -6046,44 +5743,37 @@ 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 ---- ====== -[role=label--new-5.21] -[[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 @@ -6097,51 +5787,39 @@ 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 @@ -6149,51 +5827,50 @@ FOREACH (value IN [1,2,3] | MERGE (:Person {age: value})) ---- Planner COST -Runtime SLOTTED +Runtime PIPELINED 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 @@ -6207,41 +5884,40 @@ 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 @@ -6255,46 +5931,48 @@ 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 @@ -6302,45 +5980,45 @@ CREATE (max)-[:FRIENDS_WITH]->(chris) ---- Planner COST -Runtime PIPELINED +Runtime SLOTTED Runtime version {neo4j-version-minor} -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] (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. + .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 @@ -6354,40 +6032,48 @@ 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 | | 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] (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. + .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 @@ -6395,42 +6081,38 @@ DETACH DELETE p ---- 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 | | 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 PIPELINED + +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 ====== @@ -6472,12 +6154,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 ====== @@ -6519,12 +6199,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 ====== @@ -6566,12 +6244,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 ====== @@ -6613,12 +6289,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 ====== @@ -6659,12 +6334,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 ====== @@ -6704,10 +6377,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-minor} + +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-minor} + ++---------------------------------+-------------------------------------------------------+----------------+------+---------+------------------------+ +| 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 +---- + +====== + + +[role=label--new-5.8] +[[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-minor} + ++-------------------------------------------------+----+------------------------------------------------------------------------------------------------------+----------------+------+---------+------------------------+ +| 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. @@ -6720,7 +6616,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 ====== @@ -6754,8 +6649,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. @@ -6799,13 +6693,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 ====== @@ -6838,13 +6729,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 ====== @@ -6879,8 +6768,7 @@ Total database accesses: 2, total allocated memory: 64 [[query-plan-create-index]] -== Create Index -// CreateIndex +=== Create Index The `CreateIndex` operator creates an index. @@ -6921,8 +6809,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. @@ -6965,12 +6852,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 ====== @@ -7003,13 +6888,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 ====== @@ -7045,8 +6928,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. @@ -7087,13 +6969,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 ====== @@ -7127,8 +7007,7 @@ Total database accesses: 0, total allocated memory: 64 ====== [[query-plan-show-settings]] -== Show Settings -// ShowSettings +=== Show Settings The `ShowSettings` operator lists configuration settings. @@ -7165,13 +7044,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 ====== @@ -7207,12 +7084,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 b8ba76a7e..07faae8a7 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 f57877bde1d2737bced65cad5e036f57155b9b61 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 47/93] 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 0461834ce..30dbbb03a 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 76cc351c6028989f281ce64ed07f075b454f385a 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 48/93] 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 cf83ee2a5..9fa9f20bf 100644 --- a/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc +++ b/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc @@ -602,7 +602,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 0513358bd42c5a4d266292eae6e1d42f9d85470b 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:12:28 +0100 Subject: [PATCH 49/93] Cheat sheet tags for patterns and label expressions (#1125) Cheat Sheet PR: https://github.com/neo4j/docs-cheat-sheet/pull/203 --- modules/ROOT/pages/clauses/match.adoc | 9 +++++++++ modules/ROOT/pages/patterns/fixed-length-patterns.adoc | 8 +++++++- modules/ROOT/pages/patterns/non-linear-patterns.adoc | 6 ++++++ modules/ROOT/pages/patterns/shortest-paths.adoc | 8 ++++++++ .../ROOT/pages/patterns/variable-length-patterns.adoc | 9 +++++++++ 5 files changed, 39 insertions(+), 1 deletion(-) diff --git a/modules/ROOT/pages/clauses/match.adoc b/modules/ROOT/pages/clauses/match.adoc index 300225568..bc81ff811 100644 --- a/modules/ROOT/pages/clauses/match.adoc +++ b/modules/ROOT/pages/clauses/match.adoc @@ -90,11 +90,14 @@ RETURN movie.title === MATCH using node label expressions .Node pattern using the `OR` (`|`) label expression +// tag::clauses_match_label_expression_or[] [source, cypher] ---- MATCH (n:Movie|Person) RETURN n.name AS name, n.title AS title ---- +// end::clauses_match_label_expression_or[] + .Result [role="queryresult",options="header,footer",cols="2*(:Station {name: 'Denmark Hill'}) RETURN s.departs AS departureTime ---- +// end::patterns_fixed_length_patterns_path_pattern[] .Result [role="queryresult",options="header,footer",cols="1*` on the relationship pattern, allowing the pattern to match relationships going in either direction. This represents the fact that trains can go in both directions along the `LINK` relationships between Stations. The `+` quantifier means that one or more relationships should be matched. For more information, see xref:patterns/reference.adoc#quantified-relationships[Syntax and semantics - quantified relationships]. @@ -157,12 +159,14 @@ If there had been only four possible paths between the two Stations, then only t To return all paths that are tied for shortest length, use the keywords `ALL SHORTEST`: .Query +// tag::patterns_shortest_paths_all_shortest[] [source,cypher] ---- MATCH p = ALL SHORTEST (wos:Station)-[:LINK]-+(bmv:Station) WHERE wos.name = "Worcester Shrub Hill" AND bmv.name = "Bromsgrove" RETURN [n in nodes(p) | n.name] AS stops ---- +// end::patterns_shortest_paths_all_shortest[] .Result [role="queryresult",options="header,footer",cols="m"] @@ -184,12 +188,14 @@ To return all paths that are tied for first, second, and so on up to the kth sho For example, the following returns the first and second shortest length paths between `Worcester Shrub Hill` and `Bromsgrove`: .Query +// tag::patterns_shortest_paths_shortest_k_groups[] [source,cypher] ---- MATCH p = SHORTEST 2 GROUPS (wos:Station)-[:LINK]-+(bmv:Station) WHERE wos.name = "Worcester Shrub Hill" AND bmv.name = "Bromsgrove" RETURN [n in nodes(p) | n.name] AS stops, length(p) AS pathLength ---- +// end::patterns_shortest_paths_shortest_k_groups[] .Result [role="queryresult",options="header,footer",cols="2m,m"] @@ -240,12 +246,14 @@ It returns the same as `SHORTEST 1`, but by using the `ANY` keyword the intent o For example, the following query shows that there exists a route from `Pershore` to `Bromsgrove` where the distance between each pair of stations is less than 10 miles: .Query +// tag::patterns_shortest_paths_any[] [source,cypher] ---- MATCH path = ANY (:Station {name: 'Pershore'})-[l:LINK WHERE l.distance < 10]-+(b:Station {name: 'Bromsgrove'}) RETURN [r IN relationships(path) | r.distance] AS distances ---- +// end::patterns_shortest_paths_any[] .Result [role="queryresult",options="header,footer",cols="m"] diff --git a/modules/ROOT/pages/patterns/variable-length-patterns.adoc b/modules/ROOT/pages/patterns/variable-length-patterns.adoc index 89041e57a..927c6220b 100644 --- a/modules/ROOT/pages/patterns/variable-length-patterns.adoc +++ b/modules/ROOT/pages/patterns/variable-length-patterns.adoc @@ -172,6 +172,7 @@ Translating the union of fixed-length path patterns into a quantified path patte The following query adds a `RETURN` clause that yields the departure and arrival times of the two services: .Query +// tag::patterns_variable_length_patterns_qpp[] [source, cypher] ---- MATCH (:Station { name: 'Denmark Hill' })<-[:CALLS_AT]-(d:Stop) @@ -179,6 +180,8 @@ MATCH (:Station { name: 'Denmark Hill' })<-[:CALLS_AT]-(d:Stop) (a:Stop)-[:CALLS_AT]->(:Station { name: 'Clapham Junction' }) RETURN d.departs AS departureTime, a.arrives AS arrivalTime ---- +// end::patterns_variable_length_patterns_qpp[] + .Result [role="queryresult",options="header,footer",cols="2*` and not the node patterns abutting it. More generally, where a path pattern contained in a quantified path pattern has the following form: @@ -523,6 +529,7 @@ In this example, an inline predicate can be added that takes advantage of the ge To compose the predicate, the xref:functions/spatial.adoc#functions-distance[point.distance()] function is used to compare the distance between the left-hand `Station` (`a`) and the right-hand `Station` (`b`) for each node-pair along the path to the destination `North Dulwich`: .Query +// tag::patterns_variable_length_patterns_predicates_in_qpp[] [source,cypher] ---- MATCH (bfr:Station {name: "London Blackfriars"}), @@ -534,6 +541,8 @@ MATCH p = (bfr) RETURN reduce(acc = 0, r in relationships(p) | round(acc + r.distance, 2)) AS distance ---- +// end::patterns_variable_length_patterns_predicates_in_qpp[] + .Result [role="queryresult",options="header,footer",cols="m"] From 943a07ae8ec7e5d033e8c1c181dde3b223391f4c Mon Sep 17 00:00:00 2001 From: Stefano Ottolenghi Date: Mon, 9 Dec 2024 15:50:15 +0100 Subject: [PATCH 50/93] Version to 2025. --- antora.yml | 8 ++++---- package.json | 2 +- preview.yml | 4 ++-- publish.yml | 8 ++++---- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/antora.yml b/antora.yml index b13b62440..51d116ceb 100644 --- a/antora.yml +++ b/antora.yml @@ -1,11 +1,11 @@ name: cypher-manual title: Cypher Manual -version: '5' +version: '2025' start_page: ROOT:introduction/index.adoc nav: - modules/ROOT/content-nav.adoc asciidoc: attributes: - neo4j-version: '5' - neo4j-version-minor: '5.26' - neo4j-version-exact: '5.26.0' + neo4j-version: '2025' + neo4j-version-minor: '2025.01' + neo4j-version-exact: '2025.01' diff --git a/package.json b/package.json index 527fcd494..dfdc0ac45 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cypher-manual", - "version": "5.0.0", + "version": "2025", "description": "Neo4j Cypher Manual", "main": "server.js", "scripts": { diff --git a/preview.yml b/preview.yml index fa119684c..50f2281c1 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: '2025' 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 1184d3ccc..d321d30c6 100644 --- a/publish.yml +++ b/publish.yml @@ -25,7 +25,7 @@ urls: antora: extensions: - require: "@neo4j-antora/antora-modify-sitemaps" - sitemap_version: '5' + sitemap_version: '2025' sitemap_loc_version: 'current' move_sitemaps_to_components: true @@ -45,7 +45,7 @@ asciidoc: page-search-site: Reference Docs page-canonical-root: /docs page-pagination: true - page-no-canonical: true + page-no-canonical: true page-origin-private: false page-hide-toc: false page-mixpanel: 4bfb2414ab973c741b6f067bf06d5575 @@ -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[] @@ -66,4 +66,4 @@ asciidoc: page-ad-description: Your input matters! Share your Feedback page-ad-underline-role: button page-ad-underline: Start Here - page-ad-link: https://neo4j.typeform.com/to/E6yOZ2Py?utm_source=GA&utm_medium=blurb&utm_campaign=survey \ No newline at end of file + page-ad-link: https://neo4j.typeform.com/to/E6yOZ2Py?utm_source=GA&utm_medium=blurb&utm_campaign=survey From 9b2a5f12a363b731b54dde7b737f0de7afbb2e8d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Dec 2024 13:33:43 +0100 Subject: [PATCH 51/93] Bump the prod-dependencies group with 2 updates (#1131) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the prod-dependencies group with 2 updates: [@antora/cli](https://gitlab.com/antora/antora) and [@antora/site-generator-default](https://gitlab.com/antora/antora). Updates `@antora/cli` from 3.1.9 to 3.1.10
Changelog

Sourced from @​antora/cli's changelog.

= Antora Changelog

This document provides a summary of all notable changes to the core Antora components by release. For a detailed view of what's changed, refer to the repository's https://gitlab.com/antora/antora/commits/main[commit history].

This project utilizes semantic versioning.

== 3.2.0-alpha.8 (2024-12-05)

=== Changed

  • content-aggregator: Don't apply camelCase transformation to descendant keys of the ext key in component version descriptor (#1145)
  • content-aggregator: Include - segment in edit URL for file hosted on gitlab.com to avoid redirct
  • Apply code formatting changes to comply with biome toolchain (#1157)
  • Add directory property to repository entry in package files
  • Upgrade @​antora/expand-path-helper to 3.0.x (content-aggregator, ui-loader, file-publisher, logger)
  • Upgrade @​antora/user-require-helper to 3.0.x (content-aggregator, asciidoc-loader, file-publisher, site-generator, cli)

=== Fixed

  • content-aggregator: Gracefully handle case when value of nav key in component version descriptor is not an array (#1147)
  • page-composer: Use navtitle as content of orphan breadcrumb entry instead of doctitle (aka page title) (#1159)
  • site-generator: Fully support static register method on Class or Object exported by extension (#1158)

== 3.2.0-alpha.7 (2024-12-05)

Release failed.

== 3.2.0-alpha.6 (2024-07-23)

=== Changed

  • Replace "AsciiDoc extension" with "Asciidoctor extension" in log messages

=== Fixed

  • file-publisher: Wrap legacy stream on file when preparing files for output providers; remove listeners limit (#1139)

== 3.2.0-alpha.5 (2024-06-25)

=== Added

  • playbook-builder: Add git.fetch_depth key to control how many recent commits Antora fetches from a remote repository (#1090)
  • content-classifier: Allow component name and version to be referenced by attributes in antora.yml as antora-component-name and antora-component-version attributes, respectively (#1106)
  • asciidoc-loader: Detect (and skip) Antora extension that's been registered as an AsciiDoc extension and log a warning (#1084)
  • site-generator: Detect (and skip) AsciiDoc extension registered as an Antora extension and log a warning (#1104)

=== Changed

  • content-aggregator: Use worktree from local repository even if repository has no commits (#298)

... (truncated)

Commits
  • 854ac81 release 3.1.10
  • af08e08 fix issue references on what's new page
  • 43cdee8 fix broken internal reference on images page
  • 36207a5 add section to images page to document how to make a link to an image
  • ca6a33d improve introduction of images and attachment by mentioning use of xref macro
  • 3bab6c6 mention that xref can be used to create a link to an image
  • c741759 update what's new page for upcoming 3.1.10 release
  • 5742a22 fix issue references in CHANGELOG [skip ci]
  • 6b67ddc allow coverage npm script to be run per package and document how to invoke it...
  • 6280687 use curl to fetch the release script instead of wget [skip ci]
  • Additional commits viewable in compare view

Updates `@antora/site-generator-default` from 3.1.9 to 3.1.10
Changelog

Sourced from @​antora/site-generator-default's changelog.

= Antora Changelog

This document provides a summary of all notable changes to the core Antora components by release. For a detailed view of what's changed, refer to the repository's https://gitlab.com/antora/antora/commits/main[commit history].

This project utilizes semantic versioning.

== 3.2.0-alpha.8 (2024-12-05)

=== Changed

  • content-aggregator: Don't apply camelCase transformation to descendant keys of the ext key in component version descriptor (#1145)
  • content-aggregator: Include - segment in edit URL for file hosted on gitlab.com to avoid redirct
  • Apply code formatting changes to comply with biome toolchain (#1157)
  • Add directory property to repository entry in package files
  • Upgrade @​antora/expand-path-helper to 3.0.x (content-aggregator, ui-loader, file-publisher, logger)
  • Upgrade @​antora/user-require-helper to 3.0.x (content-aggregator, asciidoc-loader, file-publisher, site-generator, cli)

=== Fixed

  • content-aggregator: Gracefully handle case when value of nav key in component version descriptor is not an array (#1147)
  • page-composer: Use navtitle as content of orphan breadcrumb entry instead of doctitle (aka page title) (#1159)
  • site-generator: Fully support static register method on Class or Object exported by extension (#1158)

== 3.2.0-alpha.7 (2024-12-05)

Release failed.

== 3.2.0-alpha.6 (2024-07-23)

=== Changed

  • Replace "AsciiDoc extension" with "Asciidoctor extension" in log messages

=== Fixed

  • file-publisher: Wrap legacy stream on file when preparing files for output providers; remove listeners limit (#1139)

== 3.2.0-alpha.5 (2024-06-25)

=== Added

  • playbook-builder: Add git.fetch_depth key to control how many recent commits Antora fetches from a remote repository (#1090)
  • content-classifier: Allow component name and version to be referenced by attributes in antora.yml as antora-component-name and antora-component-version attributes, respectively (#1106)
  • asciidoc-loader: Detect (and skip) Antora extension that's been registered as an AsciiDoc extension and log a warning (#1084)
  • site-generator: Detect (and skip) AsciiDoc extension registered as an Antora extension and log a warning (#1104)

=== Changed

  • content-aggregator: Use worktree from local repository even if repository has no commits (#298)

... (truncated)

Commits
  • 854ac81 release 3.1.10
  • af08e08 fix issue references on what's new page
  • 43cdee8 fix broken internal reference on images page
  • 36207a5 add section to images page to document how to make a link to an image
  • ca6a33d improve introduction of images and attachment by mentioning use of xref macro
  • 3bab6c6 mention that xref can be used to create a link to an image
  • c741759 update what's new page for upcoming 3.1.10 release
  • 5742a22 fix issue references in CHANGELOG [skip ci]
  • 6b67ddc allow coverage npm script to be run per package and document how to invoke it...
  • 6280687 use curl to fetch the release script instead of wget [skip ci]
  • Additional commits viewable in compare view

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 452 +++++++++++++++++++++++----------------------- package.json | 4 +- 2 files changed, 228 insertions(+), 228 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7111aee2d..03743c620 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,16 +1,16 @@ { "name": "cypher-manual", - "version": "5.0.0", + "version": "2025", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "cypher-manual", - "version": "5.0.0", + "version": "2025", "license": "ISC", "dependencies": { - "@antora/cli": "^3.1.9", - "@antora/site-generator-default": "^3.1.9", + "@antora/cli": "^3.1.10", + "@antora/site-generator-default": "^3.1.10", "@neo4j-antora/antora-add-notes": "^0.3.1", "@neo4j-antora/antora-modify-sitemaps": "^0.4.4", "@neo4j-antora/antora-page-roles": "^0.3.1", @@ -26,12 +26,12 @@ } }, "node_modules/@antora/asciidoc-loader": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/asciidoc-loader/-/asciidoc-loader-3.1.9.tgz", - "integrity": "sha512-flE27T2yI8TX7rUNjbBHWN3iR6s+kBuRBbUPncUFcWjx6mXzll8JLiTkxnc8JXHGzgKlveT+t5AkPYGACLfasg==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/asciidoc-loader/-/asciidoc-loader-3.1.10.tgz", + "integrity": "sha512-np0JkOV37CK7V4eDZUZXf4fQuCKYW3Alxl8FlyzBevXi2Ujv29O82JLbHbv1cyTsvGkGNNB+gzJIx9XBsQ7+Nw==", "dependencies": { - "@antora/logger": "3.1.9", - "@antora/user-require-helper": "~2.0", + "@antora/logger": "3.1.10", + "@antora/user-require-helper": "~3.0", "@asciidoctor/core": "~2.2" }, "engines": { @@ -39,13 +39,13 @@ } }, "node_modules/@antora/cli": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/cli/-/cli-3.1.9.tgz", - "integrity": "sha512-kCUqWX3G/9Pvf8SWZ45ioHwWdOc9uamy2E5/FFwyGiTeu4ubNbadOauLVvMzSZHUxVDnGxXwCsmmQ2HwM919ew==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/cli/-/cli-3.1.10.tgz", + "integrity": "sha512-gp8u9aVM0w1DtWSsB5PwvEfFYKrooPENLhN58RAfdgTrcsTsWw+CDysFZPgEaHB0Y1ZbanR82ZH/f6JVKGcZfQ==", "dependencies": { - "@antora/logger": "3.1.9", - "@antora/playbook-builder": "3.1.9", - "@antora/user-require-helper": "~2.0", + "@antora/logger": "3.1.10", + "@antora/playbook-builder": "3.1.10", + "@antora/user-require-helper": "~3.0", "commander": "~11.1" }, "bin": { @@ -56,13 +56,13 @@ } }, "node_modules/@antora/content-aggregator": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/content-aggregator/-/content-aggregator-3.1.9.tgz", - "integrity": "sha512-g+UzevPSm5c4R0j1U9uysJfdIUfp++QOHIEBmqjhfx/aIEnOL70zA+WF55Mm+syAfzU3877puI27sOp8qtPglw==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/content-aggregator/-/content-aggregator-3.1.10.tgz", + "integrity": "sha512-OT6ZcCA7LrtNfrAZUr3hFh+Z/1isKpsfnqFjCDC66NEMqIyzJO99jq0CM66rYlYhyX7mb5BwEua8lHcwpOXNow==", "dependencies": { - "@antora/expand-path-helper": "~2.0", - "@antora/logger": "3.1.9", - "@antora/user-require-helper": "~2.0", + "@antora/expand-path-helper": "~3.0", + "@antora/logger": "3.1.10", + "@antora/user-require-helper": "~3.0", "braces": "~3.0", "cache-directory": "~2.0", "fast-glob": "~3.3", @@ -92,12 +92,12 @@ } }, "node_modules/@antora/content-classifier": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/content-classifier/-/content-classifier-3.1.9.tgz", - "integrity": "sha512-PVJqwp5uvZE1PlpeJtb0p6al75fN+fmXGIC6DHcKysRnr0xo+sgz8X2r4mnNWdTWRqum2yVigMmmuXYTg3cJlQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/content-classifier/-/content-classifier-3.1.10.tgz", + "integrity": "sha512-3JJl4IIiTX00v/MirK603NoqIcHjGYAaRWt3Q4U03tI1Fv2Aho/ypO3FE45069jFf0Dx2uDJfp5kapb9gaIjdQ==", "dependencies": { - "@antora/asciidoc-loader": "3.1.9", - "@antora/logger": "3.1.9", + "@antora/asciidoc-loader": "3.1.10", + "@antora/logger": "3.1.10", "mime-types": "~2.1", "vinyl": "~3.0" }, @@ -106,31 +106,31 @@ } }, "node_modules/@antora/document-converter": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/document-converter/-/document-converter-3.1.9.tgz", - "integrity": "sha512-pH7tQaIjcPsFdYkaBEAvA/5ki04IQwQGHoR+2jadKdMl6P+J5KA1VzNnMgyIL6gHn7auJIkoOKadfItRB9lHGQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/document-converter/-/document-converter-3.1.10.tgz", + "integrity": "sha512-qi9ctgcKal8tZtWflVo66w+4zCJoBmUKRV+eA9aRRR09KDdU9r514vu1adWNgniPppISr90zD13V5l2JUy/2CQ==", "dependencies": { - "@antora/asciidoc-loader": "3.1.9" + "@antora/asciidoc-loader": "3.1.10" }, "engines": { "node": ">=16.0.0" } }, "node_modules/@antora/expand-path-helper": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@antora/expand-path-helper/-/expand-path-helper-2.0.0.tgz", - "integrity": "sha512-CSMBGC+tI21VS2kGW3PV7T2kQTM5eT3f2GTPVLttwaNYbNxDve08en/huzszHJfxo11CcEs26Ostr0F2c1QqeA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/expand-path-helper/-/expand-path-helper-3.0.0.tgz", + "integrity": "sha512-7PdEIhk97v85/CSm3HynCsX14TR6oIVz1s233nNLsiWubE8tTnpPt4sNRJR+hpmIZ6Bx9c6QDp3XIoiyu/WYYA==", "engines": { - "node": ">=10.17.0" + "node": ">=16.0.0" } }, "node_modules/@antora/file-publisher": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/file-publisher/-/file-publisher-3.1.9.tgz", - "integrity": "sha512-C0VwVjuFbE1CVpZDgwYR1gZCNr1tMw5vueyF9wHZH0KCqAsp9iwo7bwj8wKWMPogxcxdYhnAvtDJnYmYFCuDWQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/file-publisher/-/file-publisher-3.1.10.tgz", + "integrity": "sha512-DPR/0d1P+kr3qV4T0Gh81POEO/aCmNWIp/oLUYAhr0HHOcFzgpTUUoLStgcYynZPFRIB7EYKSab+oYSCK17DGA==", "dependencies": { - "@antora/expand-path-helper": "~2.0", - "@antora/user-require-helper": "~2.0", + "@antora/expand-path-helper": "~3.0", + "@antora/user-require-helper": "~3.0", "vinyl": "~3.0", "yazl": "~2.5" }, @@ -139,11 +139,11 @@ } }, "node_modules/@antora/logger": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/logger/-/logger-3.1.9.tgz", - "integrity": "sha512-MKuANodcX0lfRyiB+Rxl/Kv7UOxc2glzTYFoIoBB7uzxF0A+AhvUJDmpGQFRFN2ihxy99N3nLJmZpDebwXyE+A==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/logger/-/logger-3.1.10.tgz", + "integrity": "sha512-WSuIxEP2tVrhWtTj/sIrwBDjpi4ldB/1Kpiu4PXmY4/qeWP8thW6u8nXdwdDcWss5zqkZWjourvWKwVq7y8Wjg==", "dependencies": { - "@antora/expand-path-helper": "~2.0", + "@antora/expand-path-helper": "~3.0", "pino": "~9.2", "pino-pretty": "~11.2", "sonic-boom": "~4.0" @@ -153,22 +153,22 @@ } }, "node_modules/@antora/navigation-builder": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/navigation-builder/-/navigation-builder-3.1.9.tgz", - "integrity": "sha512-zyl2yNjK31Dl6TRJgnoFb4Czwt9ar3wLTycAdMeZ+U/8YcAUHD8z7NCssPFFvZ0BbUr00NP+gbqDmCr6yz32NQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/navigation-builder/-/navigation-builder-3.1.10.tgz", + "integrity": "sha512-aLMK49nYsSB3mEZbLkmUXDAUYmscv2AFWu+5c3eqVGkQ6Wgyd79WQ6Bz3/TN9YqkzGL+PqGs0G39F0VQzD23Hw==", "dependencies": { - "@antora/asciidoc-loader": "3.1.9" + "@antora/asciidoc-loader": "3.1.10" }, "engines": { "node": ">=16.0.0" } }, "node_modules/@antora/page-composer": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/page-composer/-/page-composer-3.1.9.tgz", - "integrity": "sha512-X6Qj+J5dfFAGXoCAOaA+R6xRp8UoNMDHsRsB1dUTT2QNzk1Lrq6YkYyljdD2cxkWjLVqQ/pQSP+BJVNFGbqDAQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/page-composer/-/page-composer-3.1.10.tgz", + "integrity": "sha512-JoEg8J8HVsnPmAgUrYSGzf0C8rQefXyCi/18ucy0utyfUvlJNsZvUbGUPx62Het9p0JP0FkAz2MTLyDlNdArVg==", "dependencies": { - "@antora/logger": "3.1.9", + "@antora/logger": "3.1.10", "handlebars": "~4.7", "require-from-string": "~2.0" }, @@ -177,9 +177,9 @@ } }, "node_modules/@antora/playbook-builder": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/playbook-builder/-/playbook-builder-3.1.9.tgz", - "integrity": "sha512-MJ/OWz4pReC98nygGTXC5bOL/TDDtCYpSkHFBz2ST4L6tuM8rv9c5+cp//JkwY/QlTOvcuJ0f2xq4a7a5nI7Qw==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/playbook-builder/-/playbook-builder-3.1.10.tgz", + "integrity": "sha512-UB8UmRYfkKgActTUlotdVS4FKGjaZgTnSXE7Fns1xb3/3HRanWvI+Yze1OmCkGC33cTpoQFnSYp7ySEH8LaiBw==", "dependencies": { "@iarna/toml": "~2.2", "convict": "~6.2", @@ -191,9 +191,9 @@ } }, "node_modules/@antora/redirect-producer": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/redirect-producer/-/redirect-producer-3.1.9.tgz", - "integrity": "sha512-9OLwoMhqifsBxTebInh/5W16GdDsdj+YkKG3TiCASlAOYsDbuhbeRPFUlyKKSRkMrtKKnFgHR0Z3DNPXYlH2NQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/redirect-producer/-/redirect-producer-3.1.10.tgz", + "integrity": "sha512-IbWJGh6LmsxJQ821h0B9JfooofFZBgFLZxsbp/IoTLkBFGLFAY5tDRvB6rvubfNLRoSjM8VjEUXGqVLlwZOb+g==", "dependencies": { "vinyl": "~3.0" }, @@ -202,46 +202,46 @@ } }, "node_modules/@antora/site-generator": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/site-generator/-/site-generator-3.1.9.tgz", - "integrity": "sha512-YYESPG22tGX1CxRPSAr6acKILCO8JfGkM1OYc7Sw3D7ZvCy1YgZMAaTYK0T5yl9LXg+l/UZi1xq/Ej0qHnYQiw==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/site-generator/-/site-generator-3.1.10.tgz", + "integrity": "sha512-NCULYtwUjIyr5FGCymhfG/zDVUmZ6pfmCPorka8mAzo4/GDx1T7bgaRL9rEIyf2AMqcm7apQiAz03mpU4kucsw==", "dependencies": { - "@antora/asciidoc-loader": "3.1.9", - "@antora/content-aggregator": "3.1.9", - "@antora/content-classifier": "3.1.9", - "@antora/document-converter": "3.1.9", - "@antora/file-publisher": "3.1.9", - "@antora/logger": "3.1.9", - "@antora/navigation-builder": "3.1.9", - "@antora/page-composer": "3.1.9", - "@antora/playbook-builder": "3.1.9", - "@antora/redirect-producer": "3.1.9", - "@antora/site-mapper": "3.1.9", - "@antora/site-publisher": "3.1.9", - "@antora/ui-loader": "3.1.9", - "@antora/user-require-helper": "~2.0" + "@antora/asciidoc-loader": "3.1.10", + "@antora/content-aggregator": "3.1.10", + "@antora/content-classifier": "3.1.10", + "@antora/document-converter": "3.1.10", + "@antora/file-publisher": "3.1.10", + "@antora/logger": "3.1.10", + "@antora/navigation-builder": "3.1.10", + "@antora/page-composer": "3.1.10", + "@antora/playbook-builder": "3.1.10", + "@antora/redirect-producer": "3.1.10", + "@antora/site-mapper": "3.1.10", + "@antora/site-publisher": "3.1.10", + "@antora/ui-loader": "3.1.10", + "@antora/user-require-helper": "~3.0" }, "engines": { "node": ">=16.0.0" } }, "node_modules/@antora/site-generator-default": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/site-generator-default/-/site-generator-default-3.1.9.tgz", - "integrity": "sha512-m/QCv2o/24VmWZaeqtc6nNEky///GTLLx/pyyihP7uWKvZ0AhGPp6Agv1yaShjKIthBzHJ3JozaMPev2leor+A==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/site-generator-default/-/site-generator-default-3.1.10.tgz", + "integrity": "sha512-dMhjbklthysj3espwYNkTkADm2Z3EbWThq9gJv/ZuSXGZSXVSwt8b3mBpCTwxOeAKIldnj3fc1pzQxei/7PC2w==", "dependencies": { - "@antora/site-generator": "3.1.9" + "@antora/site-generator": "3.1.10" }, "engines": { "node": ">=16.0.0" } }, "node_modules/@antora/site-mapper": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/site-mapper/-/site-mapper-3.1.9.tgz", - "integrity": "sha512-9FCObL+JIjBoby8z+beu2uuvAtCjm5EsEQt+16gCIMX1ktVP3W3gVsdRSvVcGcVEpizILFhMawkcQknZPUp5mg==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/site-mapper/-/site-mapper-3.1.10.tgz", + "integrity": "sha512-KY1j/y0uxC2Y7RAo4r4yKv9cgFm8aZoRylZXEODJnwj3tffbZ2ZdRzSWHp6fN0QX/Algrr9JNd9CWrjcj2f3Zw==", "dependencies": { - "@antora/content-classifier": "3.1.9", + "@antora/content-classifier": "3.1.10", "vinyl": "~3.0" }, "engines": { @@ -249,22 +249,22 @@ } }, "node_modules/@antora/site-publisher": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/site-publisher/-/site-publisher-3.1.9.tgz", - "integrity": "sha512-L5To8f4QswZliXu6yB6O7O8CuBbLctjNbxZqP3m0FP7VaOONp85ftzEq1BFEm4BXXSwH1n4ujZx1qGBHP9ooOQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/site-publisher/-/site-publisher-3.1.10.tgz", + "integrity": "sha512-G4xcUWvgth8oeEQwiu9U1cE0miQtYHwKHOobUbDBt2Y6LlC5H31zQQmAyvMwTsGRlvYRgLVtG6j9d6JBwQ6w9Q==", "dependencies": { - "@antora/file-publisher": "3.1.9" + "@antora/file-publisher": "3.1.10" }, "engines": { "node": ">=16.0.0" } }, "node_modules/@antora/ui-loader": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/ui-loader/-/ui-loader-3.1.9.tgz", - "integrity": "sha512-g0/9dRE5JVMYukIU3x+Rvr41bPdK3sUD2xQIAniRjE6usIZs1mEsTGshVKVEoOqqnSekXE85HVhybjNHsC+qbQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/ui-loader/-/ui-loader-3.1.10.tgz", + "integrity": "sha512-H1f5wI5a5HjLuE/Wexvc8NZy8w83Bhqjka7t1DbwOOqP+LyxFGLx/QbBVKdTtgFNDHVMtNBlplQq0ixeoTSh0A==", "dependencies": { - "@antora/expand-path-helper": "~2.0", + "@antora/expand-path-helper": "~3.0", "braces": "~3.0", "cache-directory": "~2.0", "fast-glob": "~3.3", @@ -292,14 +292,14 @@ } }, "node_modules/@antora/user-require-helper": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@antora/user-require-helper/-/user-require-helper-2.0.0.tgz", - "integrity": "sha512-5fMfBZfw4zLoFdDAPMQX6Frik90uvfD8rXOA4UpXPOUikkX4uT1Rk6m0/4oi8oS3fcjiIl0k/7Nc+eTxW5TcQQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/user-require-helper/-/user-require-helper-3.0.0.tgz", + "integrity": "sha512-KIXb8WYhnrnwH7Jj21l1w+et9k5GvcgcqvLOwxqWLEd0uVZOiMFdqFjqbVm3M+zcrs1JXWMeh2LLvxBbQs3q/Q==", "dependencies": { - "@antora/expand-path-helper": "~2.0" + "@antora/expand-path-helper": "~3.0" }, "engines": { - "node": ">=10.17.0" + "node": ">=16.0.0" } }, "node_modules/@asciidoctor/core": { @@ -494,9 +494,9 @@ } }, "node_modules/b4a": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.6.tgz", - "integrity": "sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==" + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", + "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==" }, "node_modules/balanced-match": { "version": "1.0.2", @@ -504,9 +504,9 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/bare-events": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.4.2.tgz", - "integrity": "sha512-qMKFd2qG/36aA4GwvKq8MxnPgCQAmBWmSyLWsJcbn8v03wvIPQ/hG1Ms8bPzndZxMDoHpxez5VOS+gC9Yi24/Q==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.0.tgz", + "integrity": "sha512-/E8dDe9dsbLyh2qrZ64PEPadOQ0F4gbl1sUJOrmph7xOiIxfY8vwab/4bFLh4Y88/Hk/ujKcrQKc+ps0mv873A==", "optional": true }, "node_modules/base64-js": { @@ -1291,9 +1291,9 @@ ] }, "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "engines": { "node": ">= 4" } @@ -1478,9 +1478,9 @@ } }, "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -2317,9 +2317,9 @@ } }, "node_modules/streamx": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.18.0.tgz", - "integrity": "sha512-LLUC1TWdjVdn1weXGcSxyTR3T4+acB6tVGXT95y0nGbca4t4o/ng1wKAGTljm9VicuCVLvRlqFYXYy5GwgM7sQ==", + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.21.0.tgz", + "integrity": "sha512-Qz6MsDZXJ6ur9u+b+4xCG18TluU7PGlRfXVAAjNiGsFrBUt/ioyLkxbFaKJygoPs+/kW4VyBj0bSj89Qu0IGyg==", "dependencies": { "fast-fifo": "^1.3.2", "queue-tick": "^1.0.1", @@ -2369,9 +2369,9 @@ } }, "node_modules/text-decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.1.1.tgz", - "integrity": "sha512-8zll7REEv4GDD3x4/0pW+ppIxSNs7H1J10IKFZsuOMscumCdM2a+toDGLPA3T+1+fLBql4zbt5z83GEQGGV5VA==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.2.tgz", + "integrity": "sha512-/MDslo7ZyWTA2vnk1j7XoDVfXsGk3tp+zFEJHJGm0UjIlQifonVFwlVbQDFh8KJzTBnT8ie115TYqir6bclddA==", "dependencies": { "b4a": "^1.6.4" } @@ -2430,9 +2430,9 @@ } }, "node_modules/uglify-js": { - "version": "3.19.1", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.1.tgz", - "integrity": "sha512-y/2wiW+ceTYR2TSSptAhfnEtpLaQ4Ups5zrjB2d3kuVxHj16j/QJwPl5PvuGy9uARb39J0+iKxcRPvtpsx4A4A==", + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", "optional": true, "bin": { "uglifyjs": "bin/uglifyjs" @@ -2557,34 +2557,34 @@ }, "dependencies": { "@antora/asciidoc-loader": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/asciidoc-loader/-/asciidoc-loader-3.1.9.tgz", - "integrity": "sha512-flE27T2yI8TX7rUNjbBHWN3iR6s+kBuRBbUPncUFcWjx6mXzll8JLiTkxnc8JXHGzgKlveT+t5AkPYGACLfasg==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/asciidoc-loader/-/asciidoc-loader-3.1.10.tgz", + "integrity": "sha512-np0JkOV37CK7V4eDZUZXf4fQuCKYW3Alxl8FlyzBevXi2Ujv29O82JLbHbv1cyTsvGkGNNB+gzJIx9XBsQ7+Nw==", "requires": { - "@antora/logger": "3.1.9", - "@antora/user-require-helper": "~2.0", + "@antora/logger": "3.1.10", + "@antora/user-require-helper": "~3.0", "@asciidoctor/core": "~2.2" } }, "@antora/cli": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/cli/-/cli-3.1.9.tgz", - "integrity": "sha512-kCUqWX3G/9Pvf8SWZ45ioHwWdOc9uamy2E5/FFwyGiTeu4ubNbadOauLVvMzSZHUxVDnGxXwCsmmQ2HwM919ew==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/cli/-/cli-3.1.10.tgz", + "integrity": "sha512-gp8u9aVM0w1DtWSsB5PwvEfFYKrooPENLhN58RAfdgTrcsTsWw+CDysFZPgEaHB0Y1ZbanR82ZH/f6JVKGcZfQ==", "requires": { - "@antora/logger": "3.1.9", - "@antora/playbook-builder": "3.1.9", - "@antora/user-require-helper": "~2.0", + "@antora/logger": "3.1.10", + "@antora/playbook-builder": "3.1.10", + "@antora/user-require-helper": "~3.0", "commander": "~11.1" } }, "@antora/content-aggregator": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/content-aggregator/-/content-aggregator-3.1.9.tgz", - "integrity": "sha512-g+UzevPSm5c4R0j1U9uysJfdIUfp++QOHIEBmqjhfx/aIEnOL70zA+WF55Mm+syAfzU3877puI27sOp8qtPglw==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/content-aggregator/-/content-aggregator-3.1.10.tgz", + "integrity": "sha512-OT6ZcCA7LrtNfrAZUr3hFh+Z/1isKpsfnqFjCDC66NEMqIyzJO99jq0CM66rYlYhyX7mb5BwEua8lHcwpOXNow==", "requires": { - "@antora/expand-path-helper": "~2.0", - "@antora/logger": "3.1.9", - "@antora/user-require-helper": "~2.0", + "@antora/expand-path-helper": "~3.0", + "@antora/logger": "3.1.10", + "@antora/user-require-helper": "~3.0", "braces": "~3.0", "cache-directory": "~2.0", "fast-glob": "~3.3", @@ -2607,73 +2607,73 @@ } }, "@antora/content-classifier": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/content-classifier/-/content-classifier-3.1.9.tgz", - "integrity": "sha512-PVJqwp5uvZE1PlpeJtb0p6al75fN+fmXGIC6DHcKysRnr0xo+sgz8X2r4mnNWdTWRqum2yVigMmmuXYTg3cJlQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/content-classifier/-/content-classifier-3.1.10.tgz", + "integrity": "sha512-3JJl4IIiTX00v/MirK603NoqIcHjGYAaRWt3Q4U03tI1Fv2Aho/ypO3FE45069jFf0Dx2uDJfp5kapb9gaIjdQ==", "requires": { - "@antora/asciidoc-loader": "3.1.9", - "@antora/logger": "3.1.9", + "@antora/asciidoc-loader": "3.1.10", + "@antora/logger": "3.1.10", "mime-types": "~2.1", "vinyl": "~3.0" } }, "@antora/document-converter": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/document-converter/-/document-converter-3.1.9.tgz", - "integrity": "sha512-pH7tQaIjcPsFdYkaBEAvA/5ki04IQwQGHoR+2jadKdMl6P+J5KA1VzNnMgyIL6gHn7auJIkoOKadfItRB9lHGQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/document-converter/-/document-converter-3.1.10.tgz", + "integrity": "sha512-qi9ctgcKal8tZtWflVo66w+4zCJoBmUKRV+eA9aRRR09KDdU9r514vu1adWNgniPppISr90zD13V5l2JUy/2CQ==", "requires": { - "@antora/asciidoc-loader": "3.1.9" + "@antora/asciidoc-loader": "3.1.10" } }, "@antora/expand-path-helper": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@antora/expand-path-helper/-/expand-path-helper-2.0.0.tgz", - "integrity": "sha512-CSMBGC+tI21VS2kGW3PV7T2kQTM5eT3f2GTPVLttwaNYbNxDve08en/huzszHJfxo11CcEs26Ostr0F2c1QqeA==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/expand-path-helper/-/expand-path-helper-3.0.0.tgz", + "integrity": "sha512-7PdEIhk97v85/CSm3HynCsX14TR6oIVz1s233nNLsiWubE8tTnpPt4sNRJR+hpmIZ6Bx9c6QDp3XIoiyu/WYYA==" }, "@antora/file-publisher": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/file-publisher/-/file-publisher-3.1.9.tgz", - "integrity": "sha512-C0VwVjuFbE1CVpZDgwYR1gZCNr1tMw5vueyF9wHZH0KCqAsp9iwo7bwj8wKWMPogxcxdYhnAvtDJnYmYFCuDWQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/file-publisher/-/file-publisher-3.1.10.tgz", + "integrity": "sha512-DPR/0d1P+kr3qV4T0Gh81POEO/aCmNWIp/oLUYAhr0HHOcFzgpTUUoLStgcYynZPFRIB7EYKSab+oYSCK17DGA==", "requires": { - "@antora/expand-path-helper": "~2.0", - "@antora/user-require-helper": "~2.0", + "@antora/expand-path-helper": "~3.0", + "@antora/user-require-helper": "~3.0", "vinyl": "~3.0", "yazl": "~2.5" } }, "@antora/logger": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/logger/-/logger-3.1.9.tgz", - "integrity": "sha512-MKuANodcX0lfRyiB+Rxl/Kv7UOxc2glzTYFoIoBB7uzxF0A+AhvUJDmpGQFRFN2ihxy99N3nLJmZpDebwXyE+A==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/logger/-/logger-3.1.10.tgz", + "integrity": "sha512-WSuIxEP2tVrhWtTj/sIrwBDjpi4ldB/1Kpiu4PXmY4/qeWP8thW6u8nXdwdDcWss5zqkZWjourvWKwVq7y8Wjg==", "requires": { - "@antora/expand-path-helper": "~2.0", + "@antora/expand-path-helper": "~3.0", "pino": "~9.2", "pino-pretty": "~11.2", "sonic-boom": "~4.0" } }, "@antora/navigation-builder": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/navigation-builder/-/navigation-builder-3.1.9.tgz", - "integrity": "sha512-zyl2yNjK31Dl6TRJgnoFb4Czwt9ar3wLTycAdMeZ+U/8YcAUHD8z7NCssPFFvZ0BbUr00NP+gbqDmCr6yz32NQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/navigation-builder/-/navigation-builder-3.1.10.tgz", + "integrity": "sha512-aLMK49nYsSB3mEZbLkmUXDAUYmscv2AFWu+5c3eqVGkQ6Wgyd79WQ6Bz3/TN9YqkzGL+PqGs0G39F0VQzD23Hw==", "requires": { - "@antora/asciidoc-loader": "3.1.9" + "@antora/asciidoc-loader": "3.1.10" } }, "@antora/page-composer": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/page-composer/-/page-composer-3.1.9.tgz", - "integrity": "sha512-X6Qj+J5dfFAGXoCAOaA+R6xRp8UoNMDHsRsB1dUTT2QNzk1Lrq6YkYyljdD2cxkWjLVqQ/pQSP+BJVNFGbqDAQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/page-composer/-/page-composer-3.1.10.tgz", + "integrity": "sha512-JoEg8J8HVsnPmAgUrYSGzf0C8rQefXyCi/18ucy0utyfUvlJNsZvUbGUPx62Het9p0JP0FkAz2MTLyDlNdArVg==", "requires": { - "@antora/logger": "3.1.9", + "@antora/logger": "3.1.10", "handlebars": "~4.7", "require-from-string": "~2.0" } }, "@antora/playbook-builder": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/playbook-builder/-/playbook-builder-3.1.9.tgz", - "integrity": "sha512-MJ/OWz4pReC98nygGTXC5bOL/TDDtCYpSkHFBz2ST4L6tuM8rv9c5+cp//JkwY/QlTOvcuJ0f2xq4a7a5nI7Qw==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/playbook-builder/-/playbook-builder-3.1.10.tgz", + "integrity": "sha512-UB8UmRYfkKgActTUlotdVS4FKGjaZgTnSXE7Fns1xb3/3HRanWvI+Yze1OmCkGC33cTpoQFnSYp7ySEH8LaiBw==", "requires": { "@iarna/toml": "~2.2", "convict": "~6.2", @@ -2682,65 +2682,65 @@ } }, "@antora/redirect-producer": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/redirect-producer/-/redirect-producer-3.1.9.tgz", - "integrity": "sha512-9OLwoMhqifsBxTebInh/5W16GdDsdj+YkKG3TiCASlAOYsDbuhbeRPFUlyKKSRkMrtKKnFgHR0Z3DNPXYlH2NQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/redirect-producer/-/redirect-producer-3.1.10.tgz", + "integrity": "sha512-IbWJGh6LmsxJQ821h0B9JfooofFZBgFLZxsbp/IoTLkBFGLFAY5tDRvB6rvubfNLRoSjM8VjEUXGqVLlwZOb+g==", "requires": { "vinyl": "~3.0" } }, "@antora/site-generator": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/site-generator/-/site-generator-3.1.9.tgz", - "integrity": "sha512-YYESPG22tGX1CxRPSAr6acKILCO8JfGkM1OYc7Sw3D7ZvCy1YgZMAaTYK0T5yl9LXg+l/UZi1xq/Ej0qHnYQiw==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/site-generator/-/site-generator-3.1.10.tgz", + "integrity": "sha512-NCULYtwUjIyr5FGCymhfG/zDVUmZ6pfmCPorka8mAzo4/GDx1T7bgaRL9rEIyf2AMqcm7apQiAz03mpU4kucsw==", "requires": { - "@antora/asciidoc-loader": "3.1.9", - "@antora/content-aggregator": "3.1.9", - "@antora/content-classifier": "3.1.9", - "@antora/document-converter": "3.1.9", - "@antora/file-publisher": "3.1.9", - "@antora/logger": "3.1.9", - "@antora/navigation-builder": "3.1.9", - "@antora/page-composer": "3.1.9", - "@antora/playbook-builder": "3.1.9", - "@antora/redirect-producer": "3.1.9", - "@antora/site-mapper": "3.1.9", - "@antora/site-publisher": "3.1.9", - "@antora/ui-loader": "3.1.9", - "@antora/user-require-helper": "~2.0" + "@antora/asciidoc-loader": "3.1.10", + "@antora/content-aggregator": "3.1.10", + "@antora/content-classifier": "3.1.10", + "@antora/document-converter": "3.1.10", + "@antora/file-publisher": "3.1.10", + "@antora/logger": "3.1.10", + "@antora/navigation-builder": "3.1.10", + "@antora/page-composer": "3.1.10", + "@antora/playbook-builder": "3.1.10", + "@antora/redirect-producer": "3.1.10", + "@antora/site-mapper": "3.1.10", + "@antora/site-publisher": "3.1.10", + "@antora/ui-loader": "3.1.10", + "@antora/user-require-helper": "~3.0" } }, "@antora/site-generator-default": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/site-generator-default/-/site-generator-default-3.1.9.tgz", - "integrity": "sha512-m/QCv2o/24VmWZaeqtc6nNEky///GTLLx/pyyihP7uWKvZ0AhGPp6Agv1yaShjKIthBzHJ3JozaMPev2leor+A==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/site-generator-default/-/site-generator-default-3.1.10.tgz", + "integrity": "sha512-dMhjbklthysj3espwYNkTkADm2Z3EbWThq9gJv/ZuSXGZSXVSwt8b3mBpCTwxOeAKIldnj3fc1pzQxei/7PC2w==", "requires": { - "@antora/site-generator": "3.1.9" + "@antora/site-generator": "3.1.10" } }, "@antora/site-mapper": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/site-mapper/-/site-mapper-3.1.9.tgz", - "integrity": "sha512-9FCObL+JIjBoby8z+beu2uuvAtCjm5EsEQt+16gCIMX1ktVP3W3gVsdRSvVcGcVEpizILFhMawkcQknZPUp5mg==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/site-mapper/-/site-mapper-3.1.10.tgz", + "integrity": "sha512-KY1j/y0uxC2Y7RAo4r4yKv9cgFm8aZoRylZXEODJnwj3tffbZ2ZdRzSWHp6fN0QX/Algrr9JNd9CWrjcj2f3Zw==", "requires": { - "@antora/content-classifier": "3.1.9", + "@antora/content-classifier": "3.1.10", "vinyl": "~3.0" } }, "@antora/site-publisher": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/site-publisher/-/site-publisher-3.1.9.tgz", - "integrity": "sha512-L5To8f4QswZliXu6yB6O7O8CuBbLctjNbxZqP3m0FP7VaOONp85ftzEq1BFEm4BXXSwH1n4ujZx1qGBHP9ooOQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/site-publisher/-/site-publisher-3.1.10.tgz", + "integrity": "sha512-G4xcUWvgth8oeEQwiu9U1cE0miQtYHwKHOobUbDBt2Y6LlC5H31zQQmAyvMwTsGRlvYRgLVtG6j9d6JBwQ6w9Q==", "requires": { - "@antora/file-publisher": "3.1.9" + "@antora/file-publisher": "3.1.10" } }, "@antora/ui-loader": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@antora/ui-loader/-/ui-loader-3.1.9.tgz", - "integrity": "sha512-g0/9dRE5JVMYukIU3x+Rvr41bPdK3sUD2xQIAniRjE6usIZs1mEsTGshVKVEoOqqnSekXE85HVhybjNHsC+qbQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@antora/ui-loader/-/ui-loader-3.1.10.tgz", + "integrity": "sha512-H1f5wI5a5HjLuE/Wexvc8NZy8w83Bhqjka7t1DbwOOqP+LyxFGLx/QbBVKdTtgFNDHVMtNBlplQq0ixeoTSh0A==", "requires": { - "@antora/expand-path-helper": "~2.0", + "@antora/expand-path-helper": "~3.0", "braces": "~3.0", "cache-directory": "~2.0", "fast-glob": "~3.3", @@ -2761,11 +2761,11 @@ } }, "@antora/user-require-helper": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@antora/user-require-helper/-/user-require-helper-2.0.0.tgz", - "integrity": "sha512-5fMfBZfw4zLoFdDAPMQX6Frik90uvfD8rXOA4UpXPOUikkX4uT1Rk6m0/4oi8oS3fcjiIl0k/7Nc+eTxW5TcQQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/user-require-helper/-/user-require-helper-3.0.0.tgz", + "integrity": "sha512-KIXb8WYhnrnwH7Jj21l1w+et9k5GvcgcqvLOwxqWLEd0uVZOiMFdqFjqbVm3M+zcrs1JXWMeh2LLvxBbQs3q/Q==", "requires": { - "@antora/expand-path-helper": "~2.0" + "@antora/expand-path-helper": "~3.0" } }, "@asciidoctor/core": { @@ -2924,9 +2924,9 @@ "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==" }, "b4a": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.6.tgz", - "integrity": "sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==" + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", + "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==" }, "balanced-match": { "version": "1.0.2", @@ -2934,9 +2934,9 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "bare-events": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.4.2.tgz", - "integrity": "sha512-qMKFd2qG/36aA4GwvKq8MxnPgCQAmBWmSyLWsJcbn8v03wvIPQ/hG1Ms8bPzndZxMDoHpxez5VOS+gC9Yi24/Q==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.0.tgz", + "integrity": "sha512-/E8dDe9dsbLyh2qrZ64PEPadOQ0F4gbl1sUJOrmph7xOiIxfY8vwab/4bFLh4Y88/Hk/ujKcrQKc+ps0mv873A==", "optional": true }, "base64-js": { @@ -3494,9 +3494,9 @@ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, "ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==" + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==" }, "ignore-by-default": { "version": "1.0.1", @@ -3632,9 +3632,9 @@ "dev": true }, "micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "requires": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -4220,9 +4220,9 @@ "dev": true }, "streamx": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.18.0.tgz", - "integrity": "sha512-LLUC1TWdjVdn1weXGcSxyTR3T4+acB6tVGXT95y0nGbca4t4o/ng1wKAGTljm9VicuCVLvRlqFYXYy5GwgM7sQ==", + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.21.0.tgz", + "integrity": "sha512-Qz6MsDZXJ6ur9u+b+4xCG18TluU7PGlRfXVAAjNiGsFrBUt/ioyLkxbFaKJygoPs+/kW4VyBj0bSj89Qu0IGyg==", "requires": { "bare-events": "^2.2.0", "fast-fifo": "^1.3.2", @@ -4261,9 +4261,9 @@ } }, "text-decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.1.1.tgz", - "integrity": "sha512-8zll7REEv4GDD3x4/0pW+ppIxSNs7H1J10IKFZsuOMscumCdM2a+toDGLPA3T+1+fLBql4zbt5z83GEQGGV5VA==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.2.tgz", + "integrity": "sha512-/MDslo7ZyWTA2vnk1j7XoDVfXsGk3tp+zFEJHJGm0UjIlQifonVFwlVbQDFh8KJzTBnT8ie115TYqir6bclddA==", "requires": { "b4a": "^1.6.4" } @@ -4310,9 +4310,9 @@ } }, "uglify-js": { - "version": "3.19.1", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.1.tgz", - "integrity": "sha512-y/2wiW+ceTYR2TSSptAhfnEtpLaQ4Ups5zrjB2d3kuVxHj16j/QJwPl5PvuGy9uARb39J0+iKxcRPvtpsx4A4A==", + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", "optional": true }, "undefsafe": { diff --git a/package.json b/package.json index dfdc0ac45..37f14c2c4 100644 --- a/package.json +++ b/package.json @@ -19,8 +19,8 @@ "author": "Neo4j", "license": "ISC", "dependencies": { - "@antora/cli": "^3.1.9", - "@antora/site-generator-default": "^3.1.9", + "@antora/cli": "^3.1.10", + "@antora/site-generator-default": "^3.1.10", "@neo4j-antora/antora-add-notes": "^0.3.1", "@neo4j-antora/antora-modify-sitemaps": "^0.4.4", "@neo4j-antora/antora-page-roles": "^0.3.1", From c1cf1393dbd6f1ccdb299b44cac3403054aee7e8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Dec 2024 13:46:22 +0100 Subject: [PATCH 52/93] Bump the dev-dependencies group across 1 directory with 2 updates (#1134) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the dev-dependencies group with 2 updates in the / directory: [express](https://github.com/expressjs/express) and [nodemon](https://github.com/remy/nodemon). Updates `express` from 4.21.1 to 4.21.2
Release notes

Sourced from express's releases.

4.21.2

What's Changed

Full Changelog: https://github.com/expressjs/express/compare/4.21.1...4.21.2

Changelog

Sourced from express's changelog.

4.21.2 / 2024-11-06

  • deps: path-to-regexp@0.1.12
    • Fix backtracking protection
  • deps: path-to-regexp@0.1.11
    • Throws an error on invalid path values
Commits
Maintainer changes

This version was pushed to npm by jonchurch, a new releaser for express since your current version.


Updates `nodemon` from 3.1.7 to 3.1.9
Release notes

Sourced from nodemon's releases.

v3.1.9

3.1.9 (2024-12-13)

Bug Fixes

  • maintain backward support for exitcrash (9c9de6e)

v3.1.8

3.1.8 (2024-12-13)

Bug Fixes

Commits

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jens Pryce-Åklundh <112686610+JPryce-Aklundh@users.noreply.github.com> --- package-lock.json | 48 +++++++++++++++++++++++++---------------------- package.json | 4 ++-- 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/package-lock.json b/package-lock.json index 03743c620..8df8e1944 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,8 +21,8 @@ "asciidoctor-kroki": "^0.18.1" }, "devDependencies": { - "express": "^4.21.1", - "nodemon": "^3.1.7" + "express": "^4.21.2", + "nodemon": "^3.1.9" } }, "node_modules/@antora/asciidoc-loader": { @@ -933,9 +933,9 @@ } }, "node_modules/express": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", - "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", "dev": true, "dependencies": { "accepts": "~1.3.8", @@ -957,7 +957,7 @@ "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.10", + "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", "qs": "6.13.0", "range-parser": "~1.2.1", @@ -972,6 +972,10 @@ }, "engines": { "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/fast-copy": { @@ -1601,9 +1605,9 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, "node_modules/nodemon": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.7.tgz", - "integrity": "sha512-hLj7fuMow6f0lbB0cD14Lz2xNjwsyruH251Pk4t/yIitCFJbmY1myuLlHm/q06aST4jg6EgAh74PIBBrRqpVAQ==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.9.tgz", + "integrity": "sha512-hdr1oIb2p6ZSxu3PB2JWWYS7ZQ0qvaZsc3hK8DR8f02kRzc8rjYmxAIvdz+aYC+8F2IjNaB7HMcSDg8nQpJxyg==", "dev": true, "dependencies": { "chokidar": "^3.5.2", @@ -1738,9 +1742,9 @@ } }, "node_modules/path-to-regexp": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", - "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", "dev": true }, "node_modules/pend": { @@ -3234,9 +3238,9 @@ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" }, "express": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", - "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", "dev": true, "requires": { "accepts": "~1.3.8", @@ -3258,7 +3262,7 @@ "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.10", + "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", "qs": "6.13.0", "range-parser": "~1.2.1", @@ -3714,9 +3718,9 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, "nodemon": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.7.tgz", - "integrity": "sha512-hLj7fuMow6f0lbB0cD14Lz2xNjwsyruH251Pk4t/yIitCFJbmY1myuLlHm/q06aST4jg6EgAh74PIBBrRqpVAQ==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.9.tgz", + "integrity": "sha512-hdr1oIb2p6ZSxu3PB2JWWYS7ZQ0qvaZsc3hK8DR8f02kRzc8rjYmxAIvdz+aYC+8F2IjNaB7HMcSDg8nQpJxyg==", "dev": true, "requires": { "chokidar": "^3.5.2", @@ -3808,9 +3812,9 @@ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" }, "path-to-regexp": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", - "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", "dev": true }, "pend": { diff --git a/package.json b/package.json index 37f14c2c4..c37ea79ab 100644 --- a/package.json +++ b/package.json @@ -31,8 +31,8 @@ "asciidoctor-kroki": "^0.18.1" }, "devDependencies": { - "express": "^4.21.1", - "nodemon": "^3.1.7" + "express": "^4.21.2", + "nodemon": "^3.1.9" }, "overrides": { "@antora/site-generator-default": { From 49d4013a52e50c733eb51536374d083e8662cb95 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 53/93] 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 12273391f..50047fdc6 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -253,7 +253,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 fb0284afc..a96b96d08 100644 --- a/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc +++ b/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc @@ -4406,26 +4406,25 @@ Runtime SLOTTED Runtime version {neo4j-version-minor} -+-------------------+----------------------------------------+----------------+------+---------+------------------------+ -| 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 ---- @@ -4466,30 +4465,29 @@ 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 | `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 ---- @@ -4530,30 +4528,29 @@ 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 | `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 87dc9689f5794bd351b1ea082457089d118060e4 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 54/93] 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 6a8986945..ebf126222 100644 --- a/modules/ROOT/pages/clauses/load-csv.adoc +++ b/modules/ROOT/pages/clauses/load-csv.adoc @@ -342,6 +342,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 bc81ff811..dbf136f4a 100644 --- a/modules/ROOT/pages/clauses/match.adoc +++ b/modules/ROOT/pages/clauses/match.adoc @@ -532,10 +532,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] ---- @@ -630,3 +626,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 2f56bc1d6..1110bd445 100644 --- a/modules/ROOT/pages/clauses/merge.adoc +++ b/modules/ROOT/pages/clauses/merge.adoc @@ -703,10 +703,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] ---- @@ -730,7 +726,7 @@ RETURN greta.name AS name, labels(greta) AS labels, type(rel) AS relType, collec // end::clauses_merge_dynamic_merge[] .Result -[role="queryresult",options="footer",cols="3* Date: Tue, 7 Jan 2025 09:51:19 +0100 Subject: [PATCH 55/93] Bump @neo4j-antora/antora-modify-sitemaps from 0.4.4 to 0.5.0 in the prod-dependencies group (#1142) Bumps the prod-dependencies group with 1 update: @neo4j-antora/antora-modify-sitemaps. Updates `@neo4j-antora/antora-modify-sitemaps` from 0.4.4 to 0.5.0 [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@neo4j-antora/antora-modify-sitemaps&package-manager=npm_and_yarn&previous-version=0.4.4&new-version=0.5.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8df8e1944..f615e80c8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@antora/cli": "^3.1.10", "@antora/site-generator-default": "^3.1.10", "@neo4j-antora/antora-add-notes": "^0.3.1", - "@neo4j-antora/antora-modify-sitemaps": "^0.4.4", + "@neo4j-antora/antora-modify-sitemaps": "^0.5.0", "@neo4j-antora/antora-page-roles": "^0.3.1", "@neo4j-antora/antora-table-footnotes": "^0.3.2", "@neo4j-antora/mark-terms": "1.1.0", @@ -327,9 +327,9 @@ "integrity": "sha512-0zapKJr9U+cNBaz5m342Zqb5+1VuaFuybhGtSzEdiG4MRmvsAZunxLX7lSG0cWm6L4DlQa0jzOKYYzpkqoap/g==" }, "node_modules/@neo4j-antora/antora-modify-sitemaps": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/@neo4j-antora/antora-modify-sitemaps/-/antora-modify-sitemaps-0.4.4.tgz", - "integrity": "sha512-IkXoilOJquZPB5G5ZhrgfSN6U3E2YToWakehtF55RA+CNQS0KboTAB2vUH01+Tkmkd8K6UElf41A6cGnnrvs0g==" + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@neo4j-antora/antora-modify-sitemaps/-/antora-modify-sitemaps-0.5.0.tgz", + "integrity": "sha512-JC2yT8M+GndKgDiidikYcVE0C4GI73YQTQR4x7kVHcPfS1ENxWOlO5bvqLRNqkYFETxw8BckvCoec2T1S6uH4A==" }, "node_modules/@neo4j-antora/antora-page-roles": { "version": "0.3.2", @@ -2792,9 +2792,9 @@ "integrity": "sha512-0zapKJr9U+cNBaz5m342Zqb5+1VuaFuybhGtSzEdiG4MRmvsAZunxLX7lSG0cWm6L4DlQa0jzOKYYzpkqoap/g==" }, "@neo4j-antora/antora-modify-sitemaps": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/@neo4j-antora/antora-modify-sitemaps/-/antora-modify-sitemaps-0.4.4.tgz", - "integrity": "sha512-IkXoilOJquZPB5G5ZhrgfSN6U3E2YToWakehtF55RA+CNQS0KboTAB2vUH01+Tkmkd8K6UElf41A6cGnnrvs0g==" + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@neo4j-antora/antora-modify-sitemaps/-/antora-modify-sitemaps-0.5.0.tgz", + "integrity": "sha512-JC2yT8M+GndKgDiidikYcVE0C4GI73YQTQR4x7kVHcPfS1ENxWOlO5bvqLRNqkYFETxw8BckvCoec2T1S6uH4A==" }, "@neo4j-antora/antora-page-roles": { "version": "0.3.2", diff --git a/package.json b/package.json index c37ea79ab..cede3ed38 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "@antora/cli": "^3.1.10", "@antora/site-generator-default": "^3.1.10", "@neo4j-antora/antora-add-notes": "^0.3.1", - "@neo4j-antora/antora-modify-sitemaps": "^0.4.4", + "@neo4j-antora/antora-modify-sitemaps": "^0.5.0", "@neo4j-antora/antora-page-roles": "^0.3.1", "@neo4j-antora/antora-table-footnotes": "^0.3.2", "@neo4j-antora/mark-terms": "1.1.0", From c20fe4a2789dfeb27cc88dd73ef3ea0d44d5719f 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:15:02 +0100 Subject: [PATCH 56/93] Add dynamically referenced labels and types to allowed parameters (#1143) --- 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 90334ffab..a021f9c0d 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..06a4f0605 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]). label:new[Introduced in 5.26] 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 d5aeaecfd65cb162dd6e74f6b5a749365b1237f9 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 57/93] 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 50047fdc6..1b97862d8 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -150,6 +150,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 702f2af3cb7da1d0be8977860dfa163836452193 Mon Sep 17 00:00:00 2001 From: Jennifer Reif Date: Thu, 9 Jan 2025 02:09:34 -0600 Subject: [PATCH 58/93] Correct genai batchEncode example syntax (#1148) --- 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 5168f0d01..2773b4848 100644 --- a/modules/ROOT/pages/genai-integrations.adoc +++ b/modules/ROOT/pages/genai-integrations.adoc @@ -185,7 +185,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> @@ -199,7 +199,7 @@ Too large a batch size may also exceed the provider's threshold. <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. -<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 912325ecad5111ac1d7c95cd661fc4aacef96af6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastien=20Lou=C3=ABrat?= Date: Thu, 9 Jan 2025 11:22:21 +0100 Subject: [PATCH 59/93] The Cypher query option `eagerAnalyzer` is deprecated (#1147) 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 | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index 1b97862d8..78da37687 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -16,6 +16,36 @@ 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 + +=== 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 @@ -162,6 +192,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 d3adebdc5c0782f30b51ace1855bc6371f99acd4 Mon Sep 17 00:00:00 2001 From: dogofbrian Date: Thu, 9 Jan 2025 15:15:05 +0000 Subject: [PATCH 60/93] 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 d9da89346..f75ac88c9 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 13bfb4ca4554659beb909bdbac28c7c6be3242e1 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 12:54:22 +0100 Subject: [PATCH 61/93] Explain trigram indexing for text-2.0 provider (#1152) --- .../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 53b35afa8..c523f2b77 100644 --- a/modules/ROOT/pages/indexes/search-performance-indexes/managing-indexes.adoc +++ b/modules/ROOT/pages/indexes/search-performance-indexes/managing-indexes.adoc @@ -216,7 +216,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, as of Neo4j 5.1, 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] @@ -286,6 +286,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 7a163a8f1..e8c4eee44 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 57ae186448600526836ebe4aba3bf44332f475f0 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 62/93] 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 f75ac88c9..af68fc22a 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 612137cbbd68cc97142064fc9ba3dbc0be789974 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 63/93] 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 a021f9c0d..f57792c60 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 78c4056ca..c6ceb9ad1 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]] @@ -123,7 +123,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 af68fc22a..04f985752 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 e1047a2f168605e39c2ce98bc5c054be4ef45360 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/93] 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 98c143dcb..019c73efc 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/{ | 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:43:10 +0100 Subject: [PATCH 65/93] Clarify YIELD (#1157) Co-authored-by: Therese Magnusson --- 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 d600d0bd4..658127b3a 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/{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/{page-version}/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 fca175bdfc932441d681da6a2dcd72eea036999b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Jan 2025 09:58:44 +0100 Subject: [PATCH 66/93] Bump @neo4j-antora/antora-modify-sitemaps from 0.5.0 to 0.6.0 in the prod-dependencies group (#1158) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the prod-dependencies group with 1 update: @neo4j-antora/antora-modify-sitemaps. Updates `@neo4j-antora/antora-modify-sitemaps` from 0.5.0 to 0.6.0 [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@neo4j-antora/antora-modify-sitemaps&package-manager=npm_and_yarn&previous-version=0.5.0&new-version=0.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jens Pryce-Åklundh <112686610+JPryce-Aklundh@users.noreply.github.com> --- package-lock.json | 73 ++++++++++++----------------------------------- package.json | 2 +- 2 files changed, 20 insertions(+), 55 deletions(-) diff --git a/package-lock.json b/package-lock.json index f615e80c8..759f2eed3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@antora/cli": "^3.1.10", "@antora/site-generator-default": "^3.1.10", "@neo4j-antora/antora-add-notes": "^0.3.1", - "@neo4j-antora/antora-modify-sitemaps": "^0.5.0", + "@neo4j-antora/antora-modify-sitemaps": "^0.6.0", "@neo4j-antora/antora-page-roles": "^0.3.1", "@neo4j-antora/antora-table-footnotes": "^0.3.2", "@neo4j-antora/mark-terms": "1.1.0", @@ -327,9 +327,12 @@ "integrity": "sha512-0zapKJr9U+cNBaz5m342Zqb5+1VuaFuybhGtSzEdiG4MRmvsAZunxLX7lSG0cWm6L4DlQa0jzOKYYzpkqoap/g==" }, "node_modules/@neo4j-antora/antora-modify-sitemaps": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@neo4j-antora/antora-modify-sitemaps/-/antora-modify-sitemaps-0.5.0.tgz", - "integrity": "sha512-JC2yT8M+GndKgDiidikYcVE0C4GI73YQTQR4x7kVHcPfS1ENxWOlO5bvqLRNqkYFETxw8BckvCoec2T1S6uH4A==" + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@neo4j-antora/antora-modify-sitemaps/-/antora-modify-sitemaps-0.6.0.tgz", + "integrity": "sha512-QdlLZoN4jL9X39RwphNQOx6FnjFYzZIdm7OhBaf7FpP31eaGXgeyfMquWQm3yNPrqrut1ax4ogGrQNeRBmAxVg==", + "dependencies": { + "semver": "^7.6.3" + } }, "node_modules/@neo4j-antora/antora-page-roles": { "version": "0.3.2", @@ -1434,18 +1437,6 @@ "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -2106,13 +2097,9 @@ "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==" }, "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "bin": { "semver": "bin/semver.js" }, @@ -2524,12 +2511,6 @@ "node": ">=4" } }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/yargs-parser": { "version": "20.2.9", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", @@ -2792,9 +2773,12 @@ "integrity": "sha512-0zapKJr9U+cNBaz5m342Zqb5+1VuaFuybhGtSzEdiG4MRmvsAZunxLX7lSG0cWm6L4DlQa0jzOKYYzpkqoap/g==" }, "@neo4j-antora/antora-modify-sitemaps": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@neo4j-antora/antora-modify-sitemaps/-/antora-modify-sitemaps-0.5.0.tgz", - "integrity": "sha512-JC2yT8M+GndKgDiidikYcVE0C4GI73YQTQR4x7kVHcPfS1ENxWOlO5bvqLRNqkYFETxw8BckvCoec2T1S6uH4A==" + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@neo4j-antora/antora-modify-sitemaps/-/antora-modify-sitemaps-0.6.0.tgz", + "integrity": "sha512-QdlLZoN4jL9X39RwphNQOx6FnjFYzZIdm7OhBaf7FpP31eaGXgeyfMquWQm3yNPrqrut1ax4ogGrQNeRBmAxVg==", + "requires": { + "semver": "^7.6.3" + } }, "@neo4j-antora/antora-page-roles": { "version": "0.3.2", @@ -3603,15 +3587,6 @@ "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -4074,13 +4049,9 @@ "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==" }, "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==" }, "send": { "version": "0.19.0", @@ -4380,12 +4351,6 @@ "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", "integrity": "sha512-1Dly4xqlulvPD3fZUQJLY+FUIeqN3N2MM3uqe4rCJftAvOjFa3jFGfctOgluGx4ahPbUCsZkmJILiP0Vi4T6lQ==" }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "yargs-parser": { "version": "20.2.9", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", diff --git a/package.json b/package.json index cede3ed38..290d1c494 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "@antora/cli": "^3.1.10", "@antora/site-generator-default": "^3.1.10", "@neo4j-antora/antora-add-notes": "^0.3.1", - "@neo4j-antora/antora-modify-sitemaps": "^0.5.0", + "@neo4j-antora/antora-modify-sitemaps": "^0.6.0", "@neo4j-antora/antora-page-roles": "^0.3.1", "@neo4j-antora/antora-table-footnotes": "^0.3.2", "@neo4j-antora/mark-terms": "1.1.0", From 09ee930ba27839209c5ec13e657024522b48f840 Mon Sep 17 00:00:00 2001 From: Richard Sill <156673635+rsill-neo4j@users.noreply.github.com> Date: Tue, 14 Jan 2025 11:24:21 +0100 Subject: [PATCH 67/93] tags for READ query section (#1133) --- modules/ROOT/pages/clauses/match.adoc | 10 ++++++++++ .../ROOT/pages/clauses/optional-match.adoc | 2 ++ modules/ROOT/pages/clauses/return.adoc | 12 +++++++++++ modules/ROOT/pages/clauses/union.adoc | 4 ++++ modules/ROOT/pages/clauses/where.adoc | 20 +++++++++++++++++++ modules/ROOT/pages/clauses/with.adoc | 4 ++++ 6 files changed, 52 insertions(+) diff --git a/modules/ROOT/pages/clauses/match.adoc b/modules/ROOT/pages/clauses/match.adoc index dbf136f4a..3dffc1a0c 100644 --- a/modules/ROOT/pages/clauses/match.adoc +++ b/modules/ROOT/pages/clauses/match.adoc @@ -45,11 +45,13 @@ For more information about finding node patterns, see xref:patterns/fixed-length By specifying a pattern with a single node and no labels, all nodes in the graph will be returned. .Find all nodes in a graph +// tag::clauses_match_all_nodes[] [source, cypher] ---- MATCH (n) RETURN n ---- +// end::clauses_match_all_nodes[] .Result [role="queryresult",options="header,footer",cols="1*() RETURN type(r) AS relType ---- +// end::clauses_match_relationship_types[] [NOTE] The above query uses the xref:functions/scalar.adoc#functions-type[`type()` function]. @@ -244,11 +250,13 @@ RETURN a, b It is possible to specify the type of a relationship in a relationship pattern by using a colon (`:`) before the relationship type. .Relationship pattern filtering on the `ACTED_IN` relationship type +// tag::clauses_match_relationship[] [source, cypher] ---- MATCH (:Movie {title: 'Wall Street'})<-[:ACTED_IN]-(actor:Person) RETURN actor.name AS actor ---- +// end::clauses_match_relationship[] .Result [source, role="queryresult",options="header,footer",cols="1*(movie:Movie) RETURN path ---- +// end::clauses_match_path[] .Result [role="queryresult",options="header,footer",cols="1*() RETURN p.name, r ---- +// end::clauses_optional_match[] .Result [role="queryresult",options="header,footer",cols="2*(m) RETURN type(r) ---- +// end::clauses_return_relationship_type[] .Result [role="queryresult",options="header,footer",cols="1*(m) RETURN * ---- +// end::clauses_return_all_elements[] This returns the two nodes, and the two possible paths between them. @@ -149,11 +157,13 @@ d|Rows: 1 Names of returned columns can be renamed using the `AS` operator: .Query +// tag::clauses_return_with_column_alias[] [source, cypher] ---- MATCH (p:Person {name: 'Keanu Reeves'}) RETURN p.nationality AS citizenship ---- +// end::clauses_return_with_column_alias[] Returns the `nationality` property of `'Keanu Reeves'`, but the column is renamed to `citizenship`. @@ -220,11 +230,13 @@ Returns a predicate, a literal and function call with a pattern expression param `DISTINCT` retrieves only unique rows for the columns that have been selected for output. .Query +// tag::clauses_return_distinct[] [source, cypher] ---- MATCH (p:Person {name: 'Keanu Reeves'})-->(m) RETURN DISTINCT m ---- +// end::clauses_return_distinct[] The `Movie` node `'Man of Tai Chi'` is returned by the query, but only once (without the `DISTINCT` operator it would have been returned twice because there are two relationships going to it from `'Keanu Reeves'`): diff --git a/modules/ROOT/pages/clauses/union.adoc b/modules/ROOT/pages/clauses/union.adoc index 2df4687aa..89c9746a8 100644 --- a/modules/ROOT/pages/clauses/union.adoc +++ b/modules/ROOT/pages/clauses/union.adoc @@ -45,6 +45,7 @@ CREATE (johnny:Actor {name: 'Johnny Depp'}), Combining the results from two queries is done using `UNION ALL`. .Query +// tag::clauses_union_all[] [source, cypher] ---- MATCH (n:Actor) @@ -53,6 +54,7 @@ UNION ALL MATCH (n:Movie) RETURN n.title AS name ---- +// end::clauses_union_all[] The combined result is returned, including duplicates. @@ -74,6 +76,7 @@ The combined result is returned, including duplicates. By not including `ALL` in the `UNION`, duplicates are removed from the combined result set. .Query +// tag::clauses_union[] [source, cypher] ---- MATCH (n:Actor) @@ -82,6 +85,7 @@ UNION MATCH (n:Movie) RETURN n.title AS name ---- +// end::clauses_union[] The combined result is returned, without duplicates. diff --git a/modules/ROOT/pages/clauses/where.adoc b/modules/ROOT/pages/clauses/where.adoc index f57792c60..c0487cb30 100644 --- a/modules/ROOT/pages/clauses/where.adoc +++ b/modules/ROOT/pages/clauses/where.adoc @@ -46,12 +46,14 @@ CREATE `WHERE` can appear inside a node pattern in a `MATCH` clause or a pattern comprehension: .Query +// tag::clauses_where_in_match_clause[] [source, cypher] ---- WITH 30 AS minAge MATCH (a:Person WHERE a.name = 'Andy')-[:KNOWS]->(b:Person WHERE b.age > minAge) RETURN b.name ---- +// end::clauses_where_in_match_clause[] .Result [role="queryresult",options="header,footer",cols="1*(b WHERE b:Person) | b.name] AS friends ---- +// end::clauses_where_pattern_comprehension[] .Result [role="queryresult",options="header,footer",cols="1*(f) WHERE k.since < 2000 RETURN f.name, f.age, f.email ---- +// end::clauses_where_relationship_property[] The `name`, `age` and `email` values for `Peter` are returned because `Andy` has known him since before 2000: @@ -218,12 +230,14 @@ The `name` and `age` values for `Timothy` are returned because he is less than 3 Use the `IS NOT NULL` predicate to only include nodes or relationships in which a property exists: .Query +// tag::clauses_where_property_existence[] [source, cypher] ---- MATCH (n:Person) WHERE n.belt IS NOT NULL RETURN n.name, n.belt ---- +// end::clauses_where_property_existence[] The `name` and `belt` values for `Andy` are returned because he is the only one with a `belt` property: @@ -242,6 +256,7 @@ The `name` and `belt` values for `Andy` are returned because he is the only one As `WHERE` is not considered a clause in its own right, its scope is not limited by a `WITH` directly before it. .Query +// tag::clauses_where_with[] [source, cypher] ---- MATCH (n:Person) @@ -249,6 +264,7 @@ WITH n.name as name WHERE n.age = 25 RETURN name ---- +// end::clauses_where_with[] .Result [role="queryresult",options="header,footer",cols="1*(timothy) RETURN other.name, other.age ---- +// end::clauses_where_patterns[] The `name` and `age` values for nodes that have an outgoing relationship to `Timothy` are returned: @@ -618,12 +636,14 @@ To check if an element exists in a list, use the `IN` operator. The below query checks whether a property exists in a literal list: .Query +// tag::clauses_where_lists[] [source, cypher] ---- MATCH (a:Person) WHERE a.name IN ['Peter', 'Timothy'] RETURN a.name, a.age ---- +// end::clauses_where_lists[] .Result [role="queryresult",options="header,footer",cols="2*(otherPerson) WITH *, type(r) AS connectionType RETURN person.name, otherPerson.name, connectionType ---- +// end::clauses_with_wildcard[] This query returns the names of all related persons and the type of relationship between them. From d20cb4b8aafbf76872d5bb2100123212a743b1d8 Mon Sep 17 00:00:00 2001 From: Richard Sill <156673635+rsill-neo4j@users.noreply.github.com> Date: Tue, 14 Jan 2025 11:29:38 +0100 Subject: [PATCH 68/93] tags for clause section (#1138) --- modules/ROOT/pages/clauses/finish.adoc | 4 +- modules/ROOT/pages/clauses/foreach.adoc | 48 +++++++++++++++++++++++- modules/ROOT/pages/clauses/limit.adoc | 4 ++ modules/ROOT/pages/clauses/load-csv.adoc | 16 +++++++- modules/ROOT/pages/clauses/order-by.adoc | 8 ++++ modules/ROOT/pages/clauses/skip.adoc | 6 +++ modules/ROOT/pages/clauses/unwind.adoc | 6 +++ modules/ROOT/pages/clauses/use.adoc | 6 ++- 8 files changed, 94 insertions(+), 4 deletions(-) diff --git a/modules/ROOT/pages/clauses/finish.adoc b/modules/ROOT/pages/clauses/finish.adoc index b233b4896..2d3315e13 100644 --- a/modules/ROOT/pages/clauses/finish.adoc +++ b/modules/ROOT/pages/clauses/finish.adoc @@ -3,17 +3,19 @@ [[query-finish]] = FINISH -A query ending in `FINISH` — instead of `RETURN` — has no result but executes all its side effects. +A query ending in `FINISH` -- instead of `RETURN` -- has no result but executes all its side effects. `FINISH` was introduced as part of Cypher's xref:appendix/gql-conformance/index.adoc[]. The following read query successfully executes but has no results: .Query +// tag::clauses_finish_match[] [source, cypher] ---- MATCH (p:Person) FINISH ---- +// end::clauses_finish_match[] The following query has no result but creates one node with the label `Person`: diff --git a/modules/ROOT/pages/clauses/foreach.adoc b/modules/ROOT/pages/clauses/foreach.adoc index b594ecace..2132954e6 100644 --- a/modules/ROOT/pages/clauses/foreach.adoc +++ b/modules/ROOT/pages/clauses/foreach.adoc @@ -33,15 +33,17 @@ CREATE [[foreach-mark-all-nodes-along-a-path]] == Mark all nodes along a path -This query will set the property `marked` to `true` on all nodes along a path. +This query sets the property `marked` to `true` on all nodes along a path. .Query +// tag::clauses_foreach_node[] [source, cypher, indent=0] ---- MATCH p=(start)-[*]->(finish) WHERE start.name = 'A' AND finish.name = 'D' FOREACH (n IN nodes(p) | SET n.marked = true) ---- +// end::clauses_foreach_node[] .Result [role="queryresult",options="footer",cols="1*(finish) +WHERE start.name = 'A' AND finish.name = 'D' +FOREACH ( r IN relationships(p) | SET r.marked = true ) +---- +// end::clauses_foreach_relationship[] + +.Result +[role="queryresult",options="footer",cols="1* Date: Tue, 14 Jan 2025 11:42:12 +0100 Subject: [PATCH 69/93] 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 ce32664f7a89b0ebe85980df520cdf0375568039 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 70/93] 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 a08608f9e..6b4e1657b 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 32ccca07ec44cd98a1c0810a587c0c2eba40fb5f 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:51:35 +0100 Subject: [PATCH 71/93] fix antora for 2025.01 (#1164) --- antora.yml | 4 ++-- preview.yml | 7 ------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/antora.yml b/antora.yml index 51d116ceb..43779c5ed 100644 --- a/antora.yml +++ b/antora.yml @@ -1,11 +1,11 @@ name: cypher-manual title: Cypher Manual -version: '2025' +version: '5' start_page: ROOT:introduction/index.adoc nav: - modules/ROOT/content-nav.adoc asciidoc: attributes: - neo4j-version: '2025' + neo4j-version: '2025.01' neo4j-version-minor: '2025.01' neo4j-version-exact: '2025.01' diff --git a/preview.yml b/preview.yml index 50f2281c1..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: '2025' - sitemap_loc_version: 'current' - move_sitemaps_to_components: true - asciidoc: extensions: - "@neo4j-documentation/remote-include" From be0343d0409e95efd7929ec0d1ee9a6902a88de6 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 72/93] 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 a96b96d08..c283399c8 100644 --- a/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc +++ b/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc @@ -4118,30 +4118,32 @@ 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 | 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 ---- @@ -4177,30 +4179,32 @@ 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 | 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 ---- @@ -4406,25 +4410,27 @@ Runtime SLOTTED Runtime version {neo4j-version-minor} -+-------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+ -| 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 ---- @@ -4465,29 +4471,31 @@ 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 | `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 ---- @@ -4528,29 +4536,31 @@ 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 | `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 fc34537a4ab14017518fa0eafef9939474eb769e Mon Sep 17 00:00:00 2001 From: Neil Dewhurst Date: Thu, 16 Jan 2025 08:20:58 +0000 Subject: [PATCH 73/93] Table fixes, remove sitemap extension from playbook (#1167) 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/call.adoc | 6 +++--- modules/ROOT/pages/clauses/where.adoc | 2 +- modules/ROOT/pages/functions/aggregating.adoc | 2 +- modules/ROOT/pages/syntax/operators.adoc | 4 ++-- modules/ROOT/pages/values-and-types/temporal.adoc | 1 - publish.yml | 7 ------- 6 files changed, 7 insertions(+), 15 deletions(-) diff --git a/modules/ROOT/pages/clauses/call.adoc b/modules/ROOT/pages/clauses/call.adoc index 658127b3a..6f2e40205 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 c0487cb30..060b49136 100644 --- a/modules/ROOT/pages/clauses/where.adoc +++ b/modules/ROOT/pages/clauses/where.adoc @@ -384,7 +384,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 76ae6984c..9bb8d535f 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/syntax/operators.adoc b/modules/ROOT/pages/syntax/operators.adoc index b6ce384ab..599ccf677 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 bba317da5..546668428 100644 --- a/modules/ROOT/pages/values-and-types/temporal.adoc +++ b/modules/ROOT/pages/values-and-types/temporal.adoc @@ -505,7 +505,6 @@ For more information, see the xref::values-and-types/temporal.adoc#cypher-tempor | | | -| |=== diff --git a/publish.yml b/publish.yml index d321d30c6..dbff37d99 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: '2025' - sitemap_loc_version: 'current' - move_sitemaps_to_components: true - asciidoc: extensions: - "@neo4j-documentation/remote-include" From 0f8ffbd6a2748bb021db2d6c7444e6fb1814e0d0 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:30:43 +0100 Subject: [PATCH 74/93] Remove redundant antora attributes (#1168) --- antora.yml | 2 - .../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 +- 7 files changed, 173 insertions(+), 175 deletions(-) diff --git a/antora.yml b/antora.yml index 43779c5ed..92fdbdc87 100644 --- a/antora.yml +++ b/antora.yml @@ -7,5 +7,3 @@ nav: asciidoc: attributes: neo4j-version: '2025.01' - neo4j-version-minor: '2025.01' - neo4j-version-exact: '2025.01' 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 c283399c8..fb1cfb99f 100644 --- a/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc +++ b/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc @@ -130,7 +130,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -173,7 +173,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -216,7 +216,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -260,7 +260,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -300,7 +300,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -343,7 +343,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -386,7 +386,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -428,7 +428,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -467,7 +467,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -509,7 +509,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -558,7 +558,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -602,7 +602,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -652,7 +652,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -696,7 +696,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -739,7 +739,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -781,7 +781,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -826,7 +826,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -870,7 +870,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -922,7 +922,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -979,7 +979,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1030,7 +1030,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1079,7 +1079,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1124,7 +1124,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1169,7 +1169,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1207,7 +1207,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 @@ -1284,7 +1284,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1325,7 +1325,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1367,7 +1367,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1412,7 +1412,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1453,7 +1453,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1497,7 +1497,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1542,7 +1542,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1590,7 +1590,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1635,7 +1635,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1681,7 +1681,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1731,7 +1731,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1775,7 +1775,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1817,7 +1817,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1861,7 +1861,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1912,7 +1912,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -1956,7 +1956,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2000,7 +2000,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2044,7 +2044,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2088,7 +2088,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2132,7 +2132,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2176,7 +2176,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2220,7 +2220,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2263,7 +2263,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2305,7 +2305,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2348,7 +2348,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2391,7 +2391,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2442,7 +2442,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2488,7 +2488,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2534,7 +2534,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2580,7 +2580,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2633,7 +2633,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2683,7 +2683,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 | @@ -2739,7 +2739,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 | @@ -2797,7 +2797,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 | @@ -2860,7 +2860,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 | +--------------------+-----------------------------------------+----------------+------+---------+------------------------+ @@ -2921,7 +2921,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -2978,7 +2978,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3037,7 +3037,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 | @@ -3098,7 +3098,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 | @@ -3157,7 +3157,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 | @@ -3215,7 +3215,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3263,7 +3263,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3322,7 +3322,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 | @@ -3377,7 +3377,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3435,7 +3435,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3494,7 +3494,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3547,7 +3547,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3612,7 +3612,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3673,7 +3673,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3720,7 +3720,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3766,7 +3766,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3817,7 +3817,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3865,7 +3865,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3911,7 +3911,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -3957,7 +3957,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4010,7 +4010,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4065,7 +4065,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4114,7 +4114,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4175,7 +4175,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4239,7 +4239,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4296,7 +4296,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4347,7 +4347,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4408,7 +4408,7 @@ Planner COST Runtime SLOTTED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +--------------------+----+----------------------------------------+----------------+------+---------+----------------+------------------------+ | Operator | Id | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | @@ -4467,7 +4467,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4532,7 +4532,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4601,7 +4601,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4663,7 +4663,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4715,7 +4715,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4762,7 +4762,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4807,7 +4807,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4852,7 +4852,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4896,7 +4896,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4938,7 +4938,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -4980,7 +4980,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 | @@ -5033,7 +5033,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5082,7 +5082,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5125,7 +5125,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5178,7 +5178,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5228,7 +5228,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5271,7 +5271,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5313,7 +5313,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5356,7 +5356,7 @@ Planner COST Runtime PARALLEL -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5405,7 +5405,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5454,7 +5454,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5502,7 +5502,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5553,7 +5553,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5598,7 +5598,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5645,7 +5645,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5691,7 +5691,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5746,7 +5746,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5790,7 +5790,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5836,7 +5836,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5887,7 +5887,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5934,7 +5934,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -5989,7 +5989,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 | @@ -6035,7 +6035,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -6090,7 +6090,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -6138,7 +6138,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -6183,7 +6183,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -6228,7 +6228,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -6273,7 +6273,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -6319,7 +6319,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -6363,7 +6363,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -6410,7 +6410,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -6463,7 +6463,7 @@ Planner COST Runtime PIPELINED -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} Batch size 128 @@ -6526,7 +6526,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 | @@ -6578,7 +6578,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 | @@ -6641,7 +6641,7 @@ Planner ADMINISTRATION Runtime SCHEMA -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +-------------------+------------------------------------------------------------------+ | Operator | Details | @@ -6682,7 +6682,7 @@ Planner ADMINISTRATION Runtime SCHEMA -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +--------------------------------+------------------------------------------------------------------+ | Operator | Details | @@ -6721,7 +6721,7 @@ Planner ADMINISTRATION Runtime SCHEMA -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +-----------------+---------------------------------+ | Operator | Details | @@ -6758,7 +6758,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 | @@ -6801,7 +6801,7 @@ Planner ADMINISTRATION Runtime SCHEMA -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +--------------+-----------------------------------------------+ | Operator | Details | @@ -6842,7 +6842,7 @@ Planner ADMINISTRATION Runtime SCHEMA -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +---------------------------+----------------------------------------------------+ | Operator | Details | @@ -6880,7 +6880,7 @@ Planner ADMINISTRATION Runtime SCHEMA -Runtime version {neo4j-version-minor} +Runtime version {neo4j-version} +------------+---------------+ | Operator | Details | @@ -6917,7 +6917,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 | @@ -6959,7 +6959,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 | @@ -6998,7 +6998,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 | @@ -7035,7 +7035,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 | @@ -7073,7 +7073,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 | @@ -7112,7 +7112,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 060c5646f..d99788eaa 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 e493ce1794ab8ffde53f2e13b4113d8472c56b37 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 75/93] 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 0f6c13678..18669961e 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/{page-ver [[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 2ab239466..cb6d57af4 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 2b2241a9146ba4c9472773d70e6d7fa2ec33e5d8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Jan 2025 10:42:11 +0100 Subject: [PATCH 76/93] Bump @neo4j-antora/antora-table-footnotes from 0.3.2 to 0.3.3 in the prod-dependencies group (#1171) Bumps the prod-dependencies group with 1 update: @neo4j-antora/antora-table-footnotes. Updates `@neo4j-antora/antora-table-footnotes` from 0.3.2 to 0.3.3 [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@neo4j-antora/antora-table-footnotes&package-manager=npm_and_yarn&previous-version=0.3.2&new-version=0.3.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 32 +++++++++++++++++++------------- package.json | 2 +- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index 759f2eed3..690453aee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "@neo4j-antora/antora-add-notes": "^0.3.1", "@neo4j-antora/antora-modify-sitemaps": "^0.6.0", "@neo4j-antora/antora-page-roles": "^0.3.1", - "@neo4j-antora/antora-table-footnotes": "^0.3.2", + "@neo4j-antora/antora-table-footnotes": "^0.3.3", "@neo4j-antora/mark-terms": "1.1.0", "@neo4j-documentation/macros": "^1.0.4", "@neo4j-documentation/remote-include": "^1.0.0", @@ -303,9 +303,10 @@ } }, "node_modules/@asciidoctor/core": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/@asciidoctor/core/-/core-2.2.6.tgz", - "integrity": "sha512-TmB2K5UfpDpSbCNBBntXzKHcAk2EA3/P68jmWvmJvglVUdkO9V6kTAuXVe12+h6C4GK0ndwuCrHHtEVcL5t6pQ==", + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/@asciidoctor/core/-/core-2.2.8.tgz", + "integrity": "sha512-oozXk7ZO1RAd/KLFLkKOhqTcG4GO3CV44WwOFg2gMcCsqCUTarvMT7xERIoWW2WurKbB0/ce+98r01p8xPOlBw==", + "license": "MIT", "dependencies": { "asciidoctor-opal-runtime": "0.3.3", "unxhr": "1.0.1" @@ -340,9 +341,13 @@ "integrity": "sha512-RqmMHcTyM87lJAhjSPdkoUzFxQCjsM2N4+ryVK4GIahAJyNV9OYydBrsjGrDbIh6F4YS+LWG+SXyvLD2zJ1keQ==" }, "node_modules/@neo4j-antora/antora-table-footnotes": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@neo4j-antora/antora-table-footnotes/-/antora-table-footnotes-0.3.2.tgz", - "integrity": "sha512-DXEGVHMJumoKiY/ZCaGRTXl2OhPziPCHT+arj18TmpU50sUs+hyjOPuTkUXUvBwNZwm109Nm1PJPvKLVIJCZSg==" + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@neo4j-antora/antora-table-footnotes/-/antora-table-footnotes-0.3.3.tgz", + "integrity": "sha512-0vKB9nMJpfZdKTJc5vOJrNCFTcae61rnw9XyPQX2aibJN4vUTEeKhIS6IaVJWW5M1CflVIU3LoZDpDzeA/GEHw==", + "license": "MIT", + "peerDependencies": { + "@asciidoctor/core": "2.2.8" + } }, "node_modules/@neo4j-antora/mark-terms": { "version": "1.1.0", @@ -2754,9 +2759,9 @@ } }, "@asciidoctor/core": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/@asciidoctor/core/-/core-2.2.6.tgz", - "integrity": "sha512-TmB2K5UfpDpSbCNBBntXzKHcAk2EA3/P68jmWvmJvglVUdkO9V6kTAuXVe12+h6C4GK0ndwuCrHHtEVcL5t6pQ==", + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/@asciidoctor/core/-/core-2.2.8.tgz", + "integrity": "sha512-oozXk7ZO1RAd/KLFLkKOhqTcG4GO3CV44WwOFg2gMcCsqCUTarvMT7xERIoWW2WurKbB0/ce+98r01p8xPOlBw==", "requires": { "asciidoctor-opal-runtime": "0.3.3", "unxhr": "1.0.1" @@ -2786,9 +2791,10 @@ "integrity": "sha512-RqmMHcTyM87lJAhjSPdkoUzFxQCjsM2N4+ryVK4GIahAJyNV9OYydBrsjGrDbIh6F4YS+LWG+SXyvLD2zJ1keQ==" }, "@neo4j-antora/antora-table-footnotes": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@neo4j-antora/antora-table-footnotes/-/antora-table-footnotes-0.3.2.tgz", - "integrity": "sha512-DXEGVHMJumoKiY/ZCaGRTXl2OhPziPCHT+arj18TmpU50sUs+hyjOPuTkUXUvBwNZwm109Nm1PJPvKLVIJCZSg==" + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@neo4j-antora/antora-table-footnotes/-/antora-table-footnotes-0.3.3.tgz", + "integrity": "sha512-0vKB9nMJpfZdKTJc5vOJrNCFTcae61rnw9XyPQX2aibJN4vUTEeKhIS6IaVJWW5M1CflVIU3LoZDpDzeA/GEHw==", + "requires": {} }, "@neo4j-antora/mark-terms": { "version": "1.1.0", diff --git a/package.json b/package.json index 290d1c494..bcbab81bb 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "@neo4j-antora/antora-add-notes": "^0.3.1", "@neo4j-antora/antora-modify-sitemaps": "^0.6.0", "@neo4j-antora/antora-page-roles": "^0.3.1", - "@neo4j-antora/antora-table-footnotes": "^0.3.2", + "@neo4j-antora/antora-table-footnotes": "^0.3.3", "@neo4j-antora/mark-terms": "1.1.0", "@neo4j-documentation/macros": "^1.0.4", "@neo4j-documentation/remote-include": "^1.0.0", From 899b365411ee51ccadcb2c050a8aeb24a2ba6820 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 13:18:26 +0100 Subject: [PATCH 77/93] Fix external links (#1172) The page-version attribute between Cypher and other manuals wont work with the release of 2025.01 --- modules/ROOT/pages/administration/index.adoc | 10 ++-- .../gql-conformance/additional-cypher.adoc | 12 ++-- .../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 | 50 ++++++++-------- 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 | 46 +++++++------- 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, 207 insertions(+), 207 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 32f648563..fd877826e 100644 --- a/modules/ROOT/pages/appendix/gql-conformance/additional-cypher.adoc +++ b/modules/ROOT/pages/appendix/gql-conformance/additional-cypher.adoc @@ -208,7 +208,7 @@ REMOVE n:$($label) | 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 xref:clauses/use.adoc[`USE`] clause. -As of Neo4j 5.26, it is supported on both link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/[standard and composite databases]. +As of Neo4j 5.26, it is supported on both link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/[standard and composite databases]. On earlier versions, it is only supported on composite databases. | xref:functions/graph.adoc#functions-graph-byname[`graph.byName()`] @@ -658,23 +658,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 019c73efc..c81f453a5 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 6f2e40205..283b594d2 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] @@ -206,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/{page-version}/reference/procedures/[Operations Manual -> Procedures] or in the `signature` column returned by a `SHOW PROCEDURES` command (see example below). +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] @@ -271,7 +271,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 18669961e..c4a9dc4b7 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 d0e421713..66969b94a 100644 --- a/modules/ROOT/pages/clauses/index.adoc +++ b/modules/ROOT/pages/clauses/index.adoc @@ -282,6 +282,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 38d4ea035..e8e391eb9 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 b79eba881..ed422d1c2 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 link:{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 3b8490dfe..b29ee66ca 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 03faf9a30..4cb1bf357 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 @@ -78,10 +78,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. @@ -95,9 +95,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`]. ==== @@ -1099,8 +1099,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. //// @@ -1168,7 +1168,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 b1a099770..6adc11c60 100644 --- a/modules/ROOT/pages/clauses/transaction-clauses.adoc +++ b/modules/ROOT/pages/clauses/transaction-clauses.adoc @@ -208,7 +208,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:: @@ -229,7 +229,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. @@ -370,7 +370,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:: @@ -395,7 +395,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 43959819f..1e79b1efa 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 283d567e3..79f7bbf16 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. @@ -1433,7 +1433,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 ====== @@ -1679,7 +1679,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 ba695630f..4347777d2 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 @@ -304,7 +304,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 78da37687..67212f833 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -153,7 +153,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]. @@ -166,7 +166,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[] @@ -179,7 +179,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[] @@ -212,7 +212,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| @@ -226,7 +226,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[] @@ -235,7 +235,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| @@ -317,7 +317,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 @@ -335,7 +335,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. @@ -355,7 +355,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]] @@ -447,7 +447,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[] @@ -475,7 +475,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). @@ -490,7 +490,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. @@ -513,7 +513,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. @@ -663,7 +663,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[] @@ -1095,7 +1095,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]. |=== @@ -1328,7 +1328,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[] @@ -1948,7 +1948,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[] @@ -4622,7 +4622,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[] @@ -4890,28 +4890,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. @@ -5284,21 +5284,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 839231680..81f176db1 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()+ @@ -199,7 +199,7 @@ For more information, see xref:subqueries/call-subquery.adoc#import-variables[CA |=== | 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. -| As of Neo4j 5.26, `graph.byElementId()` is supported on both link:{neo4j-docs-base-uri}/operations-manual/{page-version}/database-administration/[standard and composite databases]. +| As of Neo4j 5.26, `graph.byElementId()` is supported on both link:{neo4j-docs-base-uri}/operations-manual/current/database-administration/[standard and composite databases]. On earlier versions, it is only supported on 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 bb324d520..1e80dd74a 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 cc17fdc3a..6ec56dd22 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 2773b4848..7aeaa1d16 100644 --- a/modules/ROOT/pages/genai-integrations.adoc +++ b/modules/ROOT/pages/genai-integrations.adoc @@ -23,7 +23,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]. [NOTE] Prior to Neo4j 5.23, the GenAI plugin was only available on Neo4j Enterprise Edition. @@ -39,7 +39,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 (running version 5.17 or later). -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 c523f2b77..3343bb9e3 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. @@ -788,7 +788,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]] @@ -1033,7 +1033,7 @@ With `IF EXISTS`, no error is thrown and nothing happens should the index not ex As of Neo4j 5.17, an informational notification is instead 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 e8c4eee44..7f0268162 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 f2adb3aa6..475aa6308 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 @@ As of Neo4j 5.17, an informational notification is instead returned showing the As of Neo4j 5.16, 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 @@ -129,13 +129,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. @@ -391,7 +391,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 b5d4f9bdb..0f60dca75 100644 --- a/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc +++ b/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc @@ -30,7 +30,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). -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`. @@ -84,7 +84,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 label:new[Introduced in 5.15] [source, cypher] @@ -110,7 +110,7 @@ In this example, the vector dimension is explicitly set to `1536` and the vector 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. +Prior to Neo4j 5.15, node vector indexes were created using the link:{neo4j-docs-base-uri}/operations-manual/current/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: @@ -194,7 +194,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. @@ -240,7 +240,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` label:new[Introduced in 5.18] [source,syntax] @@ -257,7 +257,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] @@ -272,7 +272,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 ==== @@ -343,7 +343,7 @@ A vector index is dropped by using the xref:indexes/search-performance-indexes/m As of Neo4j 5.16, 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] @@ -478,30 +478,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. label:new[Introduced in 5.18] | 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] +| 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[] label:new[Introduced in 5.13] | 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[] label:new[Introduced in 5.18] |=== @@ -535,7 +535,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] -- @@ -594,7 +594,7 @@ This is caused by an issue in the handling of index capabilities on followers. -- 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]. +For more information about clustering in Neo4j, see the link:{neo4j-docs-base-uri}/operations-manual/current/clustering[Operations Manual -> Clustering]. -- | Neo4j 5.14 @@ -611,9 +611,9 @@ To work around this issue if you need to run multiple vector index queries and m | 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`] +* link:{neo4j-docs-base-uri}/operations-manual/current/reference/procedures/#procedure_db_create_setVectorProperty[`db.create.setVectorProperty`] +* link:{neo4j-docs-base-uri}/operations-manual/current/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_queryNodes[`db.index.vector.queryNodes`] [NOTE] -- @@ -636,7 +636,7 @@ d| The validation for xref:indexes/semantic-indexes/vector-indexes.adoc#similari 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`. +| link:{neo4j-docs-base-uri}/operations-manual/current/#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] -- @@ -648,7 +648,7 @@ It is _recommended_ to normalize your vectors (if needed), and use a xref:indexe | 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: +| link:{neo4j-docs-base-uri}/operations-manual/current/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' ---- diff --git a/modules/ROOT/pages/indexes/syntax.adoc b/modules/ROOT/pages/indexes/syntax.adoc index 47183f194..e1536f2a9 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 As of Neo4j 5.17, an informational notification is instead 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..6773e48ed 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/current/authentication-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 04f985752..a930a1c34 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 fb1cfb99f..4240d527c 100644 --- a/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc +++ b/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc @@ -1522,7 +1522,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 ====== @@ -1569,7 +1569,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 ====== @@ -1615,7 +1615,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 ====== @@ -1660,7 +1660,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 b2ea62653..ad8cfbb3a 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 015a83712..f9de72cb0 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 9fa9f20bf..5da6b9245 100644 --- a/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc +++ b/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc @@ -216,7 +216,7 @@ For larger data sets, you might want to use larger batch sizes, such as `10000 R [[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]. +As of Neo4j 5.18, `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. @@ -656,7 +656,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 a483e62f7..68e0824c2 100644 --- a/modules/ROOT/pages/syntax/naming.adoc +++ b/modules/ROOT/pages/syntax/naming.adoc @@ -76,7 +76,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 06a4f0605..f37a97fb4 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 546668428..ddcb589c1 100644 --- a/modules/ROOT/pages/values-and-types/temporal.adoc +++ b/modules/ROOT/pages/values-and-types/temporal.adoc @@ -75,7 +75,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 230001bb576dab9332f50c017414aeec8a8e044e Mon Sep 17 00:00:00 2001 From: Gem Lamont <106068376+gem-neo4j@users.noreply.github.com> Date: Thu, 23 Jan 2025 08:54:04 +0100 Subject: [PATCH 78/93] 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 df9e288cce7d9dbe258114dda4968ae547c3878a 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 79/93] 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 4240d527c..720d0d721 100644 --- a/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc +++ b/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc @@ -4118,32 +4118,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 ---- @@ -4179,32 +4177,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 ---- @@ -4410,27 +4406,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 ---- @@ -4471,31 +4465,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 ---- @@ -4536,31 +4528,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 c4762e722f5528db7189f33efce873ded3bad73c 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 80/93] 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 54db83bde..66887f583 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 9c85b23c9febb91869b5fe5a8e1cfb0152fcf249 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 81/93] 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 283b594d2..c007a50f4 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 060b49136..9a3bb0c25 100644 --- a/modules/ROOT/pages/clauses/where.adoc +++ b/modules/ROOT/pages/clauses/where.adoc @@ -384,7 +384,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 9bb8d535f..9e57a6d1d 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 599ccf677..1da8140a2 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 ddcb589c1..9d7fd4a25 100644 --- a/modules/ROOT/pages/values-and-types/temporal.adoc +++ b/modules/ROOT/pages/values-and-types/temporal.adoc @@ -505,7 +505,6 @@ For more information, see the xref::values-and-types/temporal.adoc#cypher-tempor | | | - |=== From 4ceb45c71e8856ac72f22f9ac5ddcb28afab233b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Feb 2025 08:54:49 +0100 Subject: [PATCH 82/93] Bump @neo4j-antora/antora-modify-sitemaps from 0.6.0 to 0.6.1 in the prod-dependencies group (#1180) Bumps the prod-dependencies group with 1 update: @neo4j-antora/antora-modify-sitemaps. Updates `@neo4j-antora/antora-modify-sitemaps` from 0.6.0 to 0.6.1 [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@neo4j-antora/antora-modify-sitemaps&package-manager=npm_and_yarn&previous-version=0.6.0&new-version=0.6.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 15 ++++++++------- package.json | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 690453aee..89feaa5c6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@antora/cli": "^3.1.10", "@antora/site-generator-default": "^3.1.10", "@neo4j-antora/antora-add-notes": "^0.3.1", - "@neo4j-antora/antora-modify-sitemaps": "^0.6.0", + "@neo4j-antora/antora-modify-sitemaps": "^0.6.1", "@neo4j-antora/antora-page-roles": "^0.3.1", "@neo4j-antora/antora-table-footnotes": "^0.3.3", "@neo4j-antora/mark-terms": "1.1.0", @@ -328,9 +328,10 @@ "integrity": "sha512-0zapKJr9U+cNBaz5m342Zqb5+1VuaFuybhGtSzEdiG4MRmvsAZunxLX7lSG0cWm6L4DlQa0jzOKYYzpkqoap/g==" }, "node_modules/@neo4j-antora/antora-modify-sitemaps": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@neo4j-antora/antora-modify-sitemaps/-/antora-modify-sitemaps-0.6.0.tgz", - "integrity": "sha512-QdlLZoN4jL9X39RwphNQOx6FnjFYzZIdm7OhBaf7FpP31eaGXgeyfMquWQm3yNPrqrut1ax4ogGrQNeRBmAxVg==", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@neo4j-antora/antora-modify-sitemaps/-/antora-modify-sitemaps-0.6.1.tgz", + "integrity": "sha512-3b4YXP5e7izBTAFlrUdkPzsdDRJ2LRWVFDGi/ibfArOQDMAG+z9Ta9wq5gTfUYQMt0uNUItlj+xVdt0ioQsxhA==", + "license": "MIT", "dependencies": { "semver": "^7.6.3" } @@ -2778,9 +2779,9 @@ "integrity": "sha512-0zapKJr9U+cNBaz5m342Zqb5+1VuaFuybhGtSzEdiG4MRmvsAZunxLX7lSG0cWm6L4DlQa0jzOKYYzpkqoap/g==" }, "@neo4j-antora/antora-modify-sitemaps": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@neo4j-antora/antora-modify-sitemaps/-/antora-modify-sitemaps-0.6.0.tgz", - "integrity": "sha512-QdlLZoN4jL9X39RwphNQOx6FnjFYzZIdm7OhBaf7FpP31eaGXgeyfMquWQm3yNPrqrut1ax4ogGrQNeRBmAxVg==", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@neo4j-antora/antora-modify-sitemaps/-/antora-modify-sitemaps-0.6.1.tgz", + "integrity": "sha512-3b4YXP5e7izBTAFlrUdkPzsdDRJ2LRWVFDGi/ibfArOQDMAG+z9Ta9wq5gTfUYQMt0uNUItlj+xVdt0ioQsxhA==", "requires": { "semver": "^7.6.3" } diff --git a/package.json b/package.json index bcbab81bb..c8a47b37f 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "@antora/cli": "^3.1.10", "@antora/site-generator-default": "^3.1.10", "@neo4j-antora/antora-add-notes": "^0.3.1", - "@neo4j-antora/antora-modify-sitemaps": "^0.6.0", + "@neo4j-antora/antora-modify-sitemaps": "^0.6.1", "@neo4j-antora/antora-page-roles": "^0.3.1", "@neo4j-antora/antora-table-footnotes": "^0.3.3", "@neo4j-antora/mark-terms": "1.1.0", From aa05349298d2ad13d4486bb440a9db952331da80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Tue, 4 Feb 2025 09:49:49 +0100 Subject: [PATCH 83/93] Update antora for 2025.02 (#1182) --- antora.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/antora.yml b/antora.yml index 92fdbdc87..52a8c041c 100644 --- a/antora.yml +++ b/antora.yml @@ -6,4 +6,4 @@ nav: - modules/ROOT/content-nav.adoc asciidoc: attributes: - neo4j-version: '2025.01' + neo4j-version: '2025.02' From 4f0c31861c97d37e49ee232e4bed706ff8eb9657 Mon Sep 17 00:00:00 2001 From: Stefano Ottolenghi Date: Wed, 12 Feb 2025 11:22:48 +0100 Subject: [PATCH 84/93] Typo in example --- modules/ROOT/pages/genai-integrations.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ROOT/pages/genai-integrations.adoc b/modules/ROOT/pages/genai-integrations.adoc index 7aeaa1d16..b16492a94 100644 --- a/modules/ROOT/pages/genai-integrations.adoc +++ b/modules/ROOT/pages/genai-integrations.adoc @@ -180,7 +180,7 @@ CALL db.create.setNodeVectorProperty(moviesList[index], 'embedding', vector) // [source, cypher, role=test-skip] ---- MATCH (m:Movie WHERE m.plot IS NOT NULL) -WITH collect(m) AS moviesList // <1> +WITH collect(m) AS moviesList, // <1> count(*) AS total, 100 AS batchSize // <2> UNWIND range(0, total, batchSize) AS batchStart // <3> From cfec2cf0bf5f783b3cbc73ffab0b8063ac214821 Mon Sep 17 00:00:00 2001 From: Stefano Ottolenghi Date: Wed, 12 Feb 2025 13:47:09 +0100 Subject: [PATCH 85/93] Add concurrency in GenAI example --- modules/ROOT/pages/genai-integrations.adoc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/ROOT/pages/genai-integrations.adoc b/modules/ROOT/pages/genai-integrations.adoc index b16492a94..d229abf79 100644 --- a/modules/ROOT/pages/genai-integrations.adoc +++ b/modules/ROOT/pages/genai-integrations.adoc @@ -183,12 +183,12 @@ MATCH (m:Movie WHERE m.plot IS NOT NULL) WITH collect(m) AS moviesList, // <1> count(*) AS total, 100 AS batchSize // <2> -UNWIND range(0, total, batchSize) AS batchStart // <3> +UNWIND range(0, total-1, batchSize) AS batchStart // <3> CALL (moviesList, batchStart, batchSize) { // <4> 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> +} IN CONCURRENT TRANSACTIONS OF 1 ROW <7> ---- <1> xref:functions/aggregating.adoc#functions-collect[Collect] all returned `Movie` nodes into a `LIST`. @@ -196,12 +196,14 @@ CALL (moviesList, batchStart, batchSize) { // <4> Because vector embeddings can be very large, a larger batch size may require significantly more memory on the Neo4j server. Too large a batch size may also exceed the provider's threshold. <3> Process `Movie` nodes in increments of `batchSize`. +The end range `total-1` is due to `range` being inclusive on both ends. <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. <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. +Concurrency in transactions was introduced in Cypher 5.21 (see xref:subqueries/subqueries-in-transactions.adoc#concurrent-transactions[`CALL` subqueries -> Concurrent transactions]). [NOTE] This example may not scale to larger datasets, as `collect(m)` requires the whole result set to be loaded in memory. From 483736972e7e5eb867616810ac6cf34bb64f055a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Wed, 19 Feb 2025 14:27:16 +0100 Subject: [PATCH 86/93] Add examples to temporal instant values (#1189) --- .../ROOT/pages/values-and-types/temporal.adoc | 584 +++++++++++++++--- 1 file changed, 493 insertions(+), 91 deletions(-) diff --git a/modules/ROOT/pages/values-and-types/temporal.adoc b/modules/ROOT/pages/values-and-types/temporal.adoc index 9d7fd4a25..106107711 100644 --- a/modules/ROOT/pages/values-and-types/temporal.adoc +++ b/modules/ROOT/pages/values-and-types/temporal.adoc @@ -511,145 +511,397 @@ For more information, see the xref::values-and-types/temporal.adoc#cypher-tempor [[cypher-temporal-specify-instant-examples]] === Examples -Below are examples of parsing instant values using various temporal functions. -More information about these temporal functions can be found xref::functions/temporal/index.adoc[here]. +To work with a particular temporal instant type, its corresponding xref:functions/temporal/index.adoc[function] must be used. +For example, in order to create a property value of type `ZONED DATETIME`, the xref:functions/temporal/index.adoc#functions-datetime[`datetime()`] function must be used. -.+datetime+ -====== +For specific examples, see: -Parsing a `ZONED DATETIME` using the _calendar date_ format: +* xref:values-and-types/temporal.adoc#examples-date[`DATE`] +* xref:values-and-types/temporal.adoc#examples-localtime[`LOCAL TIME`] +* xref:values-and-types/temporal.adoc#examples-zonedtime[`ZONED TIME`] +* xref:values-and-types/temporal.adoc#examples-local-datetime[`LOCAL DATETIME`] +* xref:values-and-types/temporal.adoc#examples-zoned-datetime[`ZONED DATETIME`] +* xref:values-and-types/temporal.adoc#examples-truncate[Truncating temporal values] -.Query +[[examples-date]] +==== `DATE` + +To work with `DATE` values, including creating, parsing, and extracting components, use the xref:functions/temporal/index.adoc#functions-date[`date()`] function. + +.`DATE` +====== + +.Create a `DATE` property value [source, cypher] ---- -RETURN datetime('2015-06-24T12:50:35.556+0100') AS theDateTime +CREATE (n:Label) +SET n.date = date("2025-02-18") +RETURN n.date AS date, valueType(n.date) AS temporalValueType ---- .Result -[role="queryresult",options="header,footer",cols="1* Date: Fri, 21 Feb 2025 13:10:22 +0100 Subject: [PATCH 87/93] Fixes + sign formatting in deprecations page (#1192) In the following place, the `+` sign needs to be escaped in order to go out of the previous context to render correctly ![image](https://github.com/user-attachments/assets/9629c7b3-12a1-4b9e-94fa-c9e3e604f511) --- .../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 67212f833..4256a09a7 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -98,7 +98,7 @@ label:deprecated[] ---- ... + n:A&B\|C ---- -a| Using an unparenthesized label expression predicate as the right-hand side operand of `+` is deprecated. +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| From 56dd7848558cc5c7962ac7cbcc10329a978f2b62 Mon Sep 17 00:00:00 2001 From: JoelBergstrand Date: Fri, 21 Feb 2025 14:01:25 +0100 Subject: [PATCH 88/93] Added note on dynamic labels in INSERT (#1193) 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/create.adoc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/ROOT/pages/clauses/create.adoc b/modules/ROOT/pages/clauses/create.adoc index 5b81fd75b..e5e1f7193 100644 --- a/modules/ROOT/pages/clauses/create.adoc +++ b/modules/ROOT/pages/clauses/create.adoc @@ -263,7 +263,8 @@ RETURN greta.name AS name, labels(greta) AS labels, type(rel) AS relType, collec == `INSERT` as a synonym of `CREATE` `INSERT` can be used as a synonym to `CREATE` for creating nodes and relationships, and was introduced as part of Cypher's xref:appendix/gql-conformance/index.adoc[]. -However, `INSERT` requires that multiple labels are separated by an ampersand `&` and not by colon `:`. +However, `INSERT` requires that multiple labels are separated by an ampersand `&` and not by colon `:`. +Additionally, `INSERT` does not support using dynamic node labels and relationship types. .Query [source, cypher, indent=0] From 277830d5ea212977280093a4870cb441d66f558e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Feb 2025 09:38:56 +0100 Subject: [PATCH 89/93] Bump the prod-dependencies group with 2 updates (#1196) Bumps the prod-dependencies group with 2 updates: @neo4j-antora/antora-add-notes and @neo4j-antora/antora-modify-sitemaps. Updates `@neo4j-antora/antora-add-notes` from 0.3.1 to 0.3.2 Updates `@neo4j-antora/antora-modify-sitemaps` from 0.6.1 to 0.7.0 Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 29 +++++++++++++++-------------- package.json | 4 ++-- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index 89feaa5c6..32a6cbab3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,8 +11,8 @@ "dependencies": { "@antora/cli": "^3.1.10", "@antora/site-generator-default": "^3.1.10", - "@neo4j-antora/antora-add-notes": "^0.3.1", - "@neo4j-antora/antora-modify-sitemaps": "^0.6.1", + "@neo4j-antora/antora-add-notes": "^0.3.2", + "@neo4j-antora/antora-modify-sitemaps": "^0.7.0", "@neo4j-antora/antora-page-roles": "^0.3.1", "@neo4j-antora/antora-table-footnotes": "^0.3.3", "@neo4j-antora/mark-terms": "1.1.0", @@ -323,14 +323,15 @@ "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==" }, "node_modules/@neo4j-antora/antora-add-notes": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@neo4j-antora/antora-add-notes/-/antora-add-notes-0.3.1.tgz", - "integrity": "sha512-0zapKJr9U+cNBaz5m342Zqb5+1VuaFuybhGtSzEdiG4MRmvsAZunxLX7lSG0cWm6L4DlQa0jzOKYYzpkqoap/g==" + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@neo4j-antora/antora-add-notes/-/antora-add-notes-0.3.2.tgz", + "integrity": "sha512-Jsv17dEBELSkqplEIZE9b5I2zjYPvoHi4momLRt1FfBRQnBTWbk4kkf2JQojRJ8mQEVscj2tApfTDOAUtAOSLA==", + "license": "MIT" }, "node_modules/@neo4j-antora/antora-modify-sitemaps": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@neo4j-antora/antora-modify-sitemaps/-/antora-modify-sitemaps-0.6.1.tgz", - "integrity": "sha512-3b4YXP5e7izBTAFlrUdkPzsdDRJ2LRWVFDGi/ibfArOQDMAG+z9Ta9wq5gTfUYQMt0uNUItlj+xVdt0ioQsxhA==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@neo4j-antora/antora-modify-sitemaps/-/antora-modify-sitemaps-0.7.0.tgz", + "integrity": "sha512-mx6KhD9rdxq/gMM8NxKOEkbaT8qG8U6VgEx2TPZ0yz4Udo3kYypiJ+hvQtKfcRz1WcU9hHzISV+gV3xvTab39A==", "license": "MIT", "dependencies": { "semver": "^7.6.3" @@ -2774,14 +2775,14 @@ "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==" }, "@neo4j-antora/antora-add-notes": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@neo4j-antora/antora-add-notes/-/antora-add-notes-0.3.1.tgz", - "integrity": "sha512-0zapKJr9U+cNBaz5m342Zqb5+1VuaFuybhGtSzEdiG4MRmvsAZunxLX7lSG0cWm6L4DlQa0jzOKYYzpkqoap/g==" + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@neo4j-antora/antora-add-notes/-/antora-add-notes-0.3.2.tgz", + "integrity": "sha512-Jsv17dEBELSkqplEIZE9b5I2zjYPvoHi4momLRt1FfBRQnBTWbk4kkf2JQojRJ8mQEVscj2tApfTDOAUtAOSLA==" }, "@neo4j-antora/antora-modify-sitemaps": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@neo4j-antora/antora-modify-sitemaps/-/antora-modify-sitemaps-0.6.1.tgz", - "integrity": "sha512-3b4YXP5e7izBTAFlrUdkPzsdDRJ2LRWVFDGi/ibfArOQDMAG+z9Ta9wq5gTfUYQMt0uNUItlj+xVdt0ioQsxhA==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@neo4j-antora/antora-modify-sitemaps/-/antora-modify-sitemaps-0.7.0.tgz", + "integrity": "sha512-mx6KhD9rdxq/gMM8NxKOEkbaT8qG8U6VgEx2TPZ0yz4Udo3kYypiJ+hvQtKfcRz1WcU9hHzISV+gV3xvTab39A==", "requires": { "semver": "^7.6.3" } diff --git a/package.json b/package.json index c8a47b37f..b86fe81ff 100644 --- a/package.json +++ b/package.json @@ -21,8 +21,8 @@ "dependencies": { "@antora/cli": "^3.1.10", "@antora/site-generator-default": "^3.1.10", - "@neo4j-antora/antora-add-notes": "^0.3.1", - "@neo4j-antora/antora-modify-sitemaps": "^0.6.1", + "@neo4j-antora/antora-add-notes": "^0.3.2", + "@neo4j-antora/antora-modify-sitemaps": "^0.7.0", "@neo4j-antora/antora-page-roles": "^0.3.1", "@neo4j-antora/antora-table-footnotes": "^0.3.3", "@neo4j-antora/mark-terms": "1.1.0", From 807ebe25395f5bc963dd62ab3ed770fa0963bc79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Wed, 26 Feb 2025 16:10:45 +0100 Subject: [PATCH 90/93] Clarify predicate function and empty list behavior (#1197) --- modules/ROOT/pages/functions/predicate.adoc | 73 +++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/modules/ROOT/pages/functions/predicate.adoc b/modules/ROOT/pages/functions/predicate.adoc index 2a6d9378d..08e39bc8e 100644 --- a/modules/ROOT/pages/functions/predicate.adoc +++ b/modules/ROOT/pages/functions/predicate.adoc @@ -54,6 +54,7 @@ CREATE .Considerations |=== | `null` is returned if the `list` is `null` or if the `predicate` evaluates to `null` for at least one element and does not evaluate to false for any other element. +| `all()` returns `true` if `list` is empty because there are no elements to falsify the `predicate`. |=== .+all()+ @@ -86,6 +87,23 @@ image::predicate_function_example.svg[width="300",role="middle"] |=== +.`all()` on an empty `LIST` +[source, cypher] +---- +WITH [] as emptyList +RETURN all(i in emptyList WHERE true) as allTrue, all(i in emptyList WHERE false) as allFalse +---- + +.Result +[role="queryresult",options="header,footer",cols="2* Date: Fri, 28 Feb 2025 08:55:17 +0100 Subject: [PATCH 91/93] update antora for 2025.03 (#1200) --- antora.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/antora.yml b/antora.yml index 52a8c041c..3c7aa133b 100644 --- a/antora.yml +++ b/antora.yml @@ -6,4 +6,4 @@ nav: - modules/ROOT/content-nav.adoc asciidoc: attributes: - neo4j-version: '2025.02' + neo4j-version: '2025.03' From 86b3a1efeebcc1e51e12345099f07258e5138c08 Mon Sep 17 00:00:00 2001 From: Neil Dewhurst Date: Fri, 28 Feb 2025 15:33:09 +0000 Subject: [PATCH 92/93] remove developer survey (#1202) --- publish.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/publish.yml b/publish.yml index dbff37d99..b5183d48d 100644 --- a/publish.yml +++ b/publish.yml @@ -53,10 +53,3 @@ asciidoc: cross-mark: icon:times[] neo4j-base-uri: '' neo4j-docs-base-uri: /docs - # Developer survey - page-ad-icon: ~ - page-ad-title: Neo4j Developer Survey - page-ad-description: Your input matters! Share your Feedback - page-ad-underline-role: button - page-ad-underline: Start Here - page-ad-link: https://neo4j.typeform.com/to/E6yOZ2Py?utm_source=GA&utm_medium=blurb&utm_campaign=survey From 02b35f6bc4e36739865cf6ad8e29e7e72dab1ce1 Mon Sep 17 00:00:00 2001 From: lidiazuin Date: Tue, 4 Mar 2025 11:21:10 +0100 Subject: [PATCH 93/93] Cypher manual images refresh --- modules/ROOT/images/call-procedure.svg | 27 +++ modules/ROOT/images/call_procedure.svg | 1 - modules/ROOT/images/case-graph.svg | 34 +++ modules/ROOT/images/case_graph.svg | 1 - .../images/graph-aggregating-functions.svg | 39 ++++ modules/ROOT/images/graph-limit-clause.svg | 32 +++ modules/ROOT/images/graph-list-functions.svg | 34 +++ .../images/graph-match-clause-backtick.svg | 41 ++++ .../graph-match-clause-variable-length.svg | 55 +++++ modules/ROOT/images/graph-match-clause.svg | 37 ++++ modules/ROOT/images/graph-merge-clause.svg | 37 ++++ .../ROOT/images/graph-numeric-functions.svg | 34 +++ .../images/graph-optional-match-clause.svg | 39 ++++ modules/ROOT/images/graph-order-by-clause.svg | 15 ++ .../ROOT/images/graph-predicate-functions.svg | 39 ++++ modules/ROOT/images/graph-remove-clause.svg | 22 ++ .../ROOT/images/graph-scalar-functions.svg | 34 +++ modules/ROOT/images/graph-set-clause.svg | 24 +++ .../images/graph_aggregating_functions.svg | 1 - modules/ROOT/images/graph_limit_clause.svg | 1 - modules/ROOT/images/graph_list_functions.svg | 1 - modules/ROOT/images/graph_match_clause.svg | 1 - .../images/graph_match_clause_backtick.svg | 1 - .../graph_match_clause_variable_length.svg | 1 - modules/ROOT/images/graph_merge_clause.svg | 1 - .../ROOT/images/graph_numeric_functions.svg | 1 - .../images/graph_optional_match_clause.svg | 1 - modules/ROOT/images/graph_order_by_clause.svg | 1 - .../ROOT/images/graph_predicate_functions.svg | 1 - modules/ROOT/images/graph_remove_clause.svg | 1 - .../ROOT/images/graph_scalar_functions.svg | 1 - modules/ROOT/images/graph_set_clause.svg | 1 - modules/ROOT/images/graph_skip_clause.svg | 33 ++- modules/ROOT/images/graph_union_clause.svg | 19 +- modules/ROOT/images/graph_where_clause.svg | 16 +- modules/ROOT/images/introduction-example1.svg | 54 +++++ modules/ROOT/images/introduction_example1.svg | 1 - modules/ROOT/images/introduction_example2.svg | 21 +- modules/ROOT/images/patterns_equijoins.svg | 119 ++++++++++- .../ROOT/images/patterns_equijoins_motif.svg | 26 ++- .../ROOT/images/patterns_equijoins_motif2.svg | 26 ++- .../ROOT/images/patterns_equijoins_motif3.svg | 26 ++- .../images/patterns_equijoins_solution.svg | 199 +++++++++++++++++- .../images/patterns_equijoins_solution2.svg | 101 ++++++++- modules/ROOT/images/patterns_qpp_motif1.svg | 19 +- .../images/patterns_second_shortest_paths.svg | 66 +++++- .../ROOT/images/patterns_shortest_graph.svg | 73 ++++++- .../patterns_shortest_graph_pattern1.svg | 18 +- .../patterns_shortest_graph_pattern2.svg | 18 +- modules/ROOT/images/patterns_shortest_tie.svg | 24 ++- modules/ROOT/images/patterns_shortestpath.svg | 25 ++- .../images/predicate_function_example.svg | 13 +- .../images/values_and_types_lists_graph.svg | 48 ++++- modules/ROOT/pages/clauses/call.adoc | 2 +- modules/ROOT/pages/clauses/limit.adoc | 2 +- modules/ROOT/pages/clauses/match.adoc | 2 +- modules/ROOT/pages/clauses/merge.adoc | 5 +- .../ROOT/pages/clauses/optional-match.adoc | 2 +- modules/ROOT/pages/clauses/order-by.adoc | 2 +- modules/ROOT/pages/clauses/remove.adoc | 2 +- modules/ROOT/pages/clauses/set.adoc | 3 +- modules/ROOT/pages/functions/aggregating.adoc | 2 +- modules/ROOT/pages/functions/list.adoc | 2 +- .../pages/functions/mathematical-numeric.adoc | 2 +- modules/ROOT/pages/functions/predicate.adoc | 2 +- modules/ROOT/pages/functions/scalar.adoc | 2 +- modules/ROOT/pages/queries/basic.adoc | 2 +- modules/ROOT/pages/queries/case.adoc | 2 +- 68 files changed, 1482 insertions(+), 56 deletions(-) create mode 100644 modules/ROOT/images/call-procedure.svg delete mode 100644 modules/ROOT/images/call_procedure.svg create mode 100644 modules/ROOT/images/case-graph.svg delete mode 100644 modules/ROOT/images/case_graph.svg create mode 100644 modules/ROOT/images/graph-aggregating-functions.svg create mode 100644 modules/ROOT/images/graph-limit-clause.svg create mode 100644 modules/ROOT/images/graph-list-functions.svg create mode 100644 modules/ROOT/images/graph-match-clause-backtick.svg create mode 100644 modules/ROOT/images/graph-match-clause-variable-length.svg create mode 100644 modules/ROOT/images/graph-match-clause.svg create mode 100644 modules/ROOT/images/graph-merge-clause.svg create mode 100644 modules/ROOT/images/graph-numeric-functions.svg create mode 100644 modules/ROOT/images/graph-optional-match-clause.svg create mode 100644 modules/ROOT/images/graph-order-by-clause.svg create mode 100644 modules/ROOT/images/graph-predicate-functions.svg create mode 100644 modules/ROOT/images/graph-remove-clause.svg create mode 100644 modules/ROOT/images/graph-scalar-functions.svg create mode 100644 modules/ROOT/images/graph-set-clause.svg delete mode 100644 modules/ROOT/images/graph_aggregating_functions.svg delete mode 100644 modules/ROOT/images/graph_limit_clause.svg delete mode 100644 modules/ROOT/images/graph_list_functions.svg delete mode 100644 modules/ROOT/images/graph_match_clause.svg delete mode 100644 modules/ROOT/images/graph_match_clause_backtick.svg delete mode 100644 modules/ROOT/images/graph_match_clause_variable_length.svg delete mode 100644 modules/ROOT/images/graph_merge_clause.svg delete mode 100644 modules/ROOT/images/graph_numeric_functions.svg delete mode 100644 modules/ROOT/images/graph_optional_match_clause.svg delete mode 100644 modules/ROOT/images/graph_order_by_clause.svg delete mode 100644 modules/ROOT/images/graph_predicate_functions.svg delete mode 100644 modules/ROOT/images/graph_remove_clause.svg delete mode 100644 modules/ROOT/images/graph_scalar_functions.svg delete mode 100644 modules/ROOT/images/graph_set_clause.svg create mode 100644 modules/ROOT/images/introduction-example1.svg delete mode 100644 modules/ROOT/images/introduction_example1.svg diff --git a/modules/ROOT/images/call-procedure.svg b/modules/ROOT/images/call-procedure.svg new file mode 100644 index 000000000..e244a4122 --- /dev/null +++ b/modules/ROOT/images/call-procedure.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/call_procedure.svg b/modules/ROOT/images/call_procedure.svg deleted file mode 100644 index 7cb856c93..000000000 --- a/modules/ROOT/images/call_procedure.svg +++ /dev/null @@ -1 +0,0 @@ -KNOWSKNOWSKNOWSDevelopername:'Andy'born:1991Administratorname:'David'born:1994nationality:'Swedish'Developername:'Beatrice'born:1985Administratorname:'Charlotte'born:1990 \ No newline at end of file diff --git a/modules/ROOT/images/case-graph.svg b/modules/ROOT/images/case-graph.svg new file mode 100644 index 000000000..f07b7cab8 --- /dev/null +++ b/modules/ROOT/images/case-graph.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/case_graph.svg b/modules/ROOT/images/case_graph.svg deleted file mode 100644 index 98bfc6ba1..000000000 --- a/modules/ROOT/images/case_graph.svg +++ /dev/null @@ -1 +0,0 @@ -KNOWSKNOWSKNOWSKNOWSMARRIEDPersonname:'Alice'age:38eyes:'brown'Personname:'Charlie'age:53eyes:'green'Personname:'Bob'age:25eyes:'blue'Personname:'Daniel'eyes:'brown'Personname:'Eskil'age:41eyes:'blue' diff --git a/modules/ROOT/images/graph-aggregating-functions.svg b/modules/ROOT/images/graph-aggregating-functions.svg new file mode 100644 index 000000000..241f4e533 --- /dev/null +++ b/modules/ROOT/images/graph-aggregating-functions.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/graph-limit-clause.svg b/modules/ROOT/images/graph-limit-clause.svg new file mode 100644 index 000000000..98315ea57 --- /dev/null +++ b/modules/ROOT/images/graph-limit-clause.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/graph-list-functions.svg b/modules/ROOT/images/graph-list-functions.svg new file mode 100644 index 000000000..25c412407 --- /dev/null +++ b/modules/ROOT/images/graph-list-functions.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/graph-match-clause-backtick.svg b/modules/ROOT/images/graph-match-clause-backtick.svg new file mode 100644 index 000000000..96e0956ff --- /dev/null +++ b/modules/ROOT/images/graph-match-clause-backtick.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/graph-match-clause-variable-length.svg b/modules/ROOT/images/graph-match-clause-variable-length.svg new file mode 100644 index 000000000..c9e67d089 --- /dev/null +++ b/modules/ROOT/images/graph-match-clause-variable-length.svg @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/graph-match-clause.svg b/modules/ROOT/images/graph-match-clause.svg new file mode 100644 index 000000000..605b5c7e6 --- /dev/null +++ b/modules/ROOT/images/graph-match-clause.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/graph-merge-clause.svg b/modules/ROOT/images/graph-merge-clause.svg new file mode 100644 index 000000000..52c21c583 --- /dev/null +++ b/modules/ROOT/images/graph-merge-clause.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/graph-numeric-functions.svg b/modules/ROOT/images/graph-numeric-functions.svg new file mode 100644 index 000000000..2f8442fa0 --- /dev/null +++ b/modules/ROOT/images/graph-numeric-functions.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/graph-optional-match-clause.svg b/modules/ROOT/images/graph-optional-match-clause.svg new file mode 100644 index 000000000..30d557bc7 --- /dev/null +++ b/modules/ROOT/images/graph-optional-match-clause.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/graph-order-by-clause.svg b/modules/ROOT/images/graph-order-by-clause.svg new file mode 100644 index 000000000..3817840e9 --- /dev/null +++ b/modules/ROOT/images/graph-order-by-clause.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/graph-predicate-functions.svg b/modules/ROOT/images/graph-predicate-functions.svg new file mode 100644 index 000000000..12f5b3f19 --- /dev/null +++ b/modules/ROOT/images/graph-predicate-functions.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/graph-remove-clause.svg b/modules/ROOT/images/graph-remove-clause.svg new file mode 100644 index 000000000..9d3eaaebc --- /dev/null +++ b/modules/ROOT/images/graph-remove-clause.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/graph-scalar-functions.svg b/modules/ROOT/images/graph-scalar-functions.svg new file mode 100644 index 000000000..e8e64fffe --- /dev/null +++ b/modules/ROOT/images/graph-scalar-functions.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/graph-set-clause.svg b/modules/ROOT/images/graph-set-clause.svg new file mode 100644 index 000000000..52fc7173b --- /dev/null +++ b/modules/ROOT/images/graph-set-clause.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/graph_aggregating_functions.svg b/modules/ROOT/images/graph_aggregating_functions.svg deleted file mode 100644 index a2ec6323e..000000000 --- a/modules/ROOT/images/graph_aggregating_functions.svg +++ /dev/null @@ -1 +0,0 @@ -KNOWSKNOWSKNOWSKNOWSKNOWSACTED_INPersonname:'Guy Pearce'age:55Personname:'Carrie Anne Moss'age:55Personname:'Keanu Reeves'age:58Personname:'Liam Neeson'age:70Personname:'Kathryn Bigelow'age:71Movietitle:'Speed' \ No newline at end of file diff --git a/modules/ROOT/images/graph_limit_clause.svg b/modules/ROOT/images/graph_limit_clause.svg deleted file mode 100644 index 5a21cdd1b..000000000 --- a/modules/ROOT/images/graph_limit_clause.svg +++ /dev/null @@ -1 +0,0 @@ -KNOWSKNOWSKNOWSKNOWSPersonname:'Erika'Personname:'Andy'Personname:'David'Personname:'Charlotte'Personname:'Bernard' \ No newline at end of file diff --git a/modules/ROOT/images/graph_list_functions.svg b/modules/ROOT/images/graph_list_functions.svg deleted file mode 100644 index 82ad32e38..000000000 --- a/modules/ROOT/images/graph_list_functions.svg +++ /dev/null @@ -1 +0,0 @@ -KNOWSKNOWSKNOWSKNOWSMARRIEDAdministratorname:'Charlie'age:53eyes:'Green'Administratorname:'Bob'age:25eyes:'Blue'Developername:'Alice'age:38eyes:'Brown'Administratorname:'Daniel'age:53eyes:'Brown'Designername:'Eskil'age:41eyes:'Blue'likedColors:['Pink', 'Yellow', 'Black'] \ No newline at end of file diff --git a/modules/ROOT/images/graph_match_clause.svg b/modules/ROOT/images/graph_match_clause.svg deleted file mode 100644 index 393b3fe23..000000000 --- a/modules/ROOT/images/graph_match_clause.svg +++ /dev/null @@ -1 +0,0 @@ -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/images/graph_match_clause_backtick.svg b/modules/ROOT/images/graph_match_clause_backtick.svg deleted file mode 100644 index 3c379d15c..000000000 --- a/modules/ROOT/images/graph_match_clause_backtick.svg +++ /dev/null @@ -1 +0,0 @@ -DIRECTEDACTED_INrole:'Gordon Gekko'ACTED_INrole:'Carl Fox'ACTED_INrole:'President Andrew Shepherd'ACTED_INrole:'A.J. MacInerney'ACTED_INrole:'Bud Fox'DIRECTEDFATHER_OFOLD FRIENDSPersonname:'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 diff --git a/modules/ROOT/images/graph_match_clause_variable_length.svg b/modules/ROOT/images/graph_match_clause_variable_length.svg deleted file mode 100644 index 8c79b6f6d..000000000 --- a/modules/ROOT/images/graph_match_clause_variable_length.svg +++ /dev/null @@ -1 +0,0 @@ -DIRECTEDACTED_INrole:'Gordon Gekko'ACTED_INrole:'Carl Fox'ACTED_INrole:'President Andrew Shepherd'ACTED_INrole:'A.J. MacInerney'ACTED_INrole:'Bud Fox'DIRECTEDACTED_INrole:'Bud'lead:trueACTED_INrole:'New Warden'lead:falseACTED_INrole:'Bill Peterson'lead:trueACTED_INrole:'Jake Peterson'lead:trueFATHER_OFOLD FRIENDSPersonname:'Oliver Stone'Movietitle:'Wall Street'Personname:'Michael Douglas'Personname:'Martin Sheen'Movietitle:'The American President'Personname:'Charlie Sheen'Personname:'Rob Reiner'Movietitle:'Free Money'Movietitle:'No Code of Conduct' \ No newline at end of file diff --git a/modules/ROOT/images/graph_merge_clause.svg b/modules/ROOT/images/graph_merge_clause.svg deleted file mode 100644 index ac3e96690..000000000 --- a/modules/ROOT/images/graph_merge_clause.svg +++ /dev/null @@ -1 +0,0 @@ -ACTED_INACTED_INACTED_INDIRECTEDDIRECTEDACTED_INACTED_INPersonname:'Charlie Sheen'bornIn:'New York'chauffeurName:'John Brown'Personname:'Martin Sheen'bornIn:'Ohio'chauffeurName:'Bob Brown'Movietitle:'Wall Street'Personname:'Michael Douglas'bornIn:'New Jersey'chauffeurName:'John Brown'Personname:'Oliver Stone'bornIn:'New York'chauffeurName:'Bill White'Personname:'Rob Reiner'bornIn:'New York'chauffeurName:'Ted Green'Movietitle:'The American President' \ No newline at end of file diff --git a/modules/ROOT/images/graph_numeric_functions.svg b/modules/ROOT/images/graph_numeric_functions.svg deleted file mode 100644 index 82ad32e38..000000000 --- a/modules/ROOT/images/graph_numeric_functions.svg +++ /dev/null @@ -1 +0,0 @@ -KNOWSKNOWSKNOWSKNOWSMARRIEDAdministratorname:'Charlie'age:53eyes:'Green'Administratorname:'Bob'age:25eyes:'Blue'Developername:'Alice'age:38eyes:'Brown'Administratorname:'Daniel'age:53eyes:'Brown'Designername:'Eskil'age:41eyes:'Blue'likedColors:['Pink', 'Yellow', 'Black'] \ No newline at end of file diff --git a/modules/ROOT/images/graph_optional_match_clause.svg b/modules/ROOT/images/graph_optional_match_clause.svg deleted file mode 100644 index d5373d409..000000000 --- a/modules/ROOT/images/graph_optional_match_clause.svg +++ /dev/null @@ -1 +0,0 @@ -DIRECTEDACTED_INACTED_INACTED_INACTED_INACTED_INDIRECTEDFATHER_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 diff --git a/modules/ROOT/images/graph_order_by_clause.svg b/modules/ROOT/images/graph_order_by_clause.svg deleted file mode 100644 index a42046fcc..000000000 --- a/modules/ROOT/images/graph_order_by_clause.svg +++ /dev/null @@ -1 +0,0 @@ -KNOWSKNOWSPersonname:'Charlotte'age:32length:185Personname:'Bernard'age:36Personname:'Andy'age:34length:170 \ No newline at end of file diff --git a/modules/ROOT/images/graph_predicate_functions.svg b/modules/ROOT/images/graph_predicate_functions.svg deleted file mode 100644 index 9b8a6a64d..000000000 --- a/modules/ROOT/images/graph_predicate_functions.svg +++ /dev/null @@ -1 +0,0 @@ -KNOWSKNOWSKNOWSKNOWSKNOWSACTED_INACTED_INKNOWSPersonname:'Guy Pearce'age:55nationality:'Australian'Personname:'Carrie Anne Moss'age:55nationality:'American'Personname:'Keanu Reeves'age:58nationality:'Canadian'Personname:'Liam Neeson'age:70nationality:'Northern Irish'Personname:'Kathryn Bigelow'age:71nationality:'American'Movietitle:'The Matrix'Personname:'Jessica Chastain'age:45address:'' \ No newline at end of file diff --git a/modules/ROOT/images/graph_remove_clause.svg b/modules/ROOT/images/graph_remove_clause.svg deleted file mode 100644 index 534698e78..000000000 --- a/modules/ROOT/images/graph_remove_clause.svg +++ /dev/null @@ -1 +0,0 @@ -KNOWSKNOWSSwedishname:'Andy'age:36propTestValue2:42Swedishname:'Timothy'age:25propTestValue2:42SwedishGermanname:'Peter'age:34 \ No newline at end of file diff --git a/modules/ROOT/images/graph_scalar_functions.svg b/modules/ROOT/images/graph_scalar_functions.svg deleted file mode 100644 index 82ad32e38..000000000 --- a/modules/ROOT/images/graph_scalar_functions.svg +++ /dev/null @@ -1 +0,0 @@ -KNOWSKNOWSKNOWSKNOWSMARRIEDAdministratorname:'Charlie'age:53eyes:'Green'Administratorname:'Bob'age:25eyes:'Blue'Developername:'Alice'age:38eyes:'Brown'Administratorname:'Daniel'age:53eyes:'Brown'Designername:'Eskil'age:41eyes:'Blue'likedColors:['Pink', 'Yellow', 'Black'] \ No newline at end of file diff --git a/modules/ROOT/images/graph_set_clause.svg b/modules/ROOT/images/graph_set_clause.svg deleted file mode 100644 index 61126d48d..000000000 --- a/modules/ROOT/images/graph_set_clause.svg +++ /dev/null @@ -1 +0,0 @@ -KNOWSKNOWSKNOWSname:'Stefan'Swedishname:'Andy'age:36hungry:truename:'George'name:'Peter'age:34 \ No newline at end of file diff --git a/modules/ROOT/images/graph_skip_clause.svg b/modules/ROOT/images/graph_skip_clause.svg index 5a21cdd1b..036c103b9 100644 --- a/modules/ROOT/images/graph_skip_clause.svg +++ b/modules/ROOT/images/graph_skip_clause.svg @@ -1 +1,32 @@ -KNOWSKNOWSKNOWSKNOWSPersonname:'Erika'Personname:'Andy'Personname:'David'Personname:'Charlotte'Personname:'Bernard' \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/graph_union_clause.svg b/modules/ROOT/images/graph_union_clause.svg index 17a159aec..56a3619bd 100644 --- a/modules/ROOT/images/graph_union_clause.svg +++ b/modules/ROOT/images/graph_union_clause.svg @@ -1 +1,18 @@ -ACTED_INACTED_INActorname:'Johnny Depp'Actorname:'Sarah Jessica Parker'Movietitle:'Ed woodActorDirectorname:'Ed Wood' \ No newline at end of file + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/graph_where_clause.svg b/modules/ROOT/images/graph_where_clause.svg index b307c8355..6a1b83c80 100644 --- a/modules/ROOT/images/graph_where_clause.svg +++ b/modules/ROOT/images/graph_where_clause.svg @@ -1 +1,15 @@ -KNOWSsince:2012KNOWSsince:1999PersonSwedishname:'Andy'age:36belt:'white'Personname:'Timothy'age:25Personname:'Peter'age:35email:'peter_n@example.com' \ No newline at end of file + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/introduction-example1.svg b/modules/ROOT/images/introduction-example1.svg new file mode 100644 index 000000000..9ffe1ae4e --- /dev/null +++ b/modules/ROOT/images/introduction-example1.svg @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/introduction_example1.svg b/modules/ROOT/images/introduction_example1.svg deleted file mode 100644 index 82738cb33..000000000 --- a/modules/ROOT/images/introduction_example1.svg +++ /dev/null @@ -1 +0,0 @@ -Neo4j Graph VisualizationCreated using Neo4j (http://www.neo4j.com/)ACTED_INACTED_INACTED_INACTED_INDIRECTEDACTED_INACTED_INACTED_INACTED_INACTED_INACTED_INACTED_INACTED_IN Tom Hanks Apollo 13 You've M… A LeagueO… Joe VersusVo… That Thing You Do The Da Vinci Code Cloud Atlas Cast Away The Green Mile Sleepless in Seattl The Polar Express Charlie Wilson's Wa \ No newline at end of file diff --git a/modules/ROOT/images/introduction_example2.svg b/modules/ROOT/images/introduction_example2.svg index bb0636913..fb4c99ee4 100644 --- a/modules/ROOT/images/introduction_example2.svg +++ b/modules/ROOT/images/introduction_example2.svg @@ -1 +1,20 @@ -Neo4j Graph VisualizationCreated using Neo4j (http://www.neo4j.com/)ACTED_INREVIEWEDREVIEWEDACTED_IN Keanu Reeves Tom Hanks The Repla… Jessica Thom… The Da Vinci Code \ No newline at end of file + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/patterns_equijoins.svg b/modules/ROOT/images/patterns_equijoins.svg index 0a2c996be..5729fbb6a 100644 --- a/modules/ROOT/images/patterns_equijoins.svg +++ b/modules/ROOT/images/patterns_equijoins.svg @@ -1 +1,118 @@ -CALLS_ATCALLS_ATNEXTCALLS_ATCALLS_ATCALLS_ATNEXTNEXTCALLS_ATname:Coventrydeparts:15:54name:London Eustonname:Birmingham Int'ldeparts:08:40departs:14:45arrives:09:34departs:11:33departs:12:03 \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/patterns_equijoins_motif.svg b/modules/ROOT/images/patterns_equijoins_motif.svg index b67a84c16..eeb84153c 100644 --- a/modules/ROOT/images/patterns_equijoins_motif.svg +++ b/modules/ROOT/images/patterns_equijoins_motif.svg @@ -1 +1,25 @@ -CALLS_ATNEXTCALLS_ATCALLS_ATNEXTCALLS_ATname:Coventrynname:London Eustonname:London Euston \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/patterns_equijoins_motif2.svg b/modules/ROOT/images/patterns_equijoins_motif2.svg index 145afe3f7..5c2d34a68 100644 --- a/modules/ROOT/images/patterns_equijoins_motif2.svg +++ b/modules/ROOT/images/patterns_equijoins_motif2.svg @@ -1 +1,25 @@ -CALLS_ATNEXTCALLS_ATCALLS_ATNEXTCALLS_ATname:Coventrynname:London Eustonn \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/patterns_equijoins_motif3.svg b/modules/ROOT/images/patterns_equijoins_motif3.svg index 145afe3f7..9bceaa66e 100644 --- a/modules/ROOT/images/patterns_equijoins_motif3.svg +++ b/modules/ROOT/images/patterns_equijoins_motif3.svg @@ -1 +1,25 @@ -CALLS_ATNEXTCALLS_ATCALLS_ATNEXTCALLS_ATname:Coventrynname:London Eustonn \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/patterns_equijoins_solution.svg b/modules/ROOT/images/patterns_equijoins_solution.svg index b750a9c6e..ccf057856 100644 --- a/modules/ROOT/images/patterns_equijoins_solution.svg +++ b/modules/ROOT/images/patterns_equijoins_solution.svg @@ -1,9 +1,196 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/patterns_equijoins_solution2.svg b/modules/ROOT/images/patterns_equijoins_solution2.svg index a199ab2f0..66d37acc8 100644 --- a/modules/ROOT/images/patterns_equijoins_solution2.svg +++ b/modules/ROOT/images/patterns_equijoins_solution2.svg @@ -1 +1,100 @@ - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/patterns_qpp_motif1.svg b/modules/ROOT/images/patterns_qpp_motif1.svg index 513f6d125..94e9aa930 100644 --- a/modules/ROOT/images/patterns_qpp_motif1.svg +++ b/modules/ROOT/images/patterns_qpp_motif1.svg @@ -1 +1,18 @@ -CALLS_ ATCALLS_ATNEXTNEXTNEXTCallingPointCallingPointCallingPointCallingPoint \ No newline at end of file + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/patterns_second_shortest_paths.svg b/modules/ROOT/images/patterns_second_shortest_paths.svg index 80b0db29f..8345677fc 100644 --- a/modules/ROOT/images/patterns_second_shortest_paths.svg +++ b/modules/ROOT/images/patterns_second_shortest_paths.svg @@ -1 +1,65 @@ - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/patterns_shortest_graph.svg b/modules/ROOT/images/patterns_shortest_graph.svg index 0f946e38e..a02e83e2b 100644 --- a/modules/ROOT/images/patterns_shortest_graph.svg +++ b/modules/ROOT/images/patterns_shortest_graph.svg @@ -1 +1,72 @@ -6.030.655.763.715.646.1631.147.2511.2914.7512.64.16HartleburyDroitwichSpaWorcestershireParkwayPershoreWorcesterForegateStreetWorcesterShrub HillBromsgroveCheltenhamSpaAshchurch \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/patterns_shortest_graph_pattern1.svg b/modules/ROOT/images/patterns_shortest_graph_pattern1.svg index b1f8982bd..71c7885e7 100644 --- a/modules/ROOT/images/patterns_shortest_graph_pattern1.svg +++ b/modules/ROOT/images/patterns_shortest_graph_pattern1.svg @@ -1 +1,17 @@ -DroitwichSpaWorcestershireParkwayWorcesterShrub HillBromsgroveCheltenhamSpa \ No newline at end of file + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/patterns_shortest_graph_pattern2.svg b/modules/ROOT/images/patterns_shortest_graph_pattern2.svg index f19ab73aa..c16306b5e 100644 --- a/modules/ROOT/images/patterns_shortest_graph_pattern2.svg +++ b/modules/ROOT/images/patterns_shortest_graph_pattern2.svg @@ -1 +1,17 @@ -DroitwichSpaWorcestershireParkwayWorcesterShrub HillBromsgroveCheltenhamSpa \ No newline at end of file + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/patterns_shortest_tie.svg b/modules/ROOT/images/patterns_shortest_tie.svg index 99d2f9240..d0113abad 100644 --- a/modules/ROOT/images/patterns_shortest_tie.svg +++ b/modules/ROOT/images/patterns_shortest_tie.svg @@ -1 +1,23 @@ - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/patterns_shortestpath.svg b/modules/ROOT/images/patterns_shortestpath.svg index 2bb3d06ed..d5838b616 100644 --- a/modules/ROOT/images/patterns_shortestpath.svg +++ b/modules/ROOT/images/patterns_shortestpath.svg @@ -1 +1,24 @@ -Neo4j Graph VisualizationCreated using Neo4j (http://www.neo4j.com/)CALLS_ATNEXTCALLS_ATCALLS_ATNEXTCALLS_AT Clapham High Street Elephant Cas… "11:41:0… "11:37:0… Denmark Hill "11:47:0… "11:54:0… \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/predicate_function_example.svg b/modules/ROOT/images/predicate_function_example.svg index 8b6919eb0..7c0fe2032 100644 --- a/modules/ROOT/images/predicate_function_example.svg +++ b/modules/ROOT/images/predicate_function_example.svg @@ -1 +1,12 @@ -Neo4j Graph VisualizationCreated using Neo4j (http://www.neo4j.com/)KNOWSKNOWS Keanu Reeves Guy Pearce Carrie Anne Moss \ No newline at end of file + + + + + + + + + + + + diff --git a/modules/ROOT/images/values_and_types_lists_graph.svg b/modules/ROOT/images/values_and_types_lists_graph.svg index 8c71adee4..3fde574ac 100644 --- a/modules/ROOT/images/values_and_types_lists_graph.svg +++ b/modules/ROOT/images/values_and_types_lists_graph.svg @@ -1 +1,47 @@ -ACTED_INACTED_INACTED_INACTED_INACTED_INACTED_INACTED_INMovietitle:'The Matrix Reloaded'released:2003Movietitle:'Johnny Mnemonic'released:1995Personname:'Keanu Reeves'Movietitle:'The Matrix'released:1999Movietitle:'The Matrix Revolutions'released:2003Movietitle:'The Matrix Resurrections'released:2021Movietitle:'The Replacements'released:2000Movietitle:'The Devil's Advocate'released:1997 \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/pages/clauses/call.adoc b/modules/ROOT/pages/clauses/call.adoc index c007a50f4..03763efd0 100644 --- a/modules/ROOT/pages/clauses/call.adoc +++ b/modules/ROOT/pages/clauses/call.adoc @@ -21,7 +21,7 @@ See link:{neo4j-docs-base-uri}/java-reference/current/extending-neo4j/procedures The following graph is used for the examples below: -image::call_procedure.svg[width="400",role="middle"] +image::call-procedure.svg[Example graph connecting people in the roles of developer and administrator,role=popup,width=400] To recreate it, run the following query against an empty Neo4j database: diff --git a/modules/ROOT/pages/clauses/limit.adoc b/modules/ROOT/pages/clauses/limit.adoc index 0fee1e0ce..87646000f 100644 --- a/modules/ROOT/pages/clauses/limit.adoc +++ b/modules/ROOT/pages/clauses/limit.adoc @@ -16,7 +16,7 @@ The only clause that guarantees a specific row order is xref:clauses/order-by.ad The following graph is used for the examples below: -image::graph_limit_clause.svg[width="600", role="middle"] +image::graph-limit-clause.svg[Example graph connecting Person nodes,width=500,role=popup] To recreate it, run the following query against an empty Neo4j database: diff --git a/modules/ROOT/pages/clauses/match.adoc b/modules/ROOT/pages/clauses/match.adoc index 3dffc1a0c..4ec38cca8 100644 --- a/modules/ROOT/pages/clauses/match.adoc +++ b/modules/ROOT/pages/clauses/match.adoc @@ -11,7 +11,7 @@ The `MATCH` clause can specify the nodes, relationships, and properties in a pat The following graph is used for the examples below: -image::graph_match_clause.svg[width="500",role="middle"] +image::graph-match-clause.svg[Example graph connecting Person and Movie nodes,width=500,role=popup] To recreate the graph, run the following query against an empty Neo4j database: diff --git a/modules/ROOT/pages/clauses/merge.adoc b/modules/ROOT/pages/clauses/merge.adoc index 1110bd445..cb7ce3a9c 100644 --- a/modules/ROOT/pages/clauses/merge.adoc +++ b/modules/ROOT/pages/clauses/merge.adoc @@ -39,7 +39,10 @@ These allow a query to express additional changes to the properties of a node or The following graph is used for the examples below: -image::graph_merge_clause.svg[] +image::graph-merge-clause.svg[Example graph connecting Person and Movie nodes,role=popup,width=600] +// If we use the width of 500px here, the image gets too small. +// Either we stick to the same size and count on people clicking on the image for the popup or use exceptions when needed. +// Another option is allowing the image to expand to the full width of the content box. To recreate the graph, run the following query in an empty Neo4j database: diff --git a/modules/ROOT/pages/clauses/optional-match.adoc b/modules/ROOT/pages/clauses/optional-match.adoc index 68289328a..616f8e578 100644 --- a/modules/ROOT/pages/clauses/optional-match.adoc +++ b/modules/ROOT/pages/clauses/optional-match.adoc @@ -23,7 +23,7 @@ To understand the patterns used in the `OPTIONAL MATCH` clause, read xref::patte The following graph is used for the examples below: -image::graph_optional_match_clause.svg[width="600",role="middle"] +image::graph-optional-match-clause.svg[Example graph connecting Person and Movie nodes,width=500,role=popup] To recreate the graph, run the following query in an empty Neo4j database: diff --git a/modules/ROOT/pages/clauses/order-by.adoc b/modules/ROOT/pages/clauses/order-by.adoc index 6136a5b63..2ea2f629b 100644 --- a/modules/ROOT/pages/clauses/order-by.adoc +++ b/modules/ROOT/pages/clauses/order-by.adoc @@ -20,7 +20,7 @@ Unless `ORDER BY` is used, Neo4j does not guarantee the row order of a query res The following graph is used for the examples below: -image::graph_order_by_clause.svg[width="600", role="middle"] +image::graph-order-by-clause.svg[Example graph connecting Person nodes,width=500,role=popup] To recreate it, run the following query against an empty Neo4j database: diff --git a/modules/ROOT/pages/clauses/remove.adoc b/modules/ROOT/pages/clauses/remove.adoc index ec5a887d6..57d770698 100644 --- a/modules/ROOT/pages/clauses/remove.adoc +++ b/modules/ROOT/pages/clauses/remove.adoc @@ -20,7 +20,7 @@ The query statistics will tell you if something needed to be done or not. The following graph is used for the examples below: -image::graph_remove_clause.svg[width="600", role="middle"] +image::graph-remove-clause.svg[Example graph connecting people after their nationality as nodes,width=500,role=popup] To recreate it, run the following query against an empty Neo4j database: diff --git a/modules/ROOT/pages/clauses/set.adoc b/modules/ROOT/pages/clauses/set.adoc index d90a891d1..92f489482 100644 --- a/modules/ROOT/pages/clauses/set.adoc +++ b/modules/ROOT/pages/clauses/set.adoc @@ -17,7 +17,8 @@ The query statistics will state whether any updates actually took place. The following graph is used for the examples below: -image::graph_set_clause.svg[[width="500", role="middle"] +image::graph-set-clause.svg[Example graph connecting people through know relationships,width=300,role=popup] +// Another exception here, a graph that is small but "wide" and so might look better with a smaller width so it doesn't occupy too much space. To recreate it, run the following query against an empty Neo4j database: diff --git a/modules/ROOT/pages/functions/aggregating.adoc b/modules/ROOT/pages/functions/aggregating.adoc index 9e57a6d1d..19c0f3351 100644 --- a/modules/ROOT/pages/functions/aggregating.adoc +++ b/modules/ROOT/pages/functions/aggregating.adoc @@ -17,7 +17,7 @@ To learn more about how Cypher handles aggregations performed on zero rows, refe The following graph is used for the examples below: -image::graph_aggregating_functions.svg[role="middle", width="700"] +image::graph-aggregating-functions.svg[Graph example connecting Person and Movie nodes,role=popup,width=500] To recreate the graph, run the following query against an empty Neo4j database: diff --git a/modules/ROOT/pages/functions/list.adoc b/modules/ROOT/pages/functions/list.adoc index 7dc9e3fd7..ffaa0ddd0 100644 --- a/modules/ROOT/pages/functions/list.adoc +++ b/modules/ROOT/pages/functions/list.adoc @@ -13,7 +13,7 @@ Further details and examples of lists may be found in xref::values-and-types/lis The following graph is used for the examples below: -image::graph_list_functions.svg[role="middle", width="700"] +image::graph-list-functions.svg[Example graph connecting people after their roles as administrator, designer, and developer,role=popup,width=500] To recreate the graph, run the following query against an empty Neo4j database: diff --git a/modules/ROOT/pages/functions/mathematical-numeric.adoc b/modules/ROOT/pages/functions/mathematical-numeric.adoc index fb0ecabe7..30255bff1 100644 --- a/modules/ROOT/pages/functions/mathematical-numeric.adoc +++ b/modules/ROOT/pages/functions/mathematical-numeric.adoc @@ -12,7 +12,7 @@ See also xref::syntax/operators.adoc#query-operators-mathematical[Mathematical o The following graph is used for the examples below: -image::graph_numeric_functions.svg[role="middle", width="700"] +image::graph-numeric-functions.svg[Example graph connecting people people after their roles as administrator, designer, and developer,role=popup,width=500] To recreate the graph, run the following query against an empty Neo4j database: diff --git a/modules/ROOT/pages/functions/predicate.adoc b/modules/ROOT/pages/functions/predicate.adoc index 08e39bc8e..c294097f6 100644 --- a/modules/ROOT/pages/functions/predicate.adoc +++ b/modules/ROOT/pages/functions/predicate.adoc @@ -13,7 +13,7 @@ They are most commonly used to filter out paths in the `WHERE` part of a query. The following graph is used for the examples below: -image::graph_predicate_functions.svg[[width="600",role="middle"] +image::graph-predicate-functions.svg[Graph example connecting Person nodes among themselves and with a Movie node,width=500,role=popup] To recreate it, run the following query against an empty Neo4j database: diff --git a/modules/ROOT/pages/functions/scalar.adoc b/modules/ROOT/pages/functions/scalar.adoc index 6ec56dd22..675ef5412 100644 --- a/modules/ROOT/pages/functions/scalar.adoc +++ b/modules/ROOT/pages/functions/scalar.adoc @@ -11,7 +11,7 @@ Scalar functions return a single value. The following graph is used for the examples below: -image::graph_scalar_functions.svg[role="middle", width="700"] +image::graph-scalar-functions.svg[Example graph connecting people people after their roles as administrator, designer, and developer,role=popup,width=500] To recreate the graph, run the following query against an empty Neo4j database: diff --git a/modules/ROOT/pages/queries/basic.adoc b/modules/ROOT/pages/queries/basic.adoc index cb6d57af4..6876d75ba 100644 --- a/modules/ROOT/pages/queries/basic.adoc +++ b/modules/ROOT/pages/queries/basic.adoc @@ -678,7 +678,7 @@ RETURN type(r) AS type, m.title AS movie The result shows that he has 13 outgoing relationships connected to 12 different `Movie` nodes (12 have the `ACTED_IN` type and one has the `DIRECTED` type). -image::introduction_example1.svg[width="500",role="middle"] +image::introduction-example1.svg[Example graph connecting Tom Hanks to multiple Movie nodes,width=500,role=popup] .Result [role="queryresult",options="header,footer",cols="2*