diff --git a/antora.yml b/antora.yml index 986c4d003..3efd4c638 100644 --- a/antora.yml +++ b/antora.yml @@ -7,5 +7,5 @@ nav: asciidoc: attributes: neo4j-version: '5' - neo4j-version-minor: '5.22' - neo4j-version-exact: '5.22.0' + neo4j-version-minor: '5.23' + neo4j-version-exact: '5.23.0' diff --git a/modules/ROOT/images/call_subquery_graph.svg b/modules/ROOT/images/call_subquery_graph.svg index 10e7f2ae6..932cf79da 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/appendix/gql-conformance/index.adoc b/modules/ROOT/pages/appendix/gql-conformance/index.adoc index 99765b04a..5b58aafb1 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*: 5 July 2024 + -*Neo4j version*: 5.21 +*Last updated*: 9 August 2024 + +*Neo4j version*: 5.23 GQL is the new link:https://www.iso.org/home.html[ISO] International Standard query language for graph databases. @@ -42,5 +42,5 @@ Neo4j 5.14 added support for JavaSE 21 and version 15 of the Unicode Standard. For more information, see xref:syntax/parsing.adoc##_using_unicodes_in_cypher[Parsing -> Using Unicode in Cypher]. * Cypher supports the following mandatory GQL property types: `BOOLEAN` (`BOOL`), `FLOAT` footnote:[The `FLOAT` type in Cypher always represents a 64-bit double-precision floating point number.], `INTEGER` (`SIGNED INTEGER`, or `INT`)footnote:[The `INTEGER` type in Cypher always represents a 64-bit `INTEGER`.], and `STRING` (`VARCHAR`). + -Cypher also supports the following optional GQL property types: `DATE`, `DURATION`, `LIST` (`ARRAY`, `INNER_TYPE LIST`, or `INNER_TYPE ARRAY`)footnote:[The `INNER_TYPE` cannot be a `LIST` type.], `LOCAL DATETIME` (`TIMESTAMP WITHOUT TIMEZONE`), `LOCAL TIME` (`TIME WITHOUT TIME ZONE`), `POINT`, `ZONED DATETIME` (`TIME WITH TIMEZONE`), and `ZONED TIME` (`TIMESTAMP WITH TIMEZONE`). +Cypher also supports the following optional GQL property types: `DATE`, `DURATION`, `LIST` (`ARRAY`, `INNER_TYPE LIST`, or `INNER_TYPE ARRAY`)footnote:[The `INNER_TYPE` cannot be a `LIST` type.], `LOCAL DATETIME` (`TIMESTAMP WITHOUT TIME ZONE`), `LOCAL TIME` (`TIME WITHOUT TIME ZONE`), `POINT`, `ZONED DATETIME` (`TIME WITH TIME ZONE`), and `ZONED TIME` (`TIMESTAMP WITH TIME ZONE`). For more information, see xref:values-and-types/property-structural-constructed.adoc#_property_types[Values and types -> property types]. diff --git a/modules/ROOT/pages/appendix/gql-conformance/supported-mandatory.adoc b/modules/ROOT/pages/appendix/gql-conformance/supported-mandatory.adoc index 42cd41056..478988f85 100644 --- a/modules/ROOT/pages/appendix/gql-conformance/supported-mandatory.adoc +++ b/modules/ROOT/pages/appendix/gql-conformance/supported-mandatory.adoc @@ -71,23 +71,6 @@ The only way to guarantee row order in Neo4j is to use xref:clauses/order-by.ado | xref:clauses/return.adoc[`RETURN`] | -| 15.1 -| and -| xref:clauses/call.adoc[`CALL` procedures], xref:subqueries/call-subquery.adoc[`CALL` subqueries]. -| GQL defines an `OPTIONAL CALL` statement, enabling optional procedure and subquery calling. -This is not available in Cypher. - -| 15.2 -| -| xref:subqueries/call-subquery.adoc[`CALL` subqueries]. -| GQL either imports variables implicitly, or explicitly using a variable scope clause. -In Cypher, `CALL` subqueries require an explicit importing `WITH` clause. - -| 15.3 -| -| xref:clauses/call.adoc[`CALL` procedure] -| - | 16.2 | | xref:clauses/limit.adoc[`LIMIT`] diff --git a/modules/ROOT/pages/appendix/gql-conformance/supported-optional.adoc b/modules/ROOT/pages/appendix/gql-conformance/supported-optional.adoc index 47ba67e7f..b71364b84 100644 --- a/modules/ROOT/pages/appendix/gql-conformance/supported-optional.adoc +++ b/modules/ROOT/pages/appendix/gql-conformance/supported-optional.adoc @@ -129,6 +129,21 @@ In Cypher, `trim()` removes any whitespace character. | | +| GP01 +| Inline procedure +| xref:subqueries/call-subquery.adoc[`CALL` subqueries] +| + +| GP03 +| Inline procedure with explicit nested variable scope +| xref:subqueries/call-subquery.adoc#variable-scope-clause[`CALL` subqueries -> Variable scope clause] +| + +| GP04 +| Named procedure calls +| xref:clauses/call.adoc[`CALL` procedure] +| + | GQ01 | `USE` graph clause | xref:clauses/use.adoc[`USE`] diff --git a/modules/ROOT/pages/clauses/load-csv.adoc b/modules/ROOT/pages/clauses/load-csv.adoc index ea1998c5e..fd19b94e7 100644 --- a/modules/ROOT/pages/clauses/load-csv.adoc +++ b/modules/ROOT/pages/clauses/load-csv.adoc @@ -90,6 +90,15 @@ You can import data from a CSV file hosted on a remote path. `LOAD CSV` supports accessing CSV files via HTTPS, HTTP, and FTP (with or without credentials). It also follows redirects, except those changing the protocol (for security reasons). +[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. +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`]. +==== + + .Import artists name and year information from a remote file via HTTPS ==== @@ -599,12 +608,15 @@ person_tmdbId,bio,born,bornIn,died,person_imdbId,name,person_poster,person_url ... ---- +[NOTE] +The below query uses a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause] (introduced in Neo4j 5.23) to import variables into the `CALL` subquery. +If you are using an older version of Neo4j, use an xref:subqueries/call-subquery.adoc#importing-with[importing `WITH` clause] instead. + .Query [source, cypher] ---- LOAD CSV WITH HEADERS FROM 'https://data.neo4j.com/importing-cypher/persons.csv' AS row -CALL { - WITH row +CALL (row) { MERGE (p:Person {tmdbId: row.person_tmdbId}) SET p.name = row.name, p.born = row.born } IN TRANSACTIONS OF 200 ROWS diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index 02e11cc55..cb7621548 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -16,6 +16,102 @@ 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.23]] +== Neo4j 5.23 + +=== Deprecated features + +[cols="2", options="header"] +|=== +| Feature +| Details + +a| +label:functionality[] +label:deprecated[] +[source, cypher, role="noheader"] +---- +UNWIND [0, 1, 2] AS x +CALL { + WITH x + RETURN x * 10 AS y +} +RETURN x, y +---- + +| Using the xref:subqueries/call-subquery.adoc#importing-with[`WITH` clause to import variables] to `CALL` subqueries is deprecated, and replaced with a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause]. +It is also deprecated to use naked subqueries without a variable scope clause. +|=== + +=== Updated features + + +[cols="2", options="header"] +|=== +| Feature +| Details + +a| +label:functionality[] +label:updated[] +[source, cypher, role="noheader"] +---- +RETURN datetime.statement() IS :: TIMESTAMP WITH TIME ZONE +---- +a| +Introduced new GQL conformant aliases to duration types: `TIMESTAMP WITHOUT TIME ZONE` (alias to `LOCAL DATETIME`), `TIME WITHOUT TIME ZONE` (alias to `LOCAL TIME`), `TIMESTAMP WITH TIME ZONE` (alias to `ZONED DATETIME`), and `TIME WITH TIME ZONE` (alias to `ZONED TIME`). + +See xref::values-and-types/property-structural-constructed.adoc#types-synonyms[types and their synonyms] for more. +|=== + +=== New features + +[cols="2", options="header"] +|=== +| Feature +| Details + +a| +label:functionality[] +label:new[] +[source, cypher, role="noheader"] +---- +UNWIND [0, 1, 2] AS x +CALL (x) { + RETURN x * 10 AS y +} +RETURN x, y +---- + +| Introduced a new xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause] to import variables in `CALL` subqueries. + +a| +label:functionality[] +label:new[] +[source, cypher, role=noheader] +---- +CREATE VECTOR INDEX moviePlots IF NOT EXISTS +FOR (m:Movie) +ON m.embedding +OPTIONS {indexConfig: { +`vector.quantization.enabled`: true +`vector.hnsw.m`: 16, +`vector.hnsw.ef_construction`: 100, +}} +---- + +a| Introduced the following xref:indexes/semantic-indexes/vector-indexes.adoc#configuration-settings[configuration settings] for vector indexes: + +* `vector.quantization.enabled`: allows for enabling quantization, which can accelerate search performance but can also slightly decrease accuracy. + +* `vector.hnsw.m`: controls the maximum number of connections each node has in the index's internal graph. + +* `vector.hnsw.ef_construction`: sets the number of nearest neighbors tracked during the insertion of vectors into the index's internal graph. + +Additionally, as of Neo4j 5.23, it is no longer mandatory to configure the settings `vector.dimensions` and `vector.similarity_function` when creating a vector index. + +|=== + [[cypher-deprecations-additions-removals-5.21]] == Neo4j 5.21 diff --git a/modules/ROOT/pages/genai-integrations.adoc b/modules/ROOT/pages/genai-integrations.adoc index eba7d181b..5168f0d01 100644 --- a/modules/ROOT/pages/genai-integrations.adoc +++ b/modules/ROOT/pages/genai-integrations.adoc @@ -1,11 +1,12 @@ :description: Information about Neo4j's GenAI integrations. -:page-role: enterprise-edition new-5.17 +:page-role: new-5.17 :test-setup-dump: https://github.com/neo4j-graph-examples/recommendations/raw/main/data/recommendations-50.dump include::https://raw.githubusercontent.com/neo4j-graphacademy/courses/main/asciidoc/courses/llm-fundamentals/ad.adoc[] [[genai-integrations]] = GenAI integrations + Neo4j's xref:indexes/semantic-indexes/vector-indexes.adoc[] and xref:functions/vector.adoc[] allow you to calculate the similarity between node and relationship properties in a graph. A prerequisite for using these features is that vector embeddings have been set as properties of these entities. The GenAI plugin enables the creation of such embeddings using GenAI providers. @@ -20,10 +21,13 @@ For a hands-on guide on how to use the GenAI plugin, see link:https://neo4j.com/ The GenAI plugin is enabled by default in Neo4j Aura. -For self-managed instances, the plugin is only available on Enterprise Edition and needs to be installed. +The plugin needs to be installed on self-managed instances. This is done by moving the `neo4j-genai.jar` file from `/products` to `/plugins` in the Neo4j home directory, or, if you are using Docker, by starting the Docker container with the extra parameter `--env NEO4J_PLUGINS='["genai"]'`. For more information, see link:{neo4j-docs-base-uri}/operations-manual/{page-version}/configuration/plugins/[Operations Manual -> Configure plugins]. +[NOTE] +Prior to Neo4j 5.23, the GenAI plugin was only available on Neo4j Enterprise Edition. + [[example-graph]] == Example graph @@ -180,9 +184,8 @@ WITH collect(m) AS moviesList // <1> count(*) AS total, 100 AS batchSize // <2> UNWIND range(0, total, batchSize) AS batchStart // <3> -CALL { // <4> - WITH moviesList, batchStart, batchSize - WITH moviesList, batchStart, [movie IN moviesList[batchStart .. batchStart + batchSize] | movie.title || ': ' || movie.plot] AS resources // <5> +CALL (moviesList, batchStart, batchSize) { // <4> + WITH [movie IN moviesList[batchStart .. batchStart + batchSize] | movie.title || ': ' || movie.plot] AS resources // <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> @@ -194,6 +197,8 @@ Because vector embeddings can be very large, a larger batch size may require sig Too large a batch size may also exceed the provider's threshold. <3> Process `Movie` nodes in increments of `batchSize`. <4> A xref:subqueries/subqueries-in-transactions.adoc[`CALL` subquery] executes a separate transaction for each batch. +Note that this `CALL` subquery uses a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause] (introduced in Neo4j 5.23) to import variables. +If you are using an older version of Neo4j, use an xref:subqueries/call-subquery.adoc#importing-with[importing `WITH` clause] instead. <5> `resources` is a list of strings, each being the concatenation of `title` and `plot` of one movie. <6> The procedure sets `vector` as value for the property named `embedding` for the node at position `batchStart + index` in the `moviesList`. <7> Set to `1` the amount of batches to be processed at once. diff --git a/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc b/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc index c8bedbc44..13c8334b2 100644 --- a/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc +++ b/modules/ROOT/pages/indexes/semantic-indexes/vector-indexes.adoc @@ -92,7 +92,7 @@ Creating indexes requires link:{neo4j-docs-base-uri}/operations-manual/{page-ver CREATE VECTOR INDEX moviePlots IF NOT EXISTS // <1> FOR (m:Movie) ON m.embedding -OPTIONS {indexConfig: { +OPTIONS { indexConfig: { `vector.dimensions`: 1536, `vector.similarity_function`: 'cosine' }} // <2> @@ -103,8 +103,10 @@ This means that its default behavior is to throw an error if an attempt is made With `IF NOT EXISTS`, no error is thrown and nothing happens should an index with the same name, schema or both already exist. It may still throw an error should a constraint with the same name exist. As of Neo4j 5.17, an informational notification is returned when nothing happens, showing the existing index which blocks the creation. -<2> The `OPTIONS` map is mandatory since a vector index cannot be created without setting the vector dimensions and similarity function. -In this example, the vector dimension is set to `1536` and the vector similarity function is `cosine`, which is generally the preferred similarity function for text embeddings. +<2> Prior to Neo4j 5.23, the `OPTIONS` map was mandatory since a vector index could not be created without setting the vector dimensions and similarity function. +Since Neo4j 5.23, both can be omitted. +To read more about the available configuration settings, see xref:indexes/semantic-indexes/vector-indexes.adoc#configuration-settings[]. +In this example, the vector dimension is explicitly set to `1536` and the vector similarity function to `'cosine'`, which is generally the preferred similarity function for text embeddings. To read more about the available similarity functions, see xref:indexes/semantic-indexes/vector-indexes.adoc#similarity-functions[]. [NOTE] @@ -117,12 +119,78 @@ You can also create a vector index for relationships with a particular type on a ---- CREATE VECTOR INDEX name IF NOT EXISTS FOR ()-[r:REL_TYPE]-() ON (r.embedding) -OPTIONS {indexConfig: { +OPTIONS { indexConfig: { `vector.dimensions`: $dimension, `vector.similarity_function`: $similarityFunction }} ---- +[[configuration-settings]] +=== Configuration settings + +For more information about the values accepted by different index providers, see xref:indexes/semantic-indexes/vector-indexes.adoc#vector-index-providers[]. + +[[config-vector.dimensions]] +==== `vector.dimensions` +The dimensions of the vectors to be indexed. +For more information, see xref:indexes/semantic-indexes/vector-indexes.adoc#embeddings[]. +This setting can be omitted, and any `LIST` can be indexed and queried, separated by their dimensions, _though only vectors of the same dimension can be compared._ +Setting this value adds additional checks that ensure only vectors with the configured dimensions are indexed, and querying the index with a vector of a different dimensions returns an error. + +[NOTE] +It is recommended to provide dimensions when creating a vector index. + +Accepted values::: `INTEGER` between `1` and `4096` inclusively. +Default value::: None. +The setting was mandatory prior to Neo4j 5.23. + +[[config-vector.similarity_function]] +==== `vector.similarity_function` + +The name of the similarity function used to assess the similarity of two vectors. +To read more about the available similarity functions, see xref:indexes/semantic-indexes/vector-indexes.adoc#similarity-functions[]. + +Accepted values::: `STRING`: `'cosine'`, `'euclidean'`. +Default value::: `'cosine'`. The setting was mandatory prior to Neo4j 5.23. + +[role=label--new-5.23] +[[config-vector.quantization.enabled]] +==== `vector.quantization.enabled` + +Quantization is a technique to reduce the size of vector representations. +Enabling quantization can accelerate search performance but can slightly decrease accuracy. +It is recommended to enable quantization on machines with limited memory. +Vector indexes created prior to Neo4j 5.23 have this setting effectively set to `false`. + +Accepted values::: `BOOLEAN`: `true`, `false`. +Default value::: `true` + +[discrete] +[[config-advanced]] +=== Advanced configuration settings + +[role=label--new-5.23] +[[config-vector.hsnw.m]] +==== `vector.hnsw.m` + +The `M` parameter controls the maximum number of connections each node has in the HNSW (Hierarchical Navigable Small Worlds) graph. +Increasing this value may lead to greater accuracy at the expense of increased index population and update times, especially for vectors with high dimensionality. +Vector indexes created prior to Neo4j 5.23 have this setting effectively set to `16`. + +Accepted values::: `INTEGER` between `1` and `512` inclusively. +Default value::: `16` + +[role=label--new-5.23] +[[config-vector.hsnw.ef_construction]] +==== `vector.hnsw.ef_construction` + +The number of nearest neighbors tracked during the insertion of vectors into the HNSW graph. +Increasing this value increases the quality of the index, and may lead to greater accuracy (with diminishing returns) at the expense of increased index population and update times. +Vector indexes created prior to Neo4j 5.23 have this setting effectively set to `100`. + +Accepted values::: `INTEGER` between `1` and `3200` inclusively. +Default value::: `100` + [[query-vector-index]] == Query vector indexes @@ -159,8 +227,8 @@ RETURN movie.title AS title, movie.plot AS plot, score | "Godfather, The" | "The aging patriarch of an organized crime dynasty transfers control of his clandestine empire to his reluctant son." | 1.0 | | "Godfather: Part III, The" | "In the midst of trying to legitimize his business dealings in New York and Italy in 1979, aging Mafia don Michael Corleone seeks to avow for his sins while taking a young protégé under his wing." | 0.9648237228393555 | | "Godfather: Part II, The" | "The early life and career of Vito Corleone in 1920s New York is portrayed while his son, Michael, expands and tightens his grip on his crime syndicate stretching from Lake Tahoe, Nevada to pre-revolution 1958 Cuba." | 0.9547788500785828 | +| "Goodfellas" | "Henry Hill and his friends work their way up through the mob hierarchy." | 0.9300689697265625 | | "Scarface" | "An ambitious and near insanely violent gangster climbs the ladder of success in the mob, but his weaknesses prove to be his downfall." | 0.9367183446884155 | -| "Jane Austen's Mafia!" | "Takeoff on the Godfather with the son of a mafia king taking over for his dying father" | 0.9366795420646667 | +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ---- @@ -238,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: {`vector.dimensions`: 1536, `vector.similarity_function`: "COSINE"}, indexProvider: "vector-2.0"} | "" | "CREATE VECTOR INDEX `moviePlots` FOR (n:`Movie`) ON (n.`embedding`) OPTIONS {indexConfig: {`vector.dimensions`: 1536,`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: {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'}" | ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ---- To return only specific details, specify the desired column name(s) after the `YIELD` clause. @@ -367,7 +435,7 @@ Cosine similarity is used when the _angle_ between the vectors is what determine A valid vector for a cosine vector index is when: -* All vector components can be represented finitely in IEEE 754 double precision. +* All vector components can be represented finitely in IEEE 754 double precision.footnote:[link:https://ieeexplore.ieee.org/document/8766229[IEEE Standard for Floating-Point Arithmetic]] * Its {l2-norm} is non-zero and can be represented finitely in IEEE 754 double precision. * The ratio of each vector component with its {l2-norm} can be represented finitely in IEEE 754 single precision. @@ -386,7 +454,7 @@ In the above equation the trigonometric cosine is given by the scalar product of ==== Euclidean similarity is useful when the _distance_ between the vectors is what determines how similar two vectors are. -A valid vector for a Euclidean vector index is when all vector components can be represented finitely in IEEE 754 single precision.footnote:[link:https://ieeexplore.ieee.org/document/8766229[IEEE Standard for Floating-Point Arithmetic]] +A valid vector for a Euclidean vector index is when all vector components can be represented finitely in IEEE 754 single precision. Euclidean interprets the vectors in Cartesian coordinates. The measure is related to the Euclidean distance, i.e., how far two points are from one another. @@ -449,8 +517,6 @@ The requested _k_ nearest neighbors may not be the exact _k_ nearest, but close * Only one vector index can be over a schema. For example, you cannot have one xref:indexes/semantic-indexes/vector-indexes.adoc#similarity-functions[Euclidean] and one xref:indexes/semantic-indexes/vector-indexes.adoc#similarity-functions[cosine] vector index on the same label-property key pair. -* No provided settings or options for tuning the index. - * Changes made within the same transaction are not visible to the index. ==== @@ -463,6 +529,15 @@ 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. +In Neo4j 5.20, the error was clarified. +[TIP] +-- +Using the `CREATE VECTOR INDEX` command instead avoids this issue. +If the use of the procedure is unavoidable, performing any other write operation to the database on the newer binary before using the procedure will avoid the issue +-- +| + | Procedure signatures from `SHOW PROCEDURES` will render the vector arguments with a type of `ANY` rather than the semantically correct type of `LIST`. [NOTE] -- @@ -470,11 +545,13 @@ The types are still enforced as `LIST`. -- | +| No provided settings or options for tuning the index. +| Neo4j 5.23 + | Only node vector indexes are supported. | Neo4j 5.18 | Vector indexes cannot be assigned autogenerated names. - | Neo4j 5.15 | There is no Cypher syntax for creating a vector index. diff --git a/modules/ROOT/pages/indexes/syntax.adoc b/modules/ROOT/pages/indexes/syntax.adoc index 1eb27c3c8..baede5cba 100644 --- a/modules/ROOT/pages/indexes/syntax.adoc +++ b/modules/ROOT/pages/indexes/syntax.adoc @@ -207,17 +207,18 @@ ON (r.propertyName) [OPTIONS “{“ option: value[, …] “}”] ---- -Vector indexes have two settings, `vector.dimensions` and `vector.similarity_function`, which have no default values. -As of Neo4j 5.18, they have two index providers available, `vector-2.0` (default) and `vector-1.0`. +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]. -The `OPTIONS` clause is mandatory when creating a vector index, because it is necessary to configure the `vector.dimensions` and `vector.similarity_function` settings: +For a full list of all vector index settings, see xref:indexes/semantic-indexes/vector-indexes.adoc#configuration-settings[Vector index configuration settings]. +Note that the `OPTIONS` clause was mandatory prior to Neo4j 5.23 because it was necessary to configure the `vector.dimensions` and `vector.similarity_function` settings when creating a vector index. [source,syntax] ---- OPTIONS { indexConfig: { `vector.dimensions`: $dimension, - `vector.similarity_function`: $similarityFunction + `vector.similarity_function`: $similarityFunction } } ---- @@ -225,7 +226,7 @@ OPTIONS { [NOTE] It is not possible to create composite vector indexes on multiple properties. -For more information, see xref:indexes/semantic-indexes/vector-indexes.adoc#indexes-vector-create[Vector indexes - Create and configure vector indexes]. +For more information, see xref:indexes/semantic-indexes/vector-indexes.adoc#create-vector-index[Vector indexes - Create and configure vector indexes]. [[list-index]] == SHOW INDEX diff --git a/modules/ROOT/pages/patterns/shortest-paths.adoc b/modules/ROOT/pages/patterns/shortest-paths.adoc index 2e9779c75..01e61f3ba 100644 --- a/modules/ROOT/pages/patterns/shortest-paths.adoc +++ b/modules/ROOT/pages/patterns/shortest-paths.adoc @@ -552,6 +552,10 @@ To have the planner choose the `StatefulShortestPath(Into)` instead, rewrite the For example, in the below query, using a `CALL` subquery ensures that the planner binds `a` and `b` to exactly one `Station` node respectively for each executed row, and this forces it to use `StatefulShortestPath(Into)` for each invocation of the `CALL` subquery, since a precondition of using this operator is that both boundary nodes match exactly one node each. +[NOTE] +The below query uses a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause] (introduced in Neo4j 5.23) to import variables into the `CALL` subquery. +If you are using an older version of Neo4j, use an xref:subqueries/call-subquery.adoc#importing-with[importing `WITH` clause] instead. + .Query rewritten to use `StatefulShortestPath(Into)` [source,cypher] ---- @@ -559,8 +563,7 @@ PROFILE MATCH (a:Station {name: "Worcestershire Parkway"}), (b:Station) -CALL { - WITH a, b +CALL (a, b) { MATCH p = SHORTEST 1 (a)(()-[]-()-[]-()){1,}(b) RETURN p 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 38759c6f5..d6c0f97d8 100644 --- a/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc +++ b/modules/ROOT/pages/planning-and-tuning/operators/operators-detail.adoc @@ -2811,13 +2811,16 @@ Total database accesses: 166, total allocated memory: 976 .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 LOAD CSV FROM 'https://neo4j.com/docs/cypher-refcard/3.3/csv/artists.csv' AS line -CALL { - WITH line +CALL (line) { CREATE (a: Artist {name: line[0]}) RETURN a } IN TRANSACTIONS OF 100 ROWS @@ -3512,13 +3515,16 @@ This restricts the xref:planning-and-tuning/runtimes/index.adoc[Cypher runtime] .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. + .Query [source, cypher] ---- PROFILE MATCH (s:Person {name: 'me'}) -CALL { - WITH s +CALL (s) { SET s.seen = coalesce(s.seen + 1,1) RETURN s.seen AS result } @@ -4787,13 +4793,16 @@ Total database accesses: 9, total allocated memory: 64 .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 { - WITH line +CALL (line) { CREATE (a: Artist {name: line[0]}) } IN TRANSACTIONS OF 100 ROWS ---- @@ -4839,13 +4848,16 @@ Batch size 128 .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 { - WITH line +CALL (line) { CREATE (a: Artist {name: line[0]}) } ---- diff --git a/modules/ROOT/pages/subqueries/call-subquery.adoc b/modules/ROOT/pages/subqueries/call-subquery.adoc index 636d47eea..84624ee19 100644 --- a/modules/ROOT/pages/subqueries/call-subquery.adoc +++ b/modules/ROOT/pages/subqueries/call-subquery.adoc @@ -1,19 +1,17 @@ = CALL subqueries -:description: This page describes how to use the CALL subquery with Cypher. +:description: This page describes how to use Cypher's `CALL` subquery. -The `CALL` clause can be used to invoke a subquery. -Unlike other subqueries in Cypher, it can be used to perform changes to the database (e.g. xref:clauses/create.adoc[] new nodes), and it requires an importing xref:clauses/with.adoc[] clause. +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). [NOTE] -==== The `CALL` clause is also used for calling procedures. -For descriptions of the `CALL` clause in this context, refer to xref::clauses/call.adoc[`CALL` procedure]. -==== +For descriptions of the `CALL` clause in this context, refer to the xref::clauses/call.adoc[`CALL` procedure]. [[call-example-graph]] == Example graph -The following graph is used for the examples below: +A graph with the following schema is used for the examples below: image::call_subquery_graph.svg[] @@ -21,33 +19,45 @@ To recreate the graph, run the following query in an empty Neo4j database: [source, cypher, role=test-setup] ---- -CREATE - (a:Person:Child {name: 'Alice', age: 20}), - (b:Person {name: 'Bob', age: 27}), - (c:Person:Parent {name: 'Charlie', age: 65}), - (d:Person {name: 'Dora', age: 30}) - CREATE (a)-[:FRIEND_OF]->(b) - CREATE (a)-[:CHILD_OF]->(c) - CREATE (a)-[:OWES {dollars: 20}]->(c) - CREATE (a)-[:OWES {dollars: 25}]->(b) - CREATE (b)-[:OWES {dollars: 35}]->(d) - CREATE (d)-[:OWES {dollars: 15}]->(b) - CREATE (d)-[:OWES {dollars: 30}]->(b) -CREATE (:Counter {count: 0}) +CREATE (teamA:Team {name: 'Team A'}), + (teamB:Team {name: 'Team B'}), + (teamC:Team {name: 'Team C'}), + (playerA:Player {name: 'Player A', age: 21}), + (playerB:Player {name: 'Player B', age: 23}), + (playerC:Player {name: 'Player C', age: 19}), + (playerD:Player {name: 'Player D', age: 30}), + (playerE:Player {name: 'Player E', age: 25}), + (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), + (teamC)-[:OWES {dollars: 5000}]->(teamB) ---- -[[call-semantics]] -== Semantics +== Semantics and performance A `CALL` subquery is executed once for each incoming row. +The variables returned in a subquery are available to the outer scope of the enclosing query. -In the below example, the `CALL` subquery executes three times, one for each row that the `UNWIND` clause outputs. +.Basic example +==== +In this example, the `CALL` subquery executes three times, one for each row that the xref:clauses/unwind.adoc[`UNWIND`] clause outputs. .Query [source, cypher] ---- UNWIND [0, 1, 2] AS x -CALL { +CALL () { RETURN 'hello' AS innerReturn } RETURN innerReturn @@ -57,84 +67,360 @@ RETURN innerReturn [role="queryresult",options="header,footer",cols="m"] |=== | innerReturn + | 'hello' | 'hello' | 'hello' -d|Rows:3 + +d|Rows: 3 |=== +==== Each execution of a `CALL` subquery can observe changes from previous executions. +This allows for the accumulation of results and the progressive transformation of data within a single Cypher query. -.Query +.Incremental updates +==== +In this example, each iteration of the `CALL` subquery adds 1 to the `age` of `Player A` and the returned `newAge` reflects the `age` after each increment. + +.Incrementally update the age property of a Player [source, cypher] ---- -UNWIND [0, 1, 2] AS x -CALL { - MATCH (n:Counter) - SET n.count = n.count + 1 - RETURN n.count AS innerCount +UNWIND [1, 2, 3] AS x +CALL () { + MATCH (p:Player {name: 'Player A'}) + SET p.age = p.age + 1 + RETURN p.age AS newAge } -WITH innerCount -MATCH (n:Counter) -RETURN - innerCount, - n.count AS totalCount +WITH x, newAge +MATCH (p:Player {name: 'Player A'}) +RETURN x AS iteration, newAge, p.age AS totalAge ---- .Result -[role="queryresult",options="header,footer",cols=""2*(t) + RETURN collect(p) as players +} +RETURN t AS team, players +---- -[NOTE] +.Result +[source, role="queryresult",options="header,footer",cols="m,2m"] +|=== +| team +| players + +| (:Team {name: "Team A"}) +| [(:Player {name: "Player C", age: 19}), (:Player {name: "Player B", age: 23}), (:Player {name: "Player A", age: 24})] + +| (:Team {name: "Team B"}) +| [(:Player {name: "Player D", age: 30})] + +| (:Team {name: "Team C"}) +| [(:Player {name: "Player F", age: 35}), (:Player {name: "Player E", age: 25})] + +2+d|Rows: 3 +|=== + +The `CALL` subquery ensures that each `Team` is processed separately (one row per `Team` node), rather than having to hold every `Team` and `Player` node in heap memory simultaneously before collecting them into lists. +Using a `CALL` subquery can therefore reduce the amount of heap memory required for an operation. ==== -References to a variable in the outer scope that were not imported will introduce a new variable. + +[[import-variables]] +== Importing variables + +Variables from the outer scope must be explicitly imported into the inner scope of the `CALL` subquery, either by using a xref:subqueries/call-subquery.adoc#variable-scope-clause[variable scope clause] or an xref:subqueries/call-subquery.adoc#importing-with[importing `WITH` clause] (deprecated). +As the subquery is evaluated for each incoming input row, the imported variables are assigned the corresponding values from that row. + +[role=label--new-5.23] +[[variable-scope-clause]] +=== The variable scope clause + +Variables can be imported into a `CALL` subquery using a scope clause: `CALL ()`. +Using the scope clause disables the deprecated xref:subqueries/call-subquery.adoc#importing-with[importing `WITH`] clause. + +A scope clause can be used to import all, specific, or none of the variables from the outer scope. + +.Import specific variables from the outer scope ==== -As the subquery is evaluated for each incoming input row, the imported variables get bound to the corresponding values from the input row in each evaluation. +This example only imports the `p` variable from the outer scope and uses it to create a new, randomly generated, `rating` property for each `Player` node. +It then returns the `Player` node with the highest `rating`. -.Query +.Import one variable from the outer scope +[source, cypher, role=test-result-skip] +---- +MATCH (p:Player), (t:Team) +CALL (p) { + WITH rand() AS random + SET p.rating = random + RETURN p.name AS playerName, p.rating AS rating +} +RETURN playerName, rating, t AS team +ORDER BY rating +LIMIT 1 +---- + +.Result +[source, role="queryresult",options="header,footer",cols="3*m"] +|=== +| playerName +| rating +| team + +| "Player C" +| 0.9307432039870395 +| "Team A" + +3+d|Rows: 1 + +|=== + +To import additional variables, include them within the parentheses after `CALL`, separated by commas. +For example, to import both variables from the `MATCH` clause in the above query, modify the scope clause accordingly: `CALL (p, t)`. +==== + +.Import all variables +==== +To import all variables from the outer scope, use `CALL (*)`. +This example imports both the `p` and `t` variables and sets a new `lastUpdated` property on both. + +.Import all variables from the outer scope +[source, cypher, role=test-result-skip] +---- +MATCH (p:Player), (t:Team) +CALL (*) { + SET p.lastUpdated = timestamp() + SET t.lastUpdated = timestamp() +} +RETURN p.name AS playerName, + p.lastUpdated AS playerUpdated, + t.name AS teamName, + t.lastUpdated AS teamUpdated +LIMIT 1 +---- + +.Result +[source, role="queryresult",options="header,footer",cols="4*m"] +|=== + +| playerName +| playerUpdated +| teamName +| teamUpdated + +| "Player A" +| 1719304206653 +| "Team A" +| 1719304206653 + +4+d|Rows: 1 +|=== +==== + +.Import no variables +==== +To import no variables from the outer scope, use `CALL ()`. + +.Import no variables from the outer scope [source, cypher] ---- -UNWIND [0, 1, 2] AS x -CALL { - WITH x - RETURN x * 10 AS y +MATCH (t:Team) +CALL () { + MATCH (p:Player) + RETURN count(p) AS totalPlayers } -RETURN x, y +RETURN count(t) AS totalTeams, totalPlayers ---- .Result -[role="queryresult",options="header,footer",cols="2*(teams) + RETURN collect(p) as players +} +RETURN t AS teams, players +---- +* The scope clause’s variables cannot be re-declared in the subquery. + +.Not allowed +[source,cypher,role=test-fail] +---- +MATCH (t:Team) +CALL (t) { + WITH 'New team' AS t + MATCH (p:Player)-[:PLAYS_FOR]->(t) + RETURN collect(p) as players +} +RETURN t AS team, players +---- + +* The subquery cannot return a variable name which already exists in the outer scope. +To return imported variables they must be renamed. + +.Not allowed +[source,cypher,role=test-fail] +---- +MATCH (t:Team) +CALL (t) { + RETURN t +} +RETURN t +---- + +[role=label--deprecated] +[[importing-with]] +=== Importing `WITH` clause + +Variables can also be imported into a `CALL` subquery using an importing `WITH` clause. +Note that this syntax is not xref:appendix/gql-conformance/index.adoc[GQL conformant]. + +.Variables imported by `WITH` clause +[source, cypher] +---- +MATCH (t:Team) +CALL { + WITH t + MATCH (p:Player)-[:PLAYS_FOR]->(t) + RETURN collect(p) as players +} +RETURN t AS teams, players +---- + +.Click to read more about importing variables using the `WITH` clause +[%collapsible] +==== + +* Just as when using a variable scope clause, a subquery using an importing `WITH` clause cannot return a variable name which already exists in the outer scope. +To return imported variables they must be renamed. + +* The importing `WITH` clause must the first clause of a subquery (or the second clause, if directly following a `USE` clause). +* It is not possible to follow an importing `WITH` clause with any of the following clauses: `DISTINCT`, `ORDER BY`, `WHERE`, `SKIP`, and `LIMIT`. + +Attempting any of the above, will throw an error. +For example, the following query using a `WHERE` clause after an importing `WITH` clause will throw an error: + +.Not Allowed +[source, cypher, role=test-fail] +---- +UNWIND [[1,2],[1,2,3,4],[1,2,3,4,5]] AS l +CALL { + WITH l + WHERE size(l) > 2 + RETURN l AS largeLists +} +RETURN largeLists +---- + +.Error message +[source, error] +---- +Importing WITH should consist only of simple references to outside variables. +WHERE is not allowed. +---- + +A solution to this restriction, necessary for any filtering or ordering of an importing `WITH` clause, is to declare a second `WITH` clause after the importing `WITH` clause. +This second `WITH` clause will act as a regular `WITH` clause. +For example, the following query will not throw an error: + +.Allowed +[source, cypher] +---- +UNWIND [[1,2],[1,2,3,4],[1,2,3,4,5]] AS l +CALL { + WITH l + WITH l + WHERE size(l) > 2 + RETURN l AS largeLists +} +RETURN largeLists +---- + +.Result +[role="queryresult",options="header,footer",cols="1*(nextPerson) - RETURN current AS from, nextPerson AS to + SET nextPlayer:ListHead + CREATE(current)-[:IS_YOUNGER_THAN]->(nextPlayer) + RETURN current AS from, nextPlayer AS to } RETURN from.name AS name, @@ -171,81 +460,108 @@ RETURN ---- .Result -[role="queryresult",options="header,footer",cols="4*(other:Person) - RETURN o.dollars * -1 AS moneyOwed -UNION ALL - WITH p - OPTIONAL MATCH (other:Person)-[o:OWES]->(p) - RETURN o.dollars AS moneyOwed +MATCH (t:Team) +CALL (t) { + OPTIONAL MATCH (t)-[o:OWES]->(other:Team) + RETURN o.dollars * -1 AS moneyOwed + UNION ALL + OPTIONAL MATCH (other)-[o:OWES]->(t) + RETURN o.dollars AS moneyOwed } -RETURN p.name, sum(moneyOwed) AS amountOwing +RETURN t.name AS team, sum(moneyOwed) AS amountOwed +ORDER BY amountOwed DESC ---- .Result [role="queryresult",options="header,footer",cols="2*(p2:Player) + RETURN p2.name AS friend } -RETURN p.name, friend +RETURN p.name AS player, friend ---- .Result [role="queryresult",options="header,footer",cols="2*(c) - RETURN sum(o.dollars) AS owedAmount, c.name AS owedName +MATCH (t:Team) +CALL (t) { + MATCH (t)-[o:OWES]->(t2:Team) + RETURN sum(o.dollars) AS owedAmount, t2.name AS owedTeam } -RETURN p.name, owedAmount, owedName +RETURN t.name AS owingTeam, owedAmount, owedTeam ---- .Result [role="queryresult",options="header,footer",cols="3* 100 -CALL { - WITH n +CALL (n) { DETACH DELETE n } IN TRANSACTIONS ---- @@ -158,8 +158,7 @@ This example loads a CSV file with one transaction for every `2` input rows: [source, cypher] ---- LOAD CSV FROM 'file:///friends.csv' AS line -CALL { - WITH line +CALL (line) { CREATE (:Person {name: line[1], age: toInteger(line[2])}) } IN TRANSACTIONS OF 2 ROWS ---- @@ -191,8 +190,7 @@ For example: [source, cypher] ---- MATCH (n) -CALL { - WITH n +CALL (n) { DETACH DELETE n } IN TRANSACTIONS OF 2 ROWS ---- @@ -243,9 +241,8 @@ The following examples show how you can use `CALL { ... } IN TRANSACTIONS` on a ---- UNWIND graph.names() AS graphName LOAD CSV FROM 'file:///friends.csv' AS line -CALL { +CALL (*) { USE graph.byName( graphName ) - WITH line CREATE (:Person {name: line[1], age: toInteger(line[2])}) } IN TRANSACTIONS ---- @@ -306,7 +303,7 @@ While the declared batch size is 3, only the first 2 rows act on `composite.remo WITH ['composite.remoteGraph1', 'composite.remoteGraph2'] AS graphs UNWIND [0, 0, 1, 1, 1, 1, 0, 0] AS i WITH graphs[i] AS g -CALL { +CALL (g) { USE graph.byName( g ) CREATE () } IN TRANSACTIONS OF 3 ROWS @@ -339,8 +336,7 @@ due to division by zero. [source, cypher, role=test-fail] ---- UNWIND [4, 2, 1, 0] AS i -CALL { - WITH i +CALL (i) { CREATE (:Person {num: 100/i}) } IN TRANSACTIONS OF 2 ROWS RETURN i @@ -376,8 +372,7 @@ In the following example, `ON ERROR CONTINUE` is used after a failed inner trans [source, cypher] ---- UNWIND [1, 0, 2, 4] AS i -CALL { - WITH i +CALL (i) { CREATE (n:Person {num: 100/i}) // Note, fails when i = 0 RETURN n } IN TRANSACTIONS @@ -403,8 +398,7 @@ Note the difference in results when batching in transactions of 2 rows: [source, cypher, indent=0] ---- UNWIND [1, 0, 2, 4] AS i -CALL { - WITH i +CALL (i) { CREATE (n:Person {num: 100/i}) // Note, fails when i = 0 RETURN n } IN TRANSACTIONS @@ -435,8 +429,7 @@ In the following example, `ON ERROR BREAK` is used after a failed inner transact [source, cypher, indent=0] ---- UNWIND [1, 0, 2, 4] AS i -CALL { - WITH i +CALL (i) { CREATE (n:Person {num: 100/i}) // Note, fails when i = 0 RETURN n } IN TRANSACTIONS @@ -462,8 +455,7 @@ Note the difference in results when batching in transactions of 2 rows: [source, cypher, indent=0] ---- UNWIND [1, 0, 2, 4] AS i -CALL { - WITH i +CALL (i) { CREATE (n:Person {num: 100/i}) // Note, fails when i = 0 RETURN n } IN TRANSACTIONS @@ -489,8 +481,7 @@ In the following example, `ON ERROR FAIL` is used after the failed inner transac [source, cypher, indent=0, role=test-fail] ---- UNWIND [1, 0, 2, 4] AS i -CALL { - WITH i +CALL (i) { CREATE (n:Person {num: 100/i}) // Note, fails when i = 0 RETURN n } IN TRANSACTIONS @@ -529,8 +520,7 @@ Example of reporting status with `ON ERROR CONTINUE`: [source, cypher, indent=0, role=test-result-skip] ---- UNWIND [1, 0, 2, 4] AS i -CALL { - WITH i +CALL (i) { CREATE (n:Person {num: 100/i}) // Note, fails when i = 0 RETURN n } IN TRANSACTIONS @@ -557,8 +547,7 @@ Example of reporting status with `ON ERROR BREAK`: [source, cypher, indent=0] ---- UNWIND [1, 0, 2, 4] AS i -CALL { - WITH i +CALL (i) { CREATE (n:Person {num: 100/i}) // Note, fails when i = 0 RETURN n } IN TRANSACTIONS @@ -585,8 +574,7 @@ Reporting status with `ON ERROR FAIL` is disallowed: [source, cypher, role=test-fail] ---- UNWIND [1, 0, 2, 4] AS i -CALL { - WITH i +CALL (i) { CREATE (n:Person {num: 100/i}) // Note, fails when i = 0 RETURN n } IN TRANSACTIONS @@ -625,8 +613,7 @@ This example creates `Person` nodes from a unique `tmdbId` value assigned to eac [source, cypher] ---- LOAD CSV WITH HEADERS FROM 'https://data.neo4j.com/importing-cypher/persons.csv' AS row -CALL { - WITH row +CALL (row) { CREATE (p:Person {tmdbId: row.person_tmdbId}) SET p.name = row.name, p.born = row.born } IN 3 CONCURRENT TRANSACTIONS OF 10 ROWS @@ -684,8 +671,7 @@ Note that there are only three different years in the CSV file, meaning hat only [source, cypher, role=test-fail] ---- LOAD CSV WITH HEADERS FROM 'https://data.neo4j.com/importing-cypher/movies.csv' AS row -CALL { - WITH row +CALL (row) { MERGE (m:Movie {movieId: row.movieId}) MERGE (y:Year {year: row.year}) MERGE (m)-[r:RELEASED_IN]->(y) @@ -709,8 +695,7 @@ It returns the `transactionID`, `commitStatus` and `errorMessage` of the failed [source, cypher] ---- LOAD CSV WITH HEADERS FROM 'https://data.neo4j.com/importing-cypher/movies.csv' AS row -CALL { - WITH row +CALL (row) { MERGE (m:Movie {movieId: row.movieId}) MERGE (y:Year {year: row.year}) MERGE (m)-[r:RELEASED_IN]->(y) @@ -724,7 +709,7 @@ RETURN status.transactionId AS transaction, status.committed AS commitStatus, st [source, "queryresult"] ---- +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| transaction | commitStatus | errorMessage | +| transaction | commitStatus | errorMessage | +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | "neo4j-transaction-169" | FALSE | "ForsetiClient[transactionId=169, clientId=11] can't acquire ExclusiveLock{owner=ForsetiClient[transactionId=168, clientId=9]} on NODE_RELATIONSHIP_GROUP_DELETE(46) because holders of that lock are waiting for ForsetiClient[transactionId=169, clientId=11]. | | | \ Wait list:ExclusiveLock[ | @@ -768,16 +753,14 @@ While failed transactions may be more efficiently retried using a link:{neo4j-do [source, cypher] ---- LOAD CSV WITH HEADERS FROM 'https://data.neo4j.com/importing-cypher/movies.csv' AS row -CALL { - WITH row +CALL (row) { MERGE (m:Movie {movieId: row.movieId}) MERGE (y:Year {year: row.year}) MERGE (m)-[r:RELEASED_IN]->(y) } IN 2 CONCURRENT TRANSACTIONS OF 10 ROWS ON ERROR CONTINUE REPORT STATUS as status WITH * WHERE status.committed = false -CALL { - WITH row +CALL (row) { MERGE (m:Movie {movieId: row.movieId}) MERGE (y:Year {year: row.year}) MERGE (m)-[r:RELEASED_IN]->(y) @@ -795,59 +778,3 @@ These are the restrictions on queries that use `CALL { ... } IN TRANSACTIONS`: * A `CALL { ... } IN TRANSACTIONS` in a `UNION` is not supported. * A `CALL { ... } IN TRANSACTIONS` after a write clause is not supported, unless that write clause is inside a `CALL { ... } IN TRANSACTIONS`. -Additionally, there are some restrictions that apply when using an importing `WITH` clause in a `CALL` subquery: - -* Only variables imported with the importing `WITH` clause can be used. -* No expressions or aliasing are allowed within the importing `WITH` clause. -* It is not possible to follow an importing `WITH` clause with any of the following clauses: `DISTINCT`, `ORDER BY`, `WHERE`, `SKIP`, and `LIMIT`. - -Attempting any of the above, will throw an error. -For example, the following query using a `WHERE` clause after an importing `WITH` clause will throw an error: - -.Query -[source, cypher, role=test-fail] ----- -UNWIND [[1,2],[1,2,3,4],[1,2,3,4,5]] AS l -CALL { - WITH l - WHERE size(l) > 2 - RETURN l AS largeLists -} -RETURN largeLists ----- - -.Error message -[source, error] ----- -Importing WITH should consist only of simple references to outside variables. -WHERE is not allowed. ----- - -A solution to this restriction, necessary for any filtering or ordering of an importing `WITH` clause, is to declare a second `WITH` clause after the importing `WITH` clause. -This second `WITH` clause will act as a regular `WITH` clause. -For example, the following query will not throw an error: - -.Query -[source, cypher] ----- -UNWIND [[1,2],[1,2,3,4],[1,2,3,4,5]] AS l -CALL { - WITH l - WITH size(l) AS size, l AS l - WHERE size > 2 - RETURN l AS largeLists -} -RETURN largeLists ----- - -.Result -[role="queryresult",options="header,footer",cols="1*` | `ARRAY`, `INNER_TYPE LIST`, `INNER_TYPE ARRAY` -| `LOCAL DATETIME` | `TIMESTAMP WITHOUT TIMEZONE` -| `LOCAL TIME` | `TIME WITHOUT TIMEZONE` +| `LOCAL DATETIME` | `TIMESTAMP WITHOUT TIME ZONE`, `TIMESTAMP WITHOUT TIMEZONE` +| `LOCAL TIME` | `TIME WITHOUT TIME ZONE`, `TIME WITHOUT TIMEZONE` | `MAP` | | `NODE` | `ANY NODE`, `VERTEX`, `ANY VERTEX` | `NOTHING` | @@ -100,8 +100,8 @@ However, not all types can be used in all places. | `PROPERTY VALUE` | `ANY PROPERTY VALUE` | `RELATIONSHIP` | `ANY RELATIONSHIP`, `EDGE`, `ANY EDGE` | `STRING` | `VARCHAR` -| `ZONED DATETIME` | `TIMESTAMP WITH TIMEZONE` -| `ZONED TIME` | `TIME WITH TIMEZONE` +| `ZONED DATETIME` | `TIMESTAMP WITH TIME ZONE`, `TIMESTAMP WITH TIMEZONE` +| `ZONED TIME` | `TIME WITH TIME ZONE`, `TIME WITH TIMEZONE` | `INNER_TYPE_1 \| INNER_TYPE_2...` | `ANY` |=== diff --git a/package-lock.json b/package-lock.json index 74567389f..73be5181f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,8 +9,8 @@ "version": "5.0.0", "license": "ISC", "dependencies": { - "@antora/cli": "^3.1.8", - "@antora/site-generator-default": "^3.1.8", + "@antora/cli": "^3.1.9", + "@antora/site-generator-default": "^3.1.9", "@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,11 +26,11 @@ } }, "node_modules/@antora/asciidoc-loader": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@antora/asciidoc-loader/-/asciidoc-loader-3.1.8.tgz", - "integrity": "sha512-tNa9YBA/wVA3RGmDhAF2i4s7TPWgMcZsKZF1+mFBiYmhVuIiI5mkp6sH2M+/8MlApydSOc8p375gudgLKPKrJw==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/asciidoc-loader/-/asciidoc-loader-3.1.9.tgz", + "integrity": "sha512-flE27T2yI8TX7rUNjbBHWN3iR6s+kBuRBbUPncUFcWjx6mXzll8JLiTkxnc8JXHGzgKlveT+t5AkPYGACLfasg==", "dependencies": { - "@antora/logger": "3.1.8", + "@antora/logger": "3.1.9", "@antora/user-require-helper": "~2.0", "@asciidoctor/core": "~2.2" }, @@ -39,12 +39,12 @@ } }, "node_modules/@antora/cli": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@antora/cli/-/cli-3.1.8.tgz", - "integrity": "sha512-V7oIbbAONovCQWX2tKG14YmX03p6tquLP753NJEjj7QXjiWmJhOI0JsTD+fvaXr7DzkDnjnls4OwFBmiHZIkOw==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/cli/-/cli-3.1.9.tgz", + "integrity": "sha512-kCUqWX3G/9Pvf8SWZ45ioHwWdOc9uamy2E5/FFwyGiTeu4ubNbadOauLVvMzSZHUxVDnGxXwCsmmQ2HwM919ew==", "dependencies": { - "@antora/logger": "3.1.8", - "@antora/playbook-builder": "3.1.8", + "@antora/logger": "3.1.9", + "@antora/playbook-builder": "3.1.9", "@antora/user-require-helper": "~2.0", "commander": "~11.1" }, @@ -56,12 +56,12 @@ } }, "node_modules/@antora/content-aggregator": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@antora/content-aggregator/-/content-aggregator-3.1.8.tgz", - "integrity": "sha512-xBWbw2fiQ6UMEIGzknvpDLUW0gTpyiQVaRXjAOYe0JDAAvifjt0uJuBsu7WrRe1FmRkfkrYj8BJ6Yv34NWZJuA==", + "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==", "dependencies": { "@antora/expand-path-helper": "~2.0", - "@antora/logger": "3.1.8", + "@antora/logger": "3.1.9", "@antora/user-require-helper": "~2.0", "braces": "~3.0", "cache-directory": "~2.0", @@ -92,12 +92,12 @@ } }, "node_modules/@antora/content-classifier": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@antora/content-classifier/-/content-classifier-3.1.8.tgz", - "integrity": "sha512-0EzsZl7oBR5/MzLGIo3WwFeub2YtyDqExrELDmyDcJ4opZMREWfgUFu5Kls1MFAQPSbzEmQyIdyGacOrwTQHrg==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/content-classifier/-/content-classifier-3.1.9.tgz", + "integrity": "sha512-PVJqwp5uvZE1PlpeJtb0p6al75fN+fmXGIC6DHcKysRnr0xo+sgz8X2r4mnNWdTWRqum2yVigMmmuXYTg3cJlQ==", "dependencies": { - "@antora/asciidoc-loader": "3.1.8", - "@antora/logger": "3.1.8", + "@antora/asciidoc-loader": "3.1.9", + "@antora/logger": "3.1.9", "mime-types": "~2.1", "vinyl": "~3.0" }, @@ -106,11 +106,11 @@ } }, "node_modules/@antora/document-converter": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@antora/document-converter/-/document-converter-3.1.8.tgz", - "integrity": "sha512-dUGqgSdWnJYigbPZ9mDcoxITnufOEF5Vb5DKUxEstXe6MMn0yTZ03jJUbLs5YFgjqjhyULDMMIPo6no55zvx+w==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/document-converter/-/document-converter-3.1.9.tgz", + "integrity": "sha512-pH7tQaIjcPsFdYkaBEAvA/5ki04IQwQGHoR+2jadKdMl6P+J5KA1VzNnMgyIL6gHn7auJIkoOKadfItRB9lHGQ==", "dependencies": { - "@antora/asciidoc-loader": "3.1.8" + "@antora/asciidoc-loader": "3.1.9" }, "engines": { "node": ">=16.0.0" @@ -125,9 +125,9 @@ } }, "node_modules/@antora/file-publisher": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@antora/file-publisher/-/file-publisher-3.1.8.tgz", - "integrity": "sha512-crVP9EF5NZJDzeYPSpy74x35GRJIa4PfjfYBUxhzoNfqgX3JZcNuP8IwsWrSNyBDGO9a7ZCQ7+p4kpnVpF2x8Q==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/file-publisher/-/file-publisher-3.1.9.tgz", + "integrity": "sha512-C0VwVjuFbE1CVpZDgwYR1gZCNr1tMw5vueyF9wHZH0KCqAsp9iwo7bwj8wKWMPogxcxdYhnAvtDJnYmYFCuDWQ==", "dependencies": { "@antora/expand-path-helper": "~2.0", "@antora/user-require-helper": "~2.0", @@ -139,9 +139,9 @@ } }, "node_modules/@antora/logger": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@antora/logger/-/logger-3.1.8.tgz", - "integrity": "sha512-zbfjB1oMDDuuHjiRnBIbVTUBW1l1hCHbK4Q1oIRujnSz2LLjyY/aZfvgwODpREBGmvjkFb6Dlc9VUkKObQKi7g==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/logger/-/logger-3.1.9.tgz", + "integrity": "sha512-MKuANodcX0lfRyiB+Rxl/Kv7UOxc2glzTYFoIoBB7uzxF0A+AhvUJDmpGQFRFN2ihxy99N3nLJmZpDebwXyE+A==", "dependencies": { "@antora/expand-path-helper": "~2.0", "pino": "~9.2", @@ -153,22 +153,22 @@ } }, "node_modules/@antora/navigation-builder": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@antora/navigation-builder/-/navigation-builder-3.1.8.tgz", - "integrity": "sha512-u/USiJ1HhKSUxfUtLv7aQBFCJfBz6RtdzapKIy4z2Wol0FrwQwdaUhv7Amzabi2nrPEzkaNAM6ZX7iNPjGOw6Q==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/navigation-builder/-/navigation-builder-3.1.9.tgz", + "integrity": "sha512-zyl2yNjK31Dl6TRJgnoFb4Czwt9ar3wLTycAdMeZ+U/8YcAUHD8z7NCssPFFvZ0BbUr00NP+gbqDmCr6yz32NQ==", "dependencies": { - "@antora/asciidoc-loader": "3.1.8" + "@antora/asciidoc-loader": "3.1.9" }, "engines": { "node": ">=16.0.0" } }, "node_modules/@antora/page-composer": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@antora/page-composer/-/page-composer-3.1.8.tgz", - "integrity": "sha512-dw1ECMLYdf9GC9Zj8sHPd9Fgcg6BjU5BDbP+HI4omtOhLUiBVwWL1lZwFRVwgGMDgKSVgnxd9yotk+WTy2iLEg==", + "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==", "dependencies": { - "@antora/logger": "3.1.8", + "@antora/logger": "3.1.9", "handlebars": "~4.7", "require-from-string": "~2.0" }, @@ -177,9 +177,9 @@ } }, "node_modules/@antora/playbook-builder": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@antora/playbook-builder/-/playbook-builder-3.1.8.tgz", - "integrity": "sha512-VDIP8cVnmyRcbg4orP2mE8HkqHTh7MRE+QyJ8XyHvFZsZjcS0Qw5UqPcrlmqXrzQKmJcBj2plqSv+wKXAYbNcQ==", + "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==", "dependencies": { "@iarna/toml": "~2.2", "convict": "~6.2", @@ -191,9 +191,9 @@ } }, "node_modules/@antora/redirect-producer": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@antora/redirect-producer/-/redirect-producer-3.1.8.tgz", - "integrity": "sha512-ZSRnK/rXZ715baFheXMWEsyz0BpR+6RxFAem8A7rZPt2HMMKCOiuaFNdf9C97dxU5FxSELBIkRpqQ7eTRk+PPA==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/redirect-producer/-/redirect-producer-3.1.9.tgz", + "integrity": "sha512-9OLwoMhqifsBxTebInh/5W16GdDsdj+YkKG3TiCASlAOYsDbuhbeRPFUlyKKSRkMrtKKnFgHR0Z3DNPXYlH2NQ==", "dependencies": { "vinyl": "~3.0" }, @@ -202,23 +202,23 @@ } }, "node_modules/@antora/site-generator": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@antora/site-generator/-/site-generator-3.1.8.tgz", - "integrity": "sha512-xy1aUxTsCiC/KPlKQIoj2VWK956Mal8YyeokqXQTlTfRkuT5LPTJdmTA1ZHMEY9INy0z01Jx56Uyns62q98UtQ==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/site-generator/-/site-generator-3.1.9.tgz", + "integrity": "sha512-YYESPG22tGX1CxRPSAr6acKILCO8JfGkM1OYc7Sw3D7ZvCy1YgZMAaTYK0T5yl9LXg+l/UZi1xq/Ej0qHnYQiw==", "dependencies": { - "@antora/asciidoc-loader": "3.1.8", - "@antora/content-aggregator": "3.1.8", - "@antora/content-classifier": "3.1.8", - "@antora/document-converter": "3.1.8", - "@antora/file-publisher": "3.1.8", - "@antora/logger": "3.1.8", - "@antora/navigation-builder": "3.1.8", - "@antora/page-composer": "3.1.8", - "@antora/playbook-builder": "3.1.8", - "@antora/redirect-producer": "3.1.8", - "@antora/site-mapper": "3.1.8", - "@antora/site-publisher": "3.1.8", - "@antora/ui-loader": "3.1.8", + "@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" }, "engines": { @@ -226,22 +226,22 @@ } }, "node_modules/@antora/site-generator-default": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@antora/site-generator-default/-/site-generator-default-3.1.8.tgz", - "integrity": "sha512-6cjgxatANsp4iTbX6gbadfWwYngH4EXG3AyFWOmf6jMRih2MQSGc9zYL+QfHP6uqUiBfhIPCFwLbh3IiQ1v8JQ==", + "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==", "dependencies": { - "@antora/site-generator": "3.1.8" + "@antora/site-generator": "3.1.9" }, "engines": { "node": ">=16.0.0" } }, "node_modules/@antora/site-mapper": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@antora/site-mapper/-/site-mapper-3.1.8.tgz", - "integrity": "sha512-RV6SRiNFDd/dQRXvsckTsFQIiEpH7rHIoKlsOFB261rRY4JhXSu21TjR0dpk2vJ6iPMyudIuTkwoTWsdDi389Q==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/site-mapper/-/site-mapper-3.1.9.tgz", + "integrity": "sha512-9FCObL+JIjBoby8z+beu2uuvAtCjm5EsEQt+16gCIMX1ktVP3W3gVsdRSvVcGcVEpizILFhMawkcQknZPUp5mg==", "dependencies": { - "@antora/content-classifier": "3.1.8", + "@antora/content-classifier": "3.1.9", "vinyl": "~3.0" }, "engines": { @@ -249,20 +249,20 @@ } }, "node_modules/@antora/site-publisher": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@antora/site-publisher/-/site-publisher-3.1.8.tgz", - "integrity": "sha512-DdC+IDdzeYlmTu+LwMZ24hFJJRU+f8WG2MjM7kvKQ8fkPdk0TdzNoq3TkH78sYd+2WYXKuQU6DFU/OPxY44ulA==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/site-publisher/-/site-publisher-3.1.9.tgz", + "integrity": "sha512-L5To8f4QswZliXu6yB6O7O8CuBbLctjNbxZqP3m0FP7VaOONp85ftzEq1BFEm4BXXSwH1n4ujZx1qGBHP9ooOQ==", "dependencies": { - "@antora/file-publisher": "3.1.8" + "@antora/file-publisher": "3.1.9" }, "engines": { "node": ">=16.0.0" } }, "node_modules/@antora/ui-loader": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@antora/ui-loader/-/ui-loader-3.1.8.tgz", - "integrity": "sha512-wiStSKnt+QGTeVRpnM9fxOUf1xxyB4Y3cgRgdi5hb291pG/izz8imh3csjgMwN2jB3zZD4qYSJ29xnGr4+pK8Q==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/ui-loader/-/ui-loader-3.1.9.tgz", + "integrity": "sha512-g0/9dRE5JVMYukIU3x+Rvr41bPdK3sUD2xQIAniRjE6usIZs1mEsTGshVKVEoOqqnSekXE85HVhybjNHsC+qbQ==", "dependencies": { "@antora/expand-path-helper": "~2.0", "braces": "~3.0", @@ -2354,9 +2354,9 @@ } }, "node_modules/text-decoder": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.1.0.tgz", - "integrity": "sha512-TmLJNj6UgX8xcUZo4UDStGQtDiTzF7BzWlzn9g7UWrjkpHr5uJTK1ld16wZ3LXb2vb6jH8qU89dW5whuMdXYdw==", + "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==", "dependencies": { "b4a": "^1.6.4" } @@ -2415,9 +2415,9 @@ } }, "node_modules/uglify-js": { - "version": "3.18.0", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.18.0.tgz", - "integrity": "sha512-SyVVbcNBCk0dzr9XL/R/ySrmYf0s372K6/hFklzgcp2lBFyXtw4I7BOdDjlLhE1aVqaI/SHWXWmYdlZxuyF38A==", + "version": "3.19.1", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.1.tgz", + "integrity": "sha512-y/2wiW+ceTYR2TSSptAhfnEtpLaQ4Ups5zrjB2d3kuVxHj16j/QJwPl5PvuGy9uARb39J0+iKxcRPvtpsx4A4A==", "optional": true, "bin": { "uglifyjs": "bin/uglifyjs" @@ -2542,33 +2542,33 @@ }, "dependencies": { "@antora/asciidoc-loader": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@antora/asciidoc-loader/-/asciidoc-loader-3.1.8.tgz", - "integrity": "sha512-tNa9YBA/wVA3RGmDhAF2i4s7TPWgMcZsKZF1+mFBiYmhVuIiI5mkp6sH2M+/8MlApydSOc8p375gudgLKPKrJw==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/asciidoc-loader/-/asciidoc-loader-3.1.9.tgz", + "integrity": "sha512-flE27T2yI8TX7rUNjbBHWN3iR6s+kBuRBbUPncUFcWjx6mXzll8JLiTkxnc8JXHGzgKlveT+t5AkPYGACLfasg==", "requires": { - "@antora/logger": "3.1.8", + "@antora/logger": "3.1.9", "@antora/user-require-helper": "~2.0", "@asciidoctor/core": "~2.2" } }, "@antora/cli": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@antora/cli/-/cli-3.1.8.tgz", - "integrity": "sha512-V7oIbbAONovCQWX2tKG14YmX03p6tquLP753NJEjj7QXjiWmJhOI0JsTD+fvaXr7DzkDnjnls4OwFBmiHZIkOw==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/cli/-/cli-3.1.9.tgz", + "integrity": "sha512-kCUqWX3G/9Pvf8SWZ45ioHwWdOc9uamy2E5/FFwyGiTeu4ubNbadOauLVvMzSZHUxVDnGxXwCsmmQ2HwM919ew==", "requires": { - "@antora/logger": "3.1.8", - "@antora/playbook-builder": "3.1.8", + "@antora/logger": "3.1.9", + "@antora/playbook-builder": "3.1.9", "@antora/user-require-helper": "~2.0", "commander": "~11.1" } }, "@antora/content-aggregator": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@antora/content-aggregator/-/content-aggregator-3.1.8.tgz", - "integrity": "sha512-xBWbw2fiQ6UMEIGzknvpDLUW0gTpyiQVaRXjAOYe0JDAAvifjt0uJuBsu7WrRe1FmRkfkrYj8BJ6Yv34NWZJuA==", + "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==", "requires": { "@antora/expand-path-helper": "~2.0", - "@antora/logger": "3.1.8", + "@antora/logger": "3.1.9", "@antora/user-require-helper": "~2.0", "braces": "~3.0", "cache-directory": "~2.0", @@ -2592,22 +2592,22 @@ } }, "@antora/content-classifier": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@antora/content-classifier/-/content-classifier-3.1.8.tgz", - "integrity": "sha512-0EzsZl7oBR5/MzLGIo3WwFeub2YtyDqExrELDmyDcJ4opZMREWfgUFu5Kls1MFAQPSbzEmQyIdyGacOrwTQHrg==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/content-classifier/-/content-classifier-3.1.9.tgz", + "integrity": "sha512-PVJqwp5uvZE1PlpeJtb0p6al75fN+fmXGIC6DHcKysRnr0xo+sgz8X2r4mnNWdTWRqum2yVigMmmuXYTg3cJlQ==", "requires": { - "@antora/asciidoc-loader": "3.1.8", - "@antora/logger": "3.1.8", + "@antora/asciidoc-loader": "3.1.9", + "@antora/logger": "3.1.9", "mime-types": "~2.1", "vinyl": "~3.0" } }, "@antora/document-converter": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@antora/document-converter/-/document-converter-3.1.8.tgz", - "integrity": "sha512-dUGqgSdWnJYigbPZ9mDcoxITnufOEF5Vb5DKUxEstXe6MMn0yTZ03jJUbLs5YFgjqjhyULDMMIPo6no55zvx+w==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/document-converter/-/document-converter-3.1.9.tgz", + "integrity": "sha512-pH7tQaIjcPsFdYkaBEAvA/5ki04IQwQGHoR+2jadKdMl6P+J5KA1VzNnMgyIL6gHn7auJIkoOKadfItRB9lHGQ==", "requires": { - "@antora/asciidoc-loader": "3.1.8" + "@antora/asciidoc-loader": "3.1.9" } }, "@antora/expand-path-helper": { @@ -2616,9 +2616,9 @@ "integrity": "sha512-CSMBGC+tI21VS2kGW3PV7T2kQTM5eT3f2GTPVLttwaNYbNxDve08en/huzszHJfxo11CcEs26Ostr0F2c1QqeA==" }, "@antora/file-publisher": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@antora/file-publisher/-/file-publisher-3.1.8.tgz", - "integrity": "sha512-crVP9EF5NZJDzeYPSpy74x35GRJIa4PfjfYBUxhzoNfqgX3JZcNuP8IwsWrSNyBDGO9a7ZCQ7+p4kpnVpF2x8Q==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/file-publisher/-/file-publisher-3.1.9.tgz", + "integrity": "sha512-C0VwVjuFbE1CVpZDgwYR1gZCNr1tMw5vueyF9wHZH0KCqAsp9iwo7bwj8wKWMPogxcxdYhnAvtDJnYmYFCuDWQ==", "requires": { "@antora/expand-path-helper": "~2.0", "@antora/user-require-helper": "~2.0", @@ -2627,9 +2627,9 @@ } }, "@antora/logger": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@antora/logger/-/logger-3.1.8.tgz", - "integrity": "sha512-zbfjB1oMDDuuHjiRnBIbVTUBW1l1hCHbK4Q1oIRujnSz2LLjyY/aZfvgwODpREBGmvjkFb6Dlc9VUkKObQKi7g==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/logger/-/logger-3.1.9.tgz", + "integrity": "sha512-MKuANodcX0lfRyiB+Rxl/Kv7UOxc2glzTYFoIoBB7uzxF0A+AhvUJDmpGQFRFN2ihxy99N3nLJmZpDebwXyE+A==", "requires": { "@antora/expand-path-helper": "~2.0", "pino": "~9.2", @@ -2638,27 +2638,27 @@ } }, "@antora/navigation-builder": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@antora/navigation-builder/-/navigation-builder-3.1.8.tgz", - "integrity": "sha512-u/USiJ1HhKSUxfUtLv7aQBFCJfBz6RtdzapKIy4z2Wol0FrwQwdaUhv7Amzabi2nrPEzkaNAM6ZX7iNPjGOw6Q==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/navigation-builder/-/navigation-builder-3.1.9.tgz", + "integrity": "sha512-zyl2yNjK31Dl6TRJgnoFb4Czwt9ar3wLTycAdMeZ+U/8YcAUHD8z7NCssPFFvZ0BbUr00NP+gbqDmCr6yz32NQ==", "requires": { - "@antora/asciidoc-loader": "3.1.8" + "@antora/asciidoc-loader": "3.1.9" } }, "@antora/page-composer": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@antora/page-composer/-/page-composer-3.1.8.tgz", - "integrity": "sha512-dw1ECMLYdf9GC9Zj8sHPd9Fgcg6BjU5BDbP+HI4omtOhLUiBVwWL1lZwFRVwgGMDgKSVgnxd9yotk+WTy2iLEg==", + "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==", "requires": { - "@antora/logger": "3.1.8", + "@antora/logger": "3.1.9", "handlebars": "~4.7", "require-from-string": "~2.0" } }, "@antora/playbook-builder": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@antora/playbook-builder/-/playbook-builder-3.1.8.tgz", - "integrity": "sha512-VDIP8cVnmyRcbg4orP2mE8HkqHTh7MRE+QyJ8XyHvFZsZjcS0Qw5UqPcrlmqXrzQKmJcBj2plqSv+wKXAYbNcQ==", + "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==", "requires": { "@iarna/toml": "~2.2", "convict": "~6.2", @@ -2667,63 +2667,63 @@ } }, "@antora/redirect-producer": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@antora/redirect-producer/-/redirect-producer-3.1.8.tgz", - "integrity": "sha512-ZSRnK/rXZ715baFheXMWEsyz0BpR+6RxFAem8A7rZPt2HMMKCOiuaFNdf9C97dxU5FxSELBIkRpqQ7eTRk+PPA==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/redirect-producer/-/redirect-producer-3.1.9.tgz", + "integrity": "sha512-9OLwoMhqifsBxTebInh/5W16GdDsdj+YkKG3TiCASlAOYsDbuhbeRPFUlyKKSRkMrtKKnFgHR0Z3DNPXYlH2NQ==", "requires": { "vinyl": "~3.0" } }, "@antora/site-generator": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@antora/site-generator/-/site-generator-3.1.8.tgz", - "integrity": "sha512-xy1aUxTsCiC/KPlKQIoj2VWK956Mal8YyeokqXQTlTfRkuT5LPTJdmTA1ZHMEY9INy0z01Jx56Uyns62q98UtQ==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/site-generator/-/site-generator-3.1.9.tgz", + "integrity": "sha512-YYESPG22tGX1CxRPSAr6acKILCO8JfGkM1OYc7Sw3D7ZvCy1YgZMAaTYK0T5yl9LXg+l/UZi1xq/Ej0qHnYQiw==", "requires": { - "@antora/asciidoc-loader": "3.1.8", - "@antora/content-aggregator": "3.1.8", - "@antora/content-classifier": "3.1.8", - "@antora/document-converter": "3.1.8", - "@antora/file-publisher": "3.1.8", - "@antora/logger": "3.1.8", - "@antora/navigation-builder": "3.1.8", - "@antora/page-composer": "3.1.8", - "@antora/playbook-builder": "3.1.8", - "@antora/redirect-producer": "3.1.8", - "@antora/site-mapper": "3.1.8", - "@antora/site-publisher": "3.1.8", - "@antora/ui-loader": "3.1.8", + "@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/site-generator-default": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@antora/site-generator-default/-/site-generator-default-3.1.8.tgz", - "integrity": "sha512-6cjgxatANsp4iTbX6gbadfWwYngH4EXG3AyFWOmf6jMRih2MQSGc9zYL+QfHP6uqUiBfhIPCFwLbh3IiQ1v8JQ==", + "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==", "requires": { - "@antora/site-generator": "3.1.8" + "@antora/site-generator": "3.1.9" } }, "@antora/site-mapper": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@antora/site-mapper/-/site-mapper-3.1.8.tgz", - "integrity": "sha512-RV6SRiNFDd/dQRXvsckTsFQIiEpH7rHIoKlsOFB261rRY4JhXSu21TjR0dpk2vJ6iPMyudIuTkwoTWsdDi389Q==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/site-mapper/-/site-mapper-3.1.9.tgz", + "integrity": "sha512-9FCObL+JIjBoby8z+beu2uuvAtCjm5EsEQt+16gCIMX1ktVP3W3gVsdRSvVcGcVEpizILFhMawkcQknZPUp5mg==", "requires": { - "@antora/content-classifier": "3.1.8", + "@antora/content-classifier": "3.1.9", "vinyl": "~3.0" } }, "@antora/site-publisher": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@antora/site-publisher/-/site-publisher-3.1.8.tgz", - "integrity": "sha512-DdC+IDdzeYlmTu+LwMZ24hFJJRU+f8WG2MjM7kvKQ8fkPdk0TdzNoq3TkH78sYd+2WYXKuQU6DFU/OPxY44ulA==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/site-publisher/-/site-publisher-3.1.9.tgz", + "integrity": "sha512-L5To8f4QswZliXu6yB6O7O8CuBbLctjNbxZqP3m0FP7VaOONp85ftzEq1BFEm4BXXSwH1n4ujZx1qGBHP9ooOQ==", "requires": { - "@antora/file-publisher": "3.1.8" + "@antora/file-publisher": "3.1.9" } }, "@antora/ui-loader": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@antora/ui-loader/-/ui-loader-3.1.8.tgz", - "integrity": "sha512-wiStSKnt+QGTeVRpnM9fxOUf1xxyB4Y3cgRgdi5hb291pG/izz8imh3csjgMwN2jB3zZD4qYSJ29xnGr4+pK8Q==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@antora/ui-loader/-/ui-loader-3.1.9.tgz", + "integrity": "sha512-g0/9dRE5JVMYukIU3x+Rvr41bPdK3sUD2xQIAniRjE6usIZs1mEsTGshVKVEoOqqnSekXE85HVhybjNHsC+qbQ==", "requires": { "@antora/expand-path-helper": "~2.0", "braces": "~3.0", @@ -4240,9 +4240,9 @@ } }, "text-decoder": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.1.0.tgz", - "integrity": "sha512-TmLJNj6UgX8xcUZo4UDStGQtDiTzF7BzWlzn9g7UWrjkpHr5uJTK1ld16wZ3LXb2vb6jH8qU89dW5whuMdXYdw==", + "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==", "requires": { "b4a": "^1.6.4" } @@ -4289,9 +4289,9 @@ } }, "uglify-js": { - "version": "3.18.0", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.18.0.tgz", - "integrity": "sha512-SyVVbcNBCk0dzr9XL/R/ySrmYf0s372K6/hFklzgcp2lBFyXtw4I7BOdDjlLhE1aVqaI/SHWXWmYdlZxuyF38A==", + "version": "3.19.1", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.1.tgz", + "integrity": "sha512-y/2wiW+ceTYR2TSSptAhfnEtpLaQ4Ups5zrjB2d3kuVxHj16j/QJwPl5PvuGy9uARb39J0+iKxcRPvtpsx4A4A==", "optional": true }, "undefsafe": { diff --git a/package.json b/package.json index 9bcea5a76..624ebb8c1 100644 --- a/package.json +++ b/package.json @@ -19,8 +19,8 @@ "author": "Neo4j", "license": "ISC", "dependencies": { - "@antora/cli": "^3.1.8", - "@antora/site-generator-default": "^3.1.8", + "@antora/cli": "^3.1.9", + "@antora/site-generator-default": "^3.1.9", "@neo4j-antora/antora-add-notes": "^0.3.1", "@neo4j-antora/antora-modify-sitemaps": "^0.4.4", "@neo4j-antora/antora-page-roles": "^0.3.1",