diff --git a/modules/ROOT/pages/deprecations.adoc b/modules/ROOT/pages/deprecations.adoc index cbfb4152..093f0b05 100644 --- a/modules/ROOT/pages/deprecations.adoc +++ b/modules/ROOT/pages/deprecations.adoc @@ -9,11 +9,11 @@ The following products and applications are deprecated: == GRANDstack starter app -The main purpose of the GRANDstack starter app was to demonstrate how the Neo4j Labs GraphQL library could be used in the context of a full-stack application using React and Apollo client. +The main purpose of the GRANDstack starter app was to demonstrate how the Neo4j Labs GraphQL Library could be used in the context of a full-stack application using React and Apollo client. It allowed developers to build applications more quickly and with a bigger focus on functionality, while also helping users who already had an existing frontend and needed a new back end. Over time, the GRANDstack starter app grew to support other frameworks such as Flutter and Angular, thus the need to revisit its scope. -The intention is to replace this project with a new starter application product, which will focus on the back end and the configuration of the GraphQL library, as well as help developers with their frontend. +The intention is to replace this project with a new starter application product, which will focus on the back end and the configuration of the GraphQL Library, as well as help developers with their frontend. In the meantime, the `create-grandstack-app` npm package has been marked as deprecated. It can still be used to skeleton a GRANDstack app, but the user will be warned that the package is deprecated. diff --git a/modules/ROOT/pages/migration/index.adoc b/modules/ROOT/pages/migration/index.adoc index 8ab7e651..92ba3436 100644 --- a/modules/ROOT/pages/migration/index.adoc +++ b/modules/ROOT/pages/migration/index.adoc @@ -34,7 +34,7 @@ The following deprecated `NOT` filters are removed from the schema since they ar - `edge_NOT` -To achieve the same in version 6.x of the GraphQL library, use the xref:/queries-aggregations/filtering.adoc#_boolean_operators[boolean `NOT` operator] instead. +To achieve the same in version 6.x of the GraphQL Library, use the xref:/queries-aggregations/filtering.adoc#_boolean_operators[boolean `NOT` operator] instead. [cols="1,1"] |=== @@ -68,7 +68,7 @@ The following deprecated `_NOT` filters on `@relationship` are removed and no lo - `actors_NOT` - `actorsConnection_NOT` -To achieve the same in version 6.x of the GraphQL library, use the `NONE` quantifier. +To achieve the same in version 6.x of the GraphQL Library, use the `NONE` quantifier. [cols="1,1"] |=== diff --git a/modules/ROOT/pages/mutations/create.adoc b/modules/ROOT/pages/mutations/create.adoc index 439c97b2..dd8f87b2 100644 --- a/modules/ROOT/pages/mutations/create.adoc +++ b/modules/ROOT/pages/mutations/create.adoc @@ -2,7 +2,7 @@ :description: This page describes how to create nodes through mutations. = `create` -Using the following type definitions: +Consider the following type definitions: [source, graphql, indent=0] ---- @@ -19,7 +19,7 @@ type User @node { } ---- -These `create` mutations and response types should be generated: +The following `create` mutations and response types are generated: [source, graphql, indent=0] ---- @@ -65,11 +65,12 @@ mutation { } ---- -This should create a `User` with name "John Doe", and that name plus the autogenerated ID should be returned. +This creates a `User` with the name "John Doe". +The name and the autogenerated ID are returned. == Nested `create` -A `User` and an initial `Post` can be created by executing the following: +You can create a `User` and their initial `Post` at once by executing the following: [source, graphql, indent=0] ---- @@ -101,7 +102,7 @@ mutation { ---- This creates a `User` with name "John Doe" and an introductory post. -Both should be returned with their autogenerated IDs. +Both are returned with their autogenerated IDs. [NOTE] ==== @@ -111,7 +112,7 @@ Read about xref:mutations/update.adoc#_connectorcreate_relationships[`update`] f == `connectOrCreate` relationships -If a related node has the `@unique` directive defined, `connectOrCreate` can be used in a nested `create` to perform a `MERGE` operation on the related node. +If a related node has the `@unique` directive defined, you can use `connectOrCreate` nested in a `create` mutation to perform an operation similar to a link:https://neo4j.com/docs/cypher-manual/current/clauses/merge/[Cypher `MERGE`] operation on the related node. This will create a new relationship and the related node if it doesn't exist yet. Consider the following type definitions: @@ -130,7 +131,7 @@ type Movie @node { } ---- -Because a movie ID is unique, `connectOrCreate` can be used in an `Actor` mutation to ensure the movie exists in the database before connecting. +Since a movie ID is unique, you can use `connectOrCreate` in an `Actor` mutation to ensure the movie exists in the database before connecting them. Note that only `@unique` or `@id` fields can be used in `where`: [source, graphql, indent=0] @@ -152,15 +153,17 @@ mutation { } ---- -This will ensure that a movie with ID 1234 exists and it is connected to `"Tom Hanks"`. If the movie does not exist, it will be created with the title `"Forrest Gump"`. Note that if the movie with the given ID already exists, it will be connected to it, regardless of the title. +This ensures that a movie with ID 1234 exists and is connected to `"Tom Hanks"`. +If the movie does not exist, it will be created with the title `"Forrest Gump"`. +If a movie with the given ID already exists, it will also be connected to `"Tom Hanks"`, and keep whatever title it has. -== `CREATE` optimization +== `create` optimization -With the `create` operations, there is no limit on how many nodes can be created at once. +With `create` operations, there is no limit on how many nodes can be created at once. However, there is a known performance issue for large batch sizes. The Neo4j GraphQL Library contains an optimization feature designed to mitigate it, but it does not work in the following scenarios: * A field is populated using the directive `@populated_by`. -* The `connect` or `connectOrCreate` operation is used. +* The `connect` or `connectOrCreate` operations are used. * Interface and union types are present in the mutation. diff --git a/modules/ROOT/pages/mutations/delete.adoc b/modules/ROOT/pages/mutations/delete.adoc index cda22e37..29e33d0d 100644 --- a/modules/ROOT/pages/mutations/delete.adoc +++ b/modules/ROOT/pages/mutations/delete.adoc @@ -4,7 +4,7 @@ = `delete` -Using these type definitions: +Consider these type definitions: [source, graphql, indent=0] ---- @@ -21,7 +21,7 @@ type User @node { } ---- -These `delete` mutations and response types should be generated: +The following `delete` mutations and response types are generated: [source, graphql, indent=0] ---- @@ -43,7 +43,7 @@ The `DeleteInfo` type is the common return type for all delete mutations. == Single `delete` -A single post can be deleted by executing the following GraphQL statement: +You can delete a single post by executing the following GraphQL statement: [source, graphql, indent=0] ---- @@ -57,12 +57,12 @@ mutation { } ---- -This should delete the post using the autogenerated ID that was returned after that post's creation. -Consequently, `nodesDeleted` should be equal `1` (the post) and `relationshipsDeleted` should also equal `1` as the `HAS_POST` relationship between the `Post` and its author was deleted. +This deletes the post using the autogenerated ID that was returned after the creation of the post. +Consequently, `nodesDeleted` is equal to `1` (the post) and `relationshipsDeleted` is also equal to `1` as the `HAS_POST` relationship between the `Post` and its author was deleted. == Nested `delete` -In case you want to delete a `User` *and* all of their posts, you can use a single nested `delete` mutation: +In case you want to delete a `User` and all of their posts, you can use a single nested `delete` mutation: [source, graphql, indent=0] ---- @@ -72,42 +72,4 @@ mutation { relationshipsDeleted } } ----- - -By the time the traversal has reached it, that empty `where` argument has the context of only refer to posts that were created by Jane Doe, as the traversals to those `Post` nodes were from her `User` node. -Essentially, the above query is equivalent to: - -[source, graphql, indent=0] ----- -mutation { - deleteUsers( - where: { - name_EQ: "Jane Doe" - }, - delete: { - posts: [ - where: { - node: { - creator: { - name_EQ: "Jane Doe" - } - } - } - ] - } - ) { - nodesDeleted - relationshipsDeleted - } -} ----- - -Note that the output Cypher statement should also have a redundant `WHERE` clause: - -//Please add the cypher statement: - -//[source, cypher, indent=0] -//---- -//DELETE User (name:"Jane Doe") -//WHERE Posts - -//---- +---- \ No newline at end of file diff --git a/modules/ROOT/pages/mutations/index.adoc b/modules/ROOT/pages/mutations/index.adoc index e8fe2e4f..7dba01c1 100644 --- a/modules/ROOT/pages/mutations/index.adoc +++ b/modules/ROOT/pages/mutations/index.adoc @@ -3,7 +3,7 @@ :description: This section describes how to use mutations with the Neo4j GraphQL Library. -This section addresses basic examples of the following mutations: +This page shows examples of the following mutations: - xref::mutations/create.adoc[`create`] - create nodes, and recursively create or connect further nodes in the graph. - xref::mutations/update.adoc[`update`] - update nodes, and recursively perform any operations from there. @@ -15,5 +15,5 @@ In order to provide the abstractions available in these mutations, the output Cy This can result in your database throwing out-of-memory errors depending on its configuration. If this becomes a regular occurrence, you can adjust the link:https://neo4j.com/docs/operations-manual/current/configuration/configuration-settings/#config_server.memory.heap.max_size[`server.memory.heap.max_size`] parameter in the DBMS settings. -If you need to perform major data migrations, it may be best to manually write the necessary Cypher and execute this directly in the database. +If you must perform major data migrations, it may be best to manually write the necessary Cypher and execute this directly in the database. ==== \ No newline at end of file diff --git a/modules/ROOT/pages/mutations/update.adoc b/modules/ROOT/pages/mutations/update.adoc index 7ce43eea..0493e98c 100644 --- a/modules/ROOT/pages/mutations/update.adoc +++ b/modules/ROOT/pages/mutations/update.adoc @@ -1,10 +1,11 @@ [[mutations-update]] = `update` :page-aliases: array-methods.adoc, mathematical-operators.adoc +:example-caption!: :description: This page describes how to update nodes through mutations. -Using these type definitions: +Consider the following type definitions: [source, graphql, indent=0] ---- @@ -21,7 +22,7 @@ type User @node { } ---- -These `update` mutations and response types should be generated: +These `update` mutations and response types are generated: [source, graphql, indent=0] ---- @@ -52,7 +53,7 @@ The `id` field cannot be updated as the xref::/directives/autogeneration.adoc#ty == Single `update` -The content of a `Post` can be updated by executing the following GraphQL statement: +You can update the content of a `Post` by executing the following GraphQL statement: [source, graphql, indent=0] ---- @@ -72,7 +73,7 @@ mutation { } ---- -This should update the post by adding the sentence "Some new content for this Post!". +This updates the post by adding the sentence "Some new content for this Post!". == Nested `create` using `update` @@ -160,10 +161,14 @@ Array methods allow the modification of existing property arrays in `update` mut For that, the following operators are available: -* `_POP`: expects a single `Int` value as input. -* `_PUSH`: conforms to the type of input defined in the type definition. +* `_PUSH` +* `_POP` -Consider the following type definitions, a `Movie` with a property array called `tags`: +=== `_PUSH` + +`_PUSH` conforms to the type of input defined in the type definition. + +Consider the following type definitions, a `Movie` with a property array of `String` types called `tags`: [source, graphql, indent=0] ---- @@ -173,26 +178,14 @@ type Movie @node { } ---- -You can pop from this `tags` property array: - -[cols="1,1"] -|=== -| Before | After - -a| -``` -tags: ['a', 'b', 'c'] -``` -a| -``` -tags: ['a', 'b'] -``` -|=== +You can push tags to the `tags` property array: +.Mutation with a single `_PUSH` +==== [source, graphql, indent=0] ---- mutation { - updateMovies (update: { tags_POP: 1 }) { + updateMovies (update: { tags_PUSH: "another tag" }) { movies { title tags @@ -200,27 +193,24 @@ mutation { } } ---- +[col=1,1] +|=== +| Before | After -Or, for more than one property from the array: +| `['some tag']` -[cols="1,1"] +| `['some tag', 'another tag']` |=== -| Before | After +==== -a| -``` -tags: ['a', 'b', 'c'] -``` -a| -``` -tags: ['a'] -``` -|=== +Or push multiple elements in a single update: +.Mutation with two `_PUSH` +==== [source, graphql, indent=0] ---- mutation { - updateMovies (update: { tags_POP: 2 }) { + updateMovies (update: { tags_PUSH: ["another tag", "one more tag"] }) { movies { title tags @@ -229,6 +219,15 @@ mutation { } ---- +[col=1,1] +|=== +| Before | After + +| `['some tag']` +| `['some tag', 'another tag', 'one more tag']` +|=== +==== + Similarly, you can have multiple array property fields and update them in the same query: [source, graphql, indent=0] @@ -240,28 +239,13 @@ type Movie @node { } ---- -Then, you can `POP` from both the `tags` and `moreTags` property arrays: - -[cols="1,1"] -|=== -| Before | After - -a| -``` -tags: ['a', 'b', 'c'] -moreTags: ['x', 'y', 'z'] -``` -a| -``` - tags: ['a', 'b'] - moreTags: ['x'] -``` -|=== - +You can also push to both the `tags` and `moreTags` property arrays: +.Mutation with `_PUSH` to two different arrays +==== [source, graphql, indent=0] ---- mutation { - updateMovies (update: { tags_POP: 1, moreTags_POP: 2 }) { + updateMovies (update: { tags_PUSH: "another tag", moreTags_PUSH: "a different tag" }) { movies { title tags @@ -271,23 +255,45 @@ mutation { } ---- -=== `_PUSH` - -Using the same type definitions as before, you can push to the `tags` property array: - [col=1,1] -|==== +|=== | Before | After -| `['some tag']` +a| +``` + tags: ['some tag'] + moreTags: [] +``` +a| +``` + tags: ['some tag', 'another tag'] + moreTags ['a different tag'] +``` +|=== +==== -| `['some tag', 'another tag']` -|==== +=== `_POP` + +`_POP` expects a single `Int` value as input. +Consider the following type definitions, a `Movie` with a property array called `tags`: + +[source, graphql, indent=0] +---- +type Movie @node { + title: String + tags: [String] +} +---- + +You can pop from this `tags` property array: + +.Mutation with a single `_POP` +==== [source, graphql, indent=0] ---- mutation { - updateMovies (update: { tags_PUSH: "another tag" }) { + updateMovies (update: { tags_POP: 1 }) { movies { title tags @@ -296,20 +302,29 @@ mutation { } ---- -Or push multiple elements in a single update: +[cols="1,1"] +|=== +| Before | After -[col=1,1] -|==== -| Before | After +a| +``` +tags: ['a', 'b', 'c'] +``` +a| +``` +tags: ['a', 'b'] +``` +|=== +==== -| `['some tag']` -| `['some tag', 'another tag', 'one more tag']` -|==== +Or, for more than one property from the array: +.Mutation with two `_POP` +==== [source, graphql, indent=0] ---- mutation { - updateMovies (update: { tags_PUSH: ["another tag", "one more tag"] }) { + updateMovies (update: { tags_POP: 2 }) { movies { title tags @@ -318,8 +333,24 @@ mutation { } ---- +[cols="1,1"] +|=== +| Before | After + +a| +``` +tags: ['a', 'b', 'c'] +``` +a| +``` +tags: ['a'] +``` +|=== +==== + Similarly, you can have multiple array property fields and update them in the same query: + [source, graphql, indent=0] ---- type Movie @node { @@ -329,28 +360,14 @@ type Movie @node { } ---- -You can also push to both the `tags` and `moreTags` property arrays: - -[col=1,1] -|==== -| Before | After - -a| -``` - tags: ['some tag'] - moreTags: [] -``` -a| -``` - tags: ['some tag', 'another tag'] - moreTags ['a different tag'] -``` -|==== +Then, you can pop from both the `tags` and `moreTags` property arrays: +.Mutation with `_POP` from two different arrays +==== [source, graphql, indent=0] ---- mutation { - updateMovies (update: { tags_PUSH: "another tag", moreTags_PUSH: "a different tag" }) { + updateMovies (update: { tags_POP: 1, moreTags_POP: 2 }) { movies { title tags @@ -360,7 +377,24 @@ mutation { } ---- -=== Combined methods +[cols="1,1"] +|=== +| Before | After + +a| +``` +tags: ['a', 'b', 'c'] +moreTags: ['x', 'y', 'z'] +``` +a| +``` + tags: ['a', 'b'] + moreTags: ['x'] +``` +|=== +==== + +=== Mixing `_PUSH` and `_POP` It is possible to perform both a `_PUSH` and `_POP` operation in one single `update` mutation. @@ -375,10 +409,25 @@ type Movie @node { } ---- -You can update both property arrays with either `_POP` or `_PUSH` operators at once: +You can update both property arrays with either `_PUSH` or `_POP` operators at once: + +.Mutation with both a `_PUSH` and a `_POP` +==== +[source, graphql, indent=0] +---- +mutation { + updateMovies (update: { tags_POP: 1, moreTags_PUSH: "a different tag" }) { + movies { + title + tags + moreTags + } + } +} +---- [col=1,1] -|==== +|=== | Before | After a| @@ -392,37 +441,25 @@ a| tags: [] moreTags ['a different tag'] ``` -|==== - -[source, graphql, indent=0] ----- -mutation { - updateMovies (update: { tags_POP: 1, moreTags_PUSH: "a different tag" }) { - movies { - title - tags - moreTags - } - } -} ----- +|=== +==== == Mathematical operators -Mathematical operators can be used to update numerical fields based on their original values in a single DB transaction. -For that, specific operators are available on different numerical types: `Int`, `Float`, xref::/types/scalar.adoc[`BigInt`]. +You can use mathematical operators to update numerical fields based on their original values in a single DB transaction. +For that, specific operators are available on different numerical types: `Int`, `Float` and xref::/types/scalar.adoc[`BigInt`]. They are supported within these entities: * Nodes * Relationship properties * Interfaces -For `Int` and `BigInt` types, the following operators are available: +For the `Int` and `BigInt` types, the following operators are available: -* `_DECREMENT` * `_INCREMENT` +* `_DECREMENT` -For `Float` type, the following operators are available: +For the `Float` type, the following operators are available: * `_ADD` * `_SUBTRACT` @@ -432,10 +469,10 @@ For `Float` type, the following operators are available: [NOTE] ==== Operators remain available as optional fields. -If a mathematical operator has been used in a field not defined, it will prompt a GraphQL error. +If a mathematical operator has been used in an undefined field, it causes a GraphQL error. ==== -For example, take the following GraphQL schema for a social video platform: +For example, consider the following GraphQL schema for a social video platform: [source, graphql, indent=0] ---- @@ -455,7 +492,7 @@ type OwnVideo @relationshipProperties { } ---- -Suppose a user viewed a video in this platform, so that you want to increment `viewersCount` for that video by `1`. +Suppose a user watched a video in this platform, and you want to increment `viewersCount` for that video by `1`. Here is how you can do that: [source, graphql, indent=0] @@ -473,7 +510,7 @@ mutation incrementViewCountMutation { } ---- -Now, suppose the social platform wants to reward the user with 0.01 dollars for viewing the video. +Now, suppose you want the social platform to reward the user with 0.01 dollars for watching the video. To do that, you have to update the relationship property `revenue`: [source, graphql, indent=0] diff --git a/modules/ROOT/pages/queries-aggregations/aggregations.adoc b/modules/ROOT/pages/queries-aggregations/aggregations.adoc index c4ced6e3..a9885bb1 100644 --- a/modules/ROOT/pages/queries-aggregations/aggregations.adoc +++ b/modules/ROOT/pages/queries-aggregations/aggregations.adoc @@ -4,7 +4,7 @@ == Type definitions -Quries on this page assume the following type definitions: +Queries on this page assume the following type definitions: [source, graphql, indent=0] ---- diff --git a/modules/ROOT/pages/queries-aggregations/filtering.adoc b/modules/ROOT/pages/queries-aggregations/filtering.adoc index fa8e2e38..766ac8c6 100644 --- a/modules/ROOT/pages/queries-aggregations/filtering.adoc +++ b/modules/ROOT/pages/queries-aggregations/filtering.adoc @@ -440,7 +440,7 @@ query { == Aggregation filtering -The Neo4j GraphQL library offers an aggregation key inside the `where` argument of each relationship. +The Neo4j GraphQL Library offers an aggregation key inside the `where` argument of each relationship. You can use it both on the `node` and `edge` of a relationship. Here are some examples on how to apply this kind of filtering: