diff --git a/modules/ROOT/pages/deprecations.adoc b/modules/ROOT/pages/deprecations.adoc index 33a081b4..cbfb4152 100644 --- a/modules/ROOT/pages/deprecations.adoc +++ b/modules/ROOT/pages/deprecations.adoc @@ -10,10 +10,10 @@ 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. -It allowed developers to build applications more quickly and with a bigger focus on functionality, while also helping users who already had an existing front end and needed a new back end. +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 front end. +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/index.adoc b/modules/ROOT/pages/index.adoc index bae5886f..bdef8a5e 100644 --- a/modules/ROOT/pages/index.adoc +++ b/modules/ROOT/pages/index.adoc @@ -4,8 +4,8 @@ The Neo4j GraphQL Library is a highly flexible, low-code, open source JavaScript library that enables rapid API development for cross-platform and mobile applications by tapping into the power of connected data. -With Neo4j as the graph database, the GraphQL Library makes it simple for applications to have data treated as a graph natively from the front end all the way to storage. -This avoids duplicate schema work and ensures flawless integration between front-end and back-end developers. +With Neo4j as the graph database, the GraphQL Library makes it simple for applications to have data treated as a graph natively from the frontend all the way to storage. +This avoids duplicate schema work and ensures flawless integration between frontend and backend developers. *If you are new to Neo4j and GraphQL*, take the course https://graphacademy.neo4j.com/courses/graphql-basics/?ref=docs[Introduction to Neo4j & GraphQL] in GraphAcademy to learn the fundamentals, how to use the xref:getting-started/toolbox.adoc[Neo4j GraphQL Toolbox] and the Neo4j GraphQL Library to create GraphQL APIs backed by a Neo4j graph database. @@ -36,8 +36,8 @@ For every query and mutation that is executed against this generated schema, the == Interaction -In the xref::getting-started/index.adoc[Getting Started] guide, Apollo Server is used to host the GraphQL schema, so you can interact directly with your API with no front end. -In case you prefer to use front-end frameworks, these are some clients that interact with GraphQL APIs: +In the xref::getting-started/index.adoc[Getting Started] guide, Apollo Server is used to host the GraphQL schema, so you can interact directly with your API with no frontend. +In case you prefer to use frontend frameworks, these are some clients that interact with GraphQL APIs: - https://reactjs.org/[React] - support through https://www.apollographql.com/docs/react/[Apollo Client] - https://vuejs.org/[Vue.js] - support through https://apollo.vuejs.org/[Vue Apollo] diff --git a/modules/ROOT/pages/queries-aggregations/aggregations.adoc b/modules/ROOT/pages/queries-aggregations/aggregations.adoc index 7b0733fd..ade63ec9 100644 --- a/modules/ROOT/pages/queries-aggregations/aggregations.adoc +++ b/modules/ROOT/pages/queries-aggregations/aggregations.adoc @@ -1,78 +1,45 @@ -[[queries-aggregations]] +[[aggregations]] +:description: This page describes aggregations supported by Neo4j GraphQL. = Aggregations -Neo4j GraphQL supports aggregations on fields with type: +Based on the given <>, here is a list of fields that accept aggregations supported by Neo4j GraphQL: -1. `ID`- String -2. `String` - String -3. `Int` - Numerical -4. `Float` - Numerical -5. `BigInt` - Numerical -6. `DateTime` -7. `Time` -8. `LocalTime` -9. `LocalDateTime` -10. `Duration` - -Numerical Fields will expose the following aggregation selections: - -1. `min` -2. `max` -3. `average` -4. `sum` - -String fields will expose: - -1. `shortest` -2. `longest` - -The rest will only expose: - -1. `min` -2. `max` - - -Aggregation queries accepts a `where` argument for xref::queries-aggregations/filtering.adoc[filtering] data. - -== Counting Using aggregation - -The following Query will count all User nodes: +[cols="1,1,2"] +|=== +| Type | Aggregating function | Example +| String (e.g. `ID`, `String`) +| `shortest`, `longest` +a| +.Longest User name [source, graphql, indent=0] ---- query { usersAggregate { - count - } -} ----- - -== Counting User nodes where name starts with "J" - -[source, graphql, indent=0] ----- -query { - usersAggregate(where: { name_STARTS_WITH: "J" }) { - count + name { + longest + } } } ---- -== Querying for the longest User name - +| Numeric (e.g. `Int`, `Float`, `BigInt`) +| `min`, `max`, `average`, `sum` +a| +.Example query [source, graphql, indent=0] ---- query { usersAggregate { - name { - longest - } + } } ----- - -== Querying for first Post date +---- +| Temporal (e.g. `DateTime`, `Time`, `LocalTime`, `LocalDateTime`, `Duration`) +| `min`, `max` +a| +.First Post date [source, graphql, indent=0] ---- query { @@ -83,8 +50,13 @@ query { } } ---- +|=== + +[NOTE] +==== +The argument `where` can also be used in aggregation queries for xref::queries-aggregations/filtering.adoc[filtering] data. +==== -[[queries-aggregate-related-nodes]] == Aggregate related nodes Related nodes can also be aggregated within a query by accessing the aggregation fields in the node. @@ -92,8 +64,27 @@ In these fields, you can **count**, aggregate the **nodes** or **edges** fields. The same selections and types as before are available in relationship aggregations. -=== Counting all posts per users +.Counting User nodes +[source, graphql, indent=0] +---- +query { + usersAggregate { + count + } +} +---- + +.Counting User nodes where name starts with "J" +[source, graphql, indent=0] +---- +query { + usersAggregate(where: { name_STARTS_WITH: "J" }) { + count + } +} +---- +.Counting all posts per User [source, graphql, indent=0] ---- query { @@ -106,9 +97,9 @@ query { } ---- -=== Finding longest post per user -By using the `node` field, related nodes properties can be aggregated. +By using the `node` field, related nodes properties can be aggregated: +.Finding longest post per User [source, graphql, indent=0] ---- query { @@ -125,9 +116,11 @@ query { } ---- -=== Aggregate relationships -Relationship properties can be aggregated as well by using the `edge` field. +== Aggregate relationships + +Relationship properties can be aggregated as well by using the `edge` field: +.Querying what User nodes posted up to a date [source, graphql, indent=0] ---- query { @@ -144,10 +137,8 @@ query { } ---- -=== Undirected aggregation queries - When performing an aggregation on related nodes, the query against the relationship -can be defined as an xref::queries-aggregations/queries.adoc#_undirected_queries[undirected] using the argument `directed: false`: +can be defined as "undirected" by using the argument `directed: false`: [source, graphql, indent=0] ---- diff --git a/modules/ROOT/pages/queries-aggregations/filtering.adoc b/modules/ROOT/pages/queries-aggregations/filtering.adoc index de0ea9b1..d186e485 100644 --- a/modules/ROOT/pages/queries-aggregations/filtering.adoc +++ b/modules/ROOT/pages/queries-aggregations/filtering.adoc @@ -1,42 +1,57 @@ [[filtering]] +:description: This page describes filtering operators. = Filtering -== Operators - When querying for data, a number of operators are available for different types in the `where` argument of a query or mutation. -=== Equality operators - -All types can be tested for either equality or non-equality. For the `Boolean` type, these are the only available comparison operators. - -[[filtering-numerical-operators]] -=== Numerical operators - -The following comparison operators are available for numeric types (`Int`, `Float`, xref::reference/type-definitions/types.adoc#type-definitions-types-bigint[`BigInt`]), xref::reference/type-definitions/types.adoc#type-definitions-types-temporal[Temporal Types] and xref::reference/type-definitions/types.adoc#type-definitions-types-spatial[Spatial Types]: - -* `_LT` -* `_LTE` -* `_GTE` -* `_GT` +== Equality operators -Filtering of spatial types is different to filtering of numerical types and also offers an additional filter - see xref::reference/type-definitions/types.adoc#type-definitions-types-spatial[Spatial Types]. +All types can be tested for either equality (`_eq`) or non-equality (`_ne`). +For example: -=== String comparison +.Filtering all Users named John +[source, graphql, indent=0] +---- +query { + users(where: {name: { _eq: "John" }}) + id + name + } +---- -The following case-sensitive comparison operators are only available for use on `String` and `ID` types: +[NOTE] +==== +For the `Boolean` type, equality operators are the only ones available. +==== -* `_STARTS_WITH` -* `_ENDS_WITH` -* `_CONTAINS` +== Numerical operators -The following operators are disabled by default: +These are the operators available for numeric (`Int`, `Float`, xref::reference/type-definitions/types.adoc#type-definitions-types-bigint[`BigInt`]), xref::reference/type-definitions/types.adoc#type-definitions-types-temporal[temporal] and xref::reference/type-definitions/types.adoc#type-definitions-types-spatial[spatial] types: * `_LT` * `_LTE` * `_GT` * `_GTE` -They can be enabled by explicitly adding them in the features options: +Here is an example of how to use them: + +.Filtering Users younger than 50 years old +[source, graphql, indent=0] +---- +query { + users(where: {age: { _lt: 50 }}) { + id + name + age + } +} +---- + +Spatial types use numerical filtering differently and they also have additional options. +See xref::/reference/type-definitions/types.adoc#_filtering[Spatial types filtering] for more information. + +These same operators are disabled by default in the case of String comparisons. +To enable, explicitly add them in the features options: [source, javascript, indent=0] ---- @@ -69,15 +84,37 @@ const neoSchema = new Neo4jGraphQL({ features, typeDefs, driver }); ---- -[[filtering-regex]] -==== RegEx matching +== String comparison -The filter `_MATCHES` is also available for comparison of `String` and `ID` types, which accepts a RegEx string as an argument and returns any matches. -Note that RegEx matching filters are **disabled by default**. +The following case-sensitive comparison operators are only available for use on `String` and `ID` types: + +* `_STARTS_WITH` +* `_ENDS_WITH` +* `_CONTAINS` + +Here is an example of how to use them: + +.Filtering Users with name starting with "J" +[source, graphql, indent=0] +---- +query { + users(where: { name_STARTS_WITH: "J" }) { + id + name + } +} +---- + +== RegEx matching -To enable the inclusion of this filter, set the features configuration object for each. +The filter `_MATCHES` is also available for comparison of `String` and `ID` types. +It accepts RegEx strings as an argument and returns any matches. + + +Note that RegEx matching filters are **disabled by default**. +This is because, on an unprotected API, they could potentially be used to execute a https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS[ReDoS attack^] against the backing Neo4j database. -For `String`: +If you want to enable them, set the features configuration object for each: [source, javascript, indent=0] ---- @@ -127,10 +164,9 @@ const features = { const neoSchema = new Neo4jGraphQL({ features, typeDefs, driver }); ---- -> The nature of RegEx matching means that on an unprotected API, this could potentially be used to execute a ReDoS attack (https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS) against the backing Neo4j database. +// This next section seems to be wrong. It mentions 4 operators, but there's one 2 and a similar sentence is repicated with not much context. Please take a look. -[[array-operators]] -=== Array comparison +== Array comparison The following two comparison operators are available on non-array fields, and accept an array argument: @@ -141,33 +177,14 @@ Conversely, the following operators are available on array fields, and accept a These four operators are available for all types apart from `Boolean`. -=== AND, OR, NOT operators +== Combining operators -Complex combinations of operators are possible using the `AND`/ `OR` / `NOT` operators. -These are stand-alone operators - that is, they are used as such and not appended to field names, and they accept an array/object argument with items of the same format as the `where` argument. +All operators can be combined using the `AND`, `OR`, and `NOT` operators. +They can also be stand-alone operators, which means that they can be used as such and not be appended to field names. -== Usage +These operators accept an array argument with items of the same format as the `where` argument, which means they can also be nested to form complex combinations. -Using the type definitions from xref::queries-aggregations/queries.adoc[Queries], below are some example of how filtering can be applied when querying for data. - -=== At the root of a query - -By using the `where` argument on the query field in question, you can return a User with a particular ID: - -[source, graphql, indent=0] ----- -query { - users(where: { id: "7CF1D9D6-E527-4ACD-9C2A-207AE0F5CB8C" }) { - name - } -} ----- - -=== Combining operators - -All above-mentioned operators can be combined using the `AND`/`OR`/`NOT` operators. -They accept an array argument with items of the same format as the `where` argument, which means they can also be nested to form complex combinations. -As an example, the below query matches all actors by the name of either "Keanu" or not belonging to the "Pantoliano" family, that played in "The Matrix" movie. +For example, if you want to match all actors by the name of either "Keanu" or not belonging to the "Pantoliano" family, that played in "The Matrix" movie, here is how you can query that: [source, graphql, indent=0] ---- @@ -193,42 +210,18 @@ query { } ---- -=== Filtering relationships - -By using the `where` argument on a relationship field, you can filter for a Post with a particular ID across all Users: - -[source, graphql, indent=0] ----- -query { - users { - id - name - posts(where: { id: "2D297425-9BCF-4986-817F-F06EE0A1D9C7" }) { - content - } - } -} ----- - -== Relationship Filtering - -For each relationship field, `field`, a set of filters are available depending on whether the relationship is `n..1` or `n..m`. In the case of `n..1`, filtering is done on equality or inequality of the related node by specifying a filter on `field`, respectively. In the case of `n..m`, filtering is done on the list of related nodes and is based on the https://neo4j.com/docs/cypher-manual/current/functions/predicate/[List Predicates] available in Cypher. - -=== Available Filters +== Relationship filtering -`n..1`:: - ** `field` - equality +Relationship filtering depends on the type of relationship that you have: -`n..m`:: - ** `field_ALL` - https://neo4j.com/docs/cypher-manual/current/functions/predicate/#functions-all[all] - ** `field_NONE` - https://neo4j.com/docs/cypher-manual/current/functions/predicate/#functions-none[none] - ** `field_SOME` - https://neo4j.com/docs/cypher-manual/current/functions/predicate/#functions-any[any] - ** `field_SINGLE` - https://neo4j.com/docs/cypher-manual/current/functions/predicate/#functions-single[single] +* `n..1`: filtering done on equality or inequality of the related nodes by specifying a filter on `field`. +* `n..m`: filtering is done on the list of related nodes and is based on the https://neo4j.com/docs/cypher-manual/current/functions/predicate/[list predicates] available in Cypher: +** `field_ALL` - https://neo4j.com/docs/cypher-manual/current/functions/predicate/#functions-all[all] +** `field_NONE` - https://neo4j.com/docs/cypher-manual/current/functions/predicate/#functions-none[none] +** `field_SOME` - https://neo4j.com/docs/cypher-manual/current/functions/predicate/#functions-any[any] +** `field_SINGLE` - https://neo4j.com/docs/cypher-manual/current/functions/predicate/#functions-single[single] - -=== Relationship Filtering Usage Examples - -For this section take as type definitions the following: +As an example, take these type definitions: [source, graphql, indent=0] ---- @@ -245,10 +238,13 @@ type Post { likes: [User!]! @relationship(type: "LIKES", direction: IN) } ---- -=== `n..1` Relationships -In the above, an `author` represents a `n..1` relationship on `Post` where a given `Post` is authored by one, and only one, `author`. The available filters here will be `author`. +=== In the case of `n..1` relationships + +An `author` represents an `n..1` relationship on `Post`, where a given `Post` is authored by one, and only one, `author`. +The available filters here will be `author`. +For example: -==== Find all posts by a desired author +.Find all posts by a desired author [source, graphql, indent=0] ---- query { @@ -257,7 +253,8 @@ query { } } ---- -==== Find all posts not by an undesired author + +.Find all posts `NOT` by an undesired author [source, graphql, indent=0] ---- query { @@ -266,10 +263,13 @@ query { } } ---- -=== `n..m` Relationships -In the above, `posts` represents a `n..m` relationship on `User` where a given `User` can have any number of `posts`. -==== Find all users where all of their posts contain search term: `"neo4j"` +=== In the case of `n..m` relationships + +In the previous example, `posts` represents a `n..m` relationship on `User`, where a given `User` can have any number of `posts`. +Here are some query examples: + +.Find all Users where all of their posts contain search term: `"neo4j"` [source, graphql, indent=0] ---- query { @@ -279,7 +279,7 @@ query { } ---- -==== Find all users where none of their posts contain search term: `"cypher"` +.Find all Users where none of their posts contains search term: `"cypher"` [source, graphql, indent=0] ---- query { @@ -289,7 +289,7 @@ query { } ---- -==== Find all users where some of their posts contain search term: `"graphql"` +.Find all users where some of their posts contain search term: `"graphql"` [source, graphql, indent=0] ---- query { @@ -299,7 +299,7 @@ query { } ---- -==== Find all users where only one of their posts contain search term: `"graph"` +.Find all users where only one of their posts contain search term: `"graph"` [source, graphql, indent=0] ---- query { @@ -309,23 +309,16 @@ query { } ---- -== Aggregation Filtering - -This library offers, for each relationship, an aggregation key inside the where argument. You can use the aggregation key to satisfy questions such as: - -* Find the posts where the number of likes are greater than 5 -* Find flights where the average age of passengers is greater than or equal to 18 -* Find movies where the shortest actor screen time is less than 10 minutes - -You can use this where aggregation on both the `node` and `edge` of a relationship. - +== Aggregation filtering -=== Aggregation Filtering Usage Examples +This library offers, for each relationship, an aggregation key inside the `where` argument. +It can be used both on the `node` and `edge` of a relationship. -==== Find the posts where the number of likes are greater than 5 - -Given the schema: +Here are some examples on how to apply this kind of filtering: +. *Find posts where the number of likes are greater than 5* ++ +.Schema example [source, graphql, indent=0] ---- type User { @@ -337,9 +330,8 @@ type Post { likes: [User!]! @relationship(type: "LIKES", direction: IN) } ---- - -Answering the question: - ++ +.Query [source, graphql, indent=0] ---- query { @@ -349,10 +341,9 @@ query { } ---- -==== Find flights where the average age of passengers is greater than or equal to 18 - -Given the schema: - +. *Find flights where the average age of passengers is greater than or equal to 18* ++ +.Schema example [source, graphql, indent=0] ---- type Passenger { @@ -365,9 +356,8 @@ type Flight { passengers: [Passenger!]! @relationship(type: "FLYING_ON", direction: IN) } ---- - -Answering the question: - ++ +.Query [source, graphql, indent=0] ---- query { @@ -377,10 +367,9 @@ query { } ---- -==== Find movies where the shortest actor screen time is less than 10 minutes - -Given the schema: - +. *Find movies where the shortest actor screen time is less than 10 minutes* ++ +.Schema example [source, graphql, indent=0] ---- type Movie { @@ -396,9 +385,8 @@ interface ActedIn @relationshipProperties { screenTime: Int } ---- - -Answering the question: - ++ +.Query [source, graphql, indent=0] ---- query { @@ -408,22 +396,19 @@ query { } ---- -=== Aggregation Filtering Operators +=== Operators -Below you will learn more about the autogenerated filters available on the aggregate key and for each type on the `node` and `edge` of the specified relationship. +Aggregation filtering can also be done with operators. +They provide autogenerated filters available for each type on the `node` and `edge` of the specified relationship. -==== Count -This is a special 'top level' key inside the where aggregation and will be available for all relationships. This is used to count the amount of relationships the parent node is connected to. -The operators count has are as follows: - -* `count_EQUAL` -* `count_GT` -* `count_GTE` -* `count_LT` -* `count_LTE` - -===== Example +[cols="1,2,2,2"] +|=== +| Field type | Description | Operators | Example +| `count` +| A special 'top level' key inside the `where` aggregation and will be available for all relationships. This is used to count the amount of relationships the parent node is connected to. +| `count_EQUAL`, `count_GT`, `count_GTE`, `count_LT`, `count_LTE` +a| [source, graphql, indent=0] ---- query { @@ -433,34 +418,10 @@ query { } ---- -==== `ID` - -No Aggregation filters are available for ID. - -==== `String` - -Fields of type `String` have the following operators: - -* `_AVERAGE_LENGTH_EQUAL` -* `_AVERAGE_LENGTH_GT` -* `_AVERAGE_LENGTH_GTE` -* `_AVERAGE_LENGTH_LT` -* `_AVERAGE_LENGTH_LTE` -* `_SHORTEST_LENGTH_EQUAL` -* `_SHORTEST_LENGTH_GT` -* `_SHORTEST_LENGTH_GTE` -* `_SHORTEST_LENGTH_LT` -* `_SHORTEST_LENGTH_LTE` -* `_LONGEST_LENGTH_EQUAL` -* `_LONGEST_LENGTH_GT` -* `_LONGEST_LENGTH_GTE` -* `_LONGEST_LENGTH_LT` -* `_LONGEST_LENGTH_LTE` - -These operators are calculated against the length of each string. - -===== Example - +| `String` +| These operators are calculated against the length of each string. +| `_AVERAGE_LENGTH_EQUAL` `_AVERAGE_LENGTH_GT` `_AVERAGE_LENGTH_GTE` `_AVERAGE_LENGTH_LT` `_AVERAGE_LENGTH_LTE` `_SHORTEST_LENGTH_EQUAL` `_SHORTEST_LENGTH_GT` `_SHORTEST_LENGTH_GTE` `_SHORTEST_LENGTH_LT` `_SHORTEST_LENGTH_LTE` `_LONGEST_LENGTH_EQUAL` `_LONGEST_LENGTH_GT` `_LONGEST_LENGTH_GTE` `_LONGEST_LENGTH_LT` `_LONGEST_LENGTH_LTE` +a| [source, graphql, indent=0] ---- query { @@ -470,39 +431,10 @@ query { } ---- -==== Numerical Types - -Numerical types include the following: - -* `Int` -* `Float` -* `BigInt` - -The types in the list above have the following operators: - -* `_AVERAGE_EQUAL` -* `_AVERAGE_GT` -* `_AVERAGE_GTE` -* `_AVERAGE_LT` -* `_AVERAGE_LTE` -* `_SUM_EQUAL` -* `_SUM_GT` -* `_SUM_GTE` -* `_SUM_LT` -* `_SUM_LTE` -* `_MIN_EQUAL` -* `_MIN_GT` -* `_MIN_GTE` -* `_MIN_LT` -* `_MIN_LTE` -* `_MAX_EQUAL` -* `_MAX_GT` -* `_MAX_GTE` -* `_MAX_LT` -* `_MAX_LTE` - -===== Example - +| `Numerical` +| Used in the case of `Int`, `Float`, and `BigInt`. +| `_AVERAGE_EQUAL`, `_AVERAGE_GT`, `_AVERAGE_GTE`, `_AVERAGE_LT`, `_AVERAGE_LTE`, `_SUM_EQUAL`, `_SUM_GT`, `_SUM_GTE`, `_SUM_LT`, `_SUM_LTE`, `_MIN_EQUAL`, `_MIN_GT`, `_MIN_GTE`, `_MIN_LT`, `_MIN_LTE`, `_MAX_EQUAL`, `_MAX_GT`, `_MAX_GTE`, `_MAX_LT`, `_MAX_LTE` +a| [source, graphql, indent=0] ---- query { @@ -512,33 +444,27 @@ query { } ---- -==== Temporal Types - -Temporal types include the following: - -* `DateTime` -* `LocalDateTime` -* `LocalTime` -* `Time` -* `Duration` - -The types listed above have the following aggregation operators: +| `Temporal` +| Used in the case of `DateTime`, `LocalDateTime`, `LocalTime`, `Time`, and `Duration`. +| `_MIN_EQUAL`, `_MIN_GT`, `_MIN_GTE`, `_MIN_LT`, `_MIN_LTE`, `_MAX_EQUAL`, `_MAX_GT`, `_MAX_GTE`, `_MAX_LT`, `_MAX_LTE` +a| +[source, graphql, indent=0] +---- +{} +---- -* `_MIN_EQUAL` -* `_MIN_GT` -* `_MIN_GTE` -* `_MIN_LT` -* `_MIN_LTE` -* `_MAX_EQUAL` -* `_MAX_GT` -* `_MAX_GTE` -* `_MAX_LT` -* `_MAX_LTE` +| `Duration` +| Description. +| `_AVERAGE_EQUAL`, `_AVERAGE_GT`, `_AVERAGE_GTE`, `_AVERAGE_LT`, `_AVERAGE_LTE` +a| +[source, graphql, indent=0] +---- +{} +---- -Whilst the `Duration` type also has the following additional operators: +| `ID` +| No aggregation filters are available for ID. +| - +| - -* `_AVERAGE_EQUAL` -* `_AVERAGE_GT` -* `_AVERAGE_GTE` -* `_AVERAGE_LT` -* `_AVERAGE_LTE` +|=== \ No newline at end of file diff --git a/modules/ROOT/pages/queries-aggregations/index.adoc b/modules/ROOT/pages/queries-aggregations/index.adoc index 2c4f546d..af5d8d6b 100644 --- a/modules/ROOT/pages/queries-aggregations/index.adoc +++ b/modules/ROOT/pages/queries-aggregations/index.adoc @@ -2,9 +2,49 @@ :description: This section describes queries and aggregations. = Queries and aggregations +Each node defined in xref::/reference/type-definitions/index.adoc[type definitions] has two query fields generated for it: one for *querying* data and another one for *aggregating* it. +Each of these fields, by their part, accepts two arguments used for *filtering*, *sorting*, and *pagination*. + This section addresses the following topics: * xref:queries-aggregations/queries.adoc[Queries] - How to read or fetch values. * xref:queries-aggregations/aggregations.adoc[Aggregations] - How to combine lists of types from different sources into a single list. * xref:queries-aggregations/filtering.adoc[Filtering] - How to filter query results to find objects. * xref:queries-aggregations/sorting.adoc[Sorting] - How to sort query results by each individual field. + +[#examples-reference] +*All examples featured in this section use the following type definitions:* + +[source, graphql, indent=0] +---- +type Post { + id: ID! @id + content: String! + creator: User! @relationship(type: "HAS_POST", direction: IN, properties: "PostedAt") + createdAt: DateTime! +} + +type User { + id: ID! @id + name: String! + posts: [Post!]! @relationship(type: "HAS_POST", direction: OUT, properties: "PostedAt") + friends: [User!]! @relationship(type: "FRIENDS_WITH", direction: OUT) +} + +interface PostedAt @relationshipProperties { + date: DateTime +} +---- + +For which the following query fields are generated: + +[source, graphql, indent=0] +---- +type Query { + posts(where: PostWhere, options: PostOptions): [Post!]! + postsAggregate(where: PostWhere): PostAggregationSelection! + + users(where: UserWhere, options: UserOptions): [User!]! + usersAggregate(where: UserWhere): UserAggregationSelection! +} +---- \ No newline at end of file diff --git a/modules/ROOT/pages/queries-aggregations/queries.adoc b/modules/ROOT/pages/queries-aggregations/queries.adoc index ac55744d..ba46261a 100644 --- a/modules/ROOT/pages/queries-aggregations/queries.adoc +++ b/modules/ROOT/pages/queries-aggregations/queries.adoc @@ -1,58 +1,10 @@ [[queries]] +:description: This page describes how to read or fetch values in the Neo4j GraphQL Library. = Queries -Each node defined in type definitions will have two query fields generated for it: - -1. One for querying data -2. One for aggregating data - -The examples in this chapter will use the following type definitions: - -[source, graphql, indent=0] ----- -type Post { - id: ID! @id - content: String! - creator: User! @relationship(type: "HAS_POST", direction: IN, properties: "PostedAt") - createdAt: DateTime! -} - -type User { - id: ID! @id - name: String! - posts: [Post!]! @relationship(type: "HAS_POST", direction: OUT, properties: "PostedAt") - friends: [User!]! @relationship(type: "FRIENDS_WITH", direction: OUT) -} - -interface PostedAt @relationshipProperties { - date: DateTime -} ----- - -For which the following query fields will be generated: - -[source, graphql, indent=0] ----- -type Query { - posts(where: PostWhere, options: PostOptions): [Post!]! - postsAggregate(where: PostWhere): PostAggregationSelection! - - users(where: UserWhere, options: UserOptions): [User!]! - usersAggregate(where: UserWhere): UserAggregationSelection! -} ----- - -== Query - -Each field for querying data accepts two arguments: - -- `where` - used for xref::queries-aggregations/filtering.adoc[Filtering] data -- `options` - used to specify xref::queries-aggregations/sorting.adoc[Sorting] and xref::pagination/index.adoc[Pagination] options - -=== Querying for all User nodes - -The following query will return all User nodes, returning their ID and name. +Based on the given <>, here are two examples of how to write queries for reading or fetching values: +.Return all User nodes from their ID and name [source, graphql, indent=0] ---- query { @@ -63,10 +15,7 @@ query { } ---- -=== Query for user with name "Jane Smith" and their posts - -The following query will return all Users, returning the content which they have posted. - +.Query User with name "Jane Smith" and their posts [source, graphql, indent=0] ---- query { @@ -80,13 +29,14 @@ query { } ---- -=== Undirected queries +== Undirected queries -All xref:reference/type-definitions/relationships.adoc[relationships] are created with a _direction_ from one **node** to another. -By default, all queries follow the direction defined in the relationship, however, in some cases we may need to query for -all related nodes, regardless of the direction of the relationship. This can be achieved with the argument `directed: false`. +All xref:reference/type-definitions/relationships.adoc[relationships] are created with a direction from one node to another. +By default, all queries follow the direction defined in the relationship. +However, in some cases it is necessary to query for all related nodes, regardless of the direction of the relationship. +This can be achieved with the argument `directed: false`. -For example, the following query: +For example, the following query should return all User friends, regardless of the direction of the relationship `"FRIENDS_WITH"`: [source, graphql, indent=0] ---- @@ -100,9 +50,7 @@ query { } ---- -Will return all user friends, regardless on the direction of the relationship `"FRIENDS_WITH"`. - -Undirected relationships can also be used in the same fashion with connections: +In addition, undirected relationships can also be used in the same fashion with connections: [source, graphql, indent=0] ---- @@ -119,170 +67,5 @@ query Query { } ---- -Note that _undirected relationships_ are only supported in queries. - -The xref:reference/type-definitions/relationships.adoc#_querydirection[type definitions] for a relationship may define -a different behaviour, so the `directed` option may not be available in some cases. - -[[queries-aggregate]] -== Aggregate - -Neo4j GraphQL supports aggregations on fields with type: - -1. `ID`- String -2. `String` - String -3. `Int` - Numerical -4. `Float` - Numerical -5. `BigInt` - Numerical -6. `DateTime` -7. `Time` -8. `LocalTime` -9. `LocalDateTime` -10. `Duration` - -Numerical Fields will expose the following aggregation selections: - -1. `min` -2. `max` -3. `average` -4. `sum` - -String fields will expose: - -1. `shortest` -2. `longest` - -The rest will only expose: - -1. `min` -2. `max` - - -Aggregation queries accepts a `where` argument for xref::queries-aggregations/filtering.adoc[filtering] data. - -=== Counting Using aggregation - -The following query will count all User nodes: - -[source, graphql, indent=0] ----- -query { - usersAggregate { - count - } -} ----- - -=== Counting User nodes where name starts with "J" - -[source, graphql, indent=0] ----- -query { - usersAggregate(where: { name_STARTS_WITH: "J" }) { - count - } -} ----- - -=== Querying for the longest User name - -[source, graphql, indent=0] ----- -query { - usersAggregate { - name { - longest - } - } -} ----- - -=== Querying for first Post date - -[source, graphql, indent=0] ----- -query { - postsAggregate { - createdAt { - min - } - } -} ----- - -[[queries-aggregate-related-nodes]] -== Aggregate related nodes - -Related nodes can also be aggregated within a query by accessing the aggregation fields in the node. -In these fields, you can **count**, aggregate the **nodes** or **edges** fields. - -The same selections and types as before are available in relationship aggregations. - -=== Counting all posts per users - -[source, graphql, indent=0] ----- -query { - users { - id - postsAggregate { - count - } - } -} ----- - -=== Finding longest post per user -By using the `node` field, related nodes properties can be aggregated. - -[source, graphql, indent=0] ----- -query { - users { - name - postsAggregate { - node { - content { - longest - } - } - } - } -} ----- - -=== Aggregate relationships -Relationship properties can be aggregated as well by using the `edge` field. - -[source, graphql, indent=0] ----- -query { - users { - name - postsAggregate { - edge { - date { - max - } - } - } - } -} ----- - -=== Undirected aggregation queries - -When performing an aggregation on related nodes, the query against the relationship -can be defined as an xref::queries-aggregations/queries.adoc#_undirected_queries[undirected] using the argument `directed: false`: - -[source, graphql, indent=0] ----- -query { - users { - id - postsAggregate(directed: false) { - count - } - } -} ----- +Keep in mind that *undirected relationships are only supported in queries*. +The xref:reference/type-definitions/relationships.adoc#_querydirection[type definitions] for a relationship may define a different behavior, so the `directed` option may not be available in some cases. \ No newline at end of file diff --git a/modules/ROOT/pages/queries-aggregations/sorting.adoc b/modules/ROOT/pages/queries-aggregations/sorting.adoc index 923d2391..aa5b93bc 100644 --- a/modules/ROOT/pages/queries-aggregations/sorting.adoc +++ b/modules/ROOT/pages/queries-aggregations/sorting.adoc @@ -1,9 +1,11 @@ [[sorting]] +:description: This page describes how to use sorting input types. = Sorting -A sorting input type is generated for every object type defined in your type definitions, allowing for query results to be sorted by each individual field. +A sorting input type is generated for every object type defined in your type definitions. +It allows for query results to be sorted by each individual field. -Using the following example type definition: +Using this example type definition: [source, graphql, indent=0] ---- @@ -13,7 +15,7 @@ type Movie { } ---- -The following sorting input type and query will be generated: +The following sorting input type and query should be generated: [source, graphql, indent=0] ---- @@ -44,7 +46,7 @@ type Query { } ---- -The following query would then allow you to fetch all movies sorted by runtime in ascending order: +The resulting query should then allow fetching all movies sorted by runtime in ascending order: [source, graphql, indent=0] ---- @@ -62,7 +64,7 @@ query { } ---- -Additionally, say there was a relationship between the `Movie` and an `Actor` type, sorting can also be applied when fetching the `actors` field: +Additionally, in case there was a relationship between the `Movie` and an `Actor` type, sorting can also be applied when fetching the `actors` field: [source, graphql, indent=0] ----