diff --git a/modules/ROOT/content-nav.adoc b/modules/ROOT/content-nav.adoc index 0e4ad2df..31681d03 100644 --- a/modules/ROOT/content-nav.adoc +++ b/modules/ROOT/content-nav.adoc @@ -20,6 +20,7 @@ ** xref:types/interfaces.adoc[Interfaces] ** xref:types/unions.adoc[Union] ** xref:types/relationships.adoc[] +* xref:filtering.adoc[] * xref:neo4jgraphql-class.adoc[] * xref:directives/index.adoc[] ** xref:directives/database-mapping.adoc[] @@ -35,11 +36,8 @@ * xref:queries-aggregations/index.adoc[Queries and aggregations] ** xref:queries-aggregations/queries.adoc[] ** xref:queries-aggregations/aggregations.adoc[] -** xref:queries-aggregations/filtering.adoc[] ** xref:queries-aggregations/sorting.adoc[] -** xref:queries-aggregations/pagination/index.adoc[] -*** xref:queries-aggregations/pagination/offset-based.adoc[] -*** xref:queries-aggregations/pagination/cursor-based.adoc[] +** xref:queries-aggregations/pagination.adoc[] * xref:mutations/index.adoc[] ** xref:mutations/create.adoc[] diff --git a/modules/ROOT/pages/queries-aggregations/filtering.adoc b/modules/ROOT/pages/filtering.adoc similarity index 95% rename from modules/ROOT/pages/queries-aggregations/filtering.adoc rename to modules/ROOT/pages/filtering.adoc index 627a4203..64b5e6ce 100644 --- a/modules/ROOT/pages/queries-aggregations/filtering.adoc +++ b/modules/ROOT/pages/filtering.adoc @@ -1,11 +1,13 @@ [[filtering]] = Filtering -:page-aliases: filtering.adoc +:page-aliases: queries-aggregations/filtering.adoc :description: This page describes filtering operators. +You can apply filters when you query or aggregate data as well as use filtering rules for xref::/security/authorization.adoc#_filtering_rules[authorization]. + When querying for data, a number of operators are available for the types in the `where` argument of a query or mutation, allowing you to filter query results or specify the set of objects a mutation applies to. -Operators can either be standalone operators (see xref:#_boolean_operators[]) or they are appended to field names (for example, xref:/queries-aggregations/filtering.adoc#_string_comparison[]). +Operators can either be standalone operators (see xref:#_boolean_operators[]) or they are appended to field names (for example, xref:#_string_comparison[]). All operators can be combined using the Boolean operators `AND`, `OR`, and `NOT`. @@ -42,7 +44,7 @@ query { } ---- -`name_CONTAINS` and `name_ENDS_WITH` are xref:/queries-aggregations/filtering.adoc#_string_comparison[String comparisons] while `movies_SOME` is a xref:/queries-aggregations/filtering.adoc#_relationship_filtering[relationship filter]. +`name_CONTAINS` and `name_ENDS_WITH` are xref:#_string_comparison[String comparisons] while `movies_SOME` is a xref:#_relationship_filtering[relationship filter]. === Equality operators @@ -60,7 +62,7 @@ query { } ---- -For non-equality, you must use the xref:/queries-aggregations/filtering.adoc#_boolean_operators[`NOT`] logical operator. +For non-equality, you must use the xref:#_boolean_operators[`NOT`] logical operator. .Filtering all users which are not named John [source, graphql, indent=0] @@ -101,11 +103,11 @@ query { ---- Spatial types use numerical filtering differently and they also have additional options. -See xref:filtering.adoc#_filtering_spatial_types[Filtering spatial types] for more information. +See xref:filtering.adoc#_spatial_type_filtering[] for more information. ==== Spatial type filtering -Both the `Point` and the `CartesianPoint` types use xref::queries-aggregations/filtering.adoc#_numerical_operators[numerical operators] and have an additional `_DISTANCE` filter. +Both the `Point` and the `CartesianPoint` types use xref:#_numerical_operators[numerical operators] and have an additional `_DISTANCE` filter. Here is a list of what each filter does for the two types: * `_LT`: checks if a point is less than the distance in the `distance` field away (in meters) from the point specified by the `point` field. diff --git a/modules/ROOT/pages/index.adoc b/modules/ROOT/pages/index.adoc index c9770fda..58e796c9 100644 --- a/modules/ROOT/pages/index.adoc +++ b/modules/ROOT/pages/index.adoc @@ -27,9 +27,9 @@ For every query and mutation that is executed against this generated schema, the - xref::/types/index.adoc[Types], including temporal and spatial. - Support for both node and relationship properties. - Extensibility through the xref::/directives/custom-logic.adoc#_cypher[`@cypher` directive] and/or xref::/directives/custom-logic.adoc#_customresolver[Custom Resolvers]. -- Extensive xref::queries-aggregations/filtering.adoc[Filtering] and xref::queries-aggregations/sorting.adoc[Sorting] options. +- Extensive xref::filtering.adoc[Filtering] and xref::queries-aggregations/sorting.adoc[Sorting] options. - Options for xref::/directives/database-mapping.adoc[Database mapping] and value xref::/directives/autogeneration.adoc[Autogeneration]. -- xref::/queries-aggregations/pagination/index.adoc[Pagination] options. +- xref::/queries-aggregations/pagination.adoc[Pagination] options. - xref::/security/index.adoc[Security options] and additional xref::schema-configuration/index.adoc[Schema Configuration]. - A xref::getting-started/toolbox.adoc[Toolbox] (UI) to experiment with your Neo4j GraphQL API on Neo4j Desktop. diff --git a/modules/ROOT/pages/neo4jgraphql-class.adoc b/modules/ROOT/pages/neo4jgraphql-class.adoc index b40eeabe..83ff71e5 100644 --- a/modules/ROOT/pages/neo4jgraphql-class.adoc +++ b/modules/ROOT/pages/neo4jgraphql-class.adoc @@ -53,7 +53,7 @@ export type Neo4jFeaturesSettings = { Use `Neo4jFiltersSettings` to enable numeric String comparisons and regular expression filters for Strings and IDs. They are disabled by default. -See xref:queries-aggregations/filtering.adoc#_string_comparison[String comparison] and xref:queries-aggregations/filtering.adoc#_regex_matching[RegEx matching]. +See xref:filtering.adoc#_string_comparison[String comparison] and xref:filtering.adoc#_regex_matching[RegEx matching]. === `populatedBy` settings diff --git a/modules/ROOT/pages/queries-aggregations/index.adoc b/modules/ROOT/pages/queries-aggregations/index.adoc index e7cd86bf..c8533667 100644 --- a/modules/ROOT/pages/queries-aggregations/index.adoc +++ b/modules/ROOT/pages/queries-aggregations/index.adoc @@ -10,6 +10,7 @@ This section addresses the following topics: * xref:queries-aggregations/queries.adoc[Queries] - Read or fetch values. * xref:queries-aggregations/aggregations.adoc[Aggregations] - Combine lists of types from different sources into a single list. -* xref:queries-aggregations/filtering.adoc[Filtering] - Filter query results to find objects. * xref:queries-aggregations/sorting.adoc[Sorting] - Sort query results by individual fields. -* xref:queries-aggregations/pagination/index.adoc[Pagination] - Navigate result pages. +* xref:queries-aggregations/pagination.adoc[Pagination] - Navigate result pages. + +Also, refer to xref:filtering.adoc[Filtering] for details on how to filter query results to find objects. \ No newline at end of file diff --git a/modules/ROOT/pages/queries-aggregations/pagination.adoc b/modules/ROOT/pages/queries-aggregations/pagination.adoc new file mode 100644 index 00000000..ec891936 --- /dev/null +++ b/modules/ROOT/pages/queries-aggregations/pagination.adoc @@ -0,0 +1,185 @@ +[[pagination]] += Pagination +:page-aliases: pagination/index.adoc, pagination/offset-based.adoc, pagination/cursor-based.adoc, queries-aggregation/pagination/index.adoc, queries-aggregation/pagination/offset-based.adoc, queries-aggregation/pagination/cursor-based.adoc + + +The Neo4j GraphQL Library offers two mechanisms for pagination: + +* Offset-based pagination - Pagination based on offsets, often associated with navigation via pages. +* Cursor-based pagination - Pagination based on cursors, often associated with infinitely-scrolling applications. + + +[[pagination-offset-based]] +== Offset-based pagination + +Offset-based pagination, often associated with navigation via pages, can be achieved through the use of the `offset` and `limit` options available when querying for data. + +Using the following type definition: + +[source, graphql, indent=0] +---- +type User @node { + name: String! +} +---- + +Fetch the first page of 10 by executing: + +[source, graphql, indent=0] +---- +query { + users(limit: 10) { + name + } +} +---- + +And then on subsequent calls, introduce the `offset` argument and increment it by 10 on each call. + +Fetch the second page with: + +[source, graphql, indent=0] +---- +query { + users(offset: 10, limit: 10) { + name + } +} +---- + +Fetch the third page with: + +[source, graphql, indent=0] +---- +query { + users(offset: 20, limit: 10) { + name + } +} +---- + +And so on. + + +=== Total number of pages + +You can fetch the total number of records for a certain type using its count query, and then divide that number by your entries per page in order to calculate the total number of pages. +This determines what the last page is, and whether there is a next page. + +See xref::queries-aggregations/queries.adoc[Count] queries for details on how to execute these queries. + + +=== Paginating relationship fields + +Say that in addition to the `User` type above, there is also a `Post` type which a `User` has many of. +You can also fetch a `User` and then paginate through their posts: + +[source, graphql, indent=0] +---- +query { + users(where: { + name_EQ: "Billy" + }) { + name + posts(offset: 20, limit: 10) { + content + } + } +} +---- + + +[[pagination-cursor-based]] +== Cursor-based pagination + +On relationship fields, you are able to take advantage of cursor-based pagination, which is often associated with infinitely-scrolling applications. + +Using the following type definition: + +[source, graphql, indent=0] +---- +type User @node { + name: String! + posts: [Post!]! @relationship(type: "HAS_POST", direction: OUT) +} + +type Post @node { + content: String! +} +---- + +If you wanted to fetch the posts of user "John Smith" 10 at a time, you would first fetch 10: + +[source, graphql, indent=0] +---- +query { + users(where: { name_EQ: "John Smith" }) { + name + postsConnection(first: 10) { + edges { + node { + content + } + } + pageInfo { + endCursor + hasNextPage + } + } + } +} +---- + +In the return value, if `hasNextPage` is `true`, you would pass `endCursor` into the next query of 10. +You can do this with a variable, for example, `$after` in the following query: + +[source, graphql, indent=0] +---- +query Users($after: String) { + users(where: { name_EQ: "John Smith" }) { + name + postsConnection(first: 10, after: $after) { + edges { + node { + content + } + } + pageInfo { + endCursor + hasNextPage + } + } + } +} +---- + +You may continue until `hasNextPage` is `false` in the return - this is when you have reached the end of the data. + + +=== `totalCount` + +The Connection fields also offer a `totalCount` field which can be used to calculate page numbers. +This is useful if you want to paginate by cursor but use page numbers in your application. + +Add the `totalCount` field which returns the total number of results matching the filter used, for example: + +[source, graphql, indent=0] +---- +query Users($after: String) { + users(where: { name_EQ: "John Smith" }) { + name + postsConnection(first: 10) { + edges { + node { + content + } + } + pageInfo { + endCursor + hasNextPage + } + totalCount + } + } +} +---- diff --git a/modules/ROOT/pages/queries-aggregations/pagination/cursor-based.adoc b/modules/ROOT/pages/queries-aggregations/pagination/cursor-based.adoc deleted file mode 100644 index f0b41bdf..00000000 --- a/modules/ROOT/pages/queries-aggregations/pagination/cursor-based.adoc +++ /dev/null @@ -1,91 +0,0 @@ -[[pagination-cursor-based]] -= Cursor-based pagination -:page-aliases: pagination/cursor-based.adoc - - -On relationship fields, you are able to take advantage of cursor-based pagination, which is often associated with infinitely-scrolling applications. - -Using the following type definition: - -[source, graphql, indent=0] ----- -type User @node { - name: String! - posts: [Post!]! @relationship(type: "HAS_POST", direction: OUT) -} - -type Post @node { - content: String! -} ----- - -If you wanted to fetch the posts of user "John Smith" 10 at a time, you would first fetch 10: - -[source, graphql, indent=0] ----- -query { - users(where: { name_EQ: "John Smith" }) { - name - postsConnection(first: 10) { - edges { - node { - content - } - } - pageInfo { - endCursor - hasNextPage - } - } - } -} ----- - -In the return value, if `hasNextPage` is `true`, you would pass `endCursor` into the next query of 10. You might do this using a variable as in the following example: - -[source, graphql, indent=0] ----- -query Users($after: String) { - users(where: { name_EQ: "John Smith" }) { - name - postsConnection(first: 10, after: $after) { - edges { - node { - content - } - } - pageInfo { - endCursor - hasNextPage - } - } - } -} ----- - -You would continue doing this until `hasNextPage` if `false` - this is when you have reached the end of the data. - -== `totalCount` - -The Connection fields also offer a `totalCount` field which can be used to calculate page numbers, which is useful if you want to page by cursors but use page number in your application. Using the example above, you would simply add the `totalCount` field which will return the total number of results matching the filter used, which in this example would just be all posts: - -[source, graphql, indent=0] ----- -query Users($after: String) { - users(where: { name_EQ: "John Smith" }) { - name - postsConnection(first: 10) { - edges { - node { - content - } - } - pageInfo { - endCursor - hasNextPage - } - totalCount - } - } -} ----- diff --git a/modules/ROOT/pages/queries-aggregations/pagination/index.adoc b/modules/ROOT/pages/queries-aggregations/pagination/index.adoc deleted file mode 100644 index 6d0bedc6..00000000 --- a/modules/ROOT/pages/queries-aggregations/pagination/index.adoc +++ /dev/null @@ -1,9 +0,0 @@ -[[pagination]] -= Pagination -:page-aliases: pagination/index.adoc - - -The Neo4j GraphQL Library offers two mechanisms for pagination: - -- xref::/queries-aggregations/pagination/offset-based.adoc[Offset-based pagination] - Pagination based on offsets, often associated with navigation via pages. -- xref::/queries-aggregations/pagination/cursor-based.adoc[Cursor-based pagination] - Pagination based on cursors, often associated with infinitely-scrolling applications. diff --git a/modules/ROOT/pages/queries-aggregations/pagination/offset-based.adoc b/modules/ROOT/pages/queries-aggregations/pagination/offset-based.adoc deleted file mode 100644 index 9cc6ac91..00000000 --- a/modules/ROOT/pages/queries-aggregations/pagination/offset-based.adoc +++ /dev/null @@ -1,75 +0,0 @@ -[[pagination-offset-based]] -= Offset-based pagination -:page-aliases: pagination/offset-based.adoc - -Offset-based pagination, often associated with navigation via pages, can be achieved through the use of the `offset` and `limit` options available when querying for data. - -Using the following type definition: - -[source, graphql, indent=0] ----- -type User @node { - name: String! -} ----- - -You would fetch the first "page" of 10 by executing: - -[source, graphql, indent=0] ----- -query { - users(limit: 10) { - name - } -} ----- - -And then on subsequent calls, introduce the `offset` argument and increment it by 10 on each call. - -*Page 2:* - -[source, graphql, indent=0] ----- -query { - users(offset: 10, limit: 10) { - name - } -} ----- - -*Page 3:* - -[source, graphql, indent=0] ----- -query { - users(offset: 20, limit: 10) { - name - } -} ----- - -And so on, so forth. - -== Total number of pages - -You can fetch the total number of records for a certain type using its count query, and then divide that number by your entries per page in order to calculate the total number of pages. This will allow to to determine what the last page is, and whether there is a next page. - -See xref::queries-aggregations/queries.adoc[Count] queries for details on how to execute these queries. - -== Paginating relationship fields - -Say that in addition to the `User` type above, there is also a `Post` type which a `User` has many of. You can also fetch a `User` and then paginate through their posts: - -[source, graphql, indent=0] ----- -query { - users(where: { - name_EQ: "Billy" - }) { - name - posts(offset: 20, limit: 10) { - content - } - } -} ----- diff --git a/modules/ROOT/pages/security/authorization.adoc b/modules/ROOT/pages/security/authorization.adoc index 20e3ddc8..930ab609 100644 --- a/modules/ROOT/pages/security/authorization.adoc +++ b/modules/ROOT/pages/security/authorization.adoc @@ -21,6 +21,9 @@ Instead, use xref::/security/subscriptions-authorization.adoc[`@subscriptionsAut Filtering rules filter out data which users do not have access to, without throwing any errors. These rules are translated into filtering predicates, which are evaluated against matched data in the database. +Filters for such rules work just like filters for queries and aggregations. +Refer to xref:filtering.adoc[]. + Filtering rules protect data as well as obfuscate the information on the _existence_ of that data to unauthorized users. For instance, here is how to filter out `Post` nodes which don't belong to the current `User`: diff --git a/modules/ROOT/pages/types/scalar.adoc b/modules/ROOT/pages/types/scalar.adoc index ea9b4400..a5fe1bd6 100644 --- a/modules/ROOT/pages/types/scalar.adoc +++ b/modules/ROOT/pages/types/scalar.adoc @@ -24,7 +24,7 @@ type Person @node { .2+| `BigInt` | Supports up to 64 bit integers, serialized as strings in variables and in data responses. -Shares the same xref::queries-aggregations/filtering.adoc#_numerical_operators[Numerical operators] as the other numeric types. +Shares the same xref::filtering.adoc#_numerical_operators[Numerical operators] as the other numeric types. a| [source, graphql, indent=0] ---- diff --git a/modules/ROOT/pages/types/spatial.adoc b/modules/ROOT/pages/types/spatial.adoc index 81fae7ed..62e65899 100644 --- a/modules/ROOT/pages/types/spatial.adoc +++ b/modules/ROOT/pages/types/spatial.adoc @@ -25,7 +25,7 @@ type TypeWithPoint @node { The `Point` type is automatically added to your schema, in addition to the input and output types that you need to query and manipulate spatial types through your API. -See xref::queries-aggregations/filtering.adoc#_filtering_spatial_types[Filtering spatial types] for filter options. +See xref::filtering.adoc#_filtering_spatial_types[Filtering spatial types] for filter options. ==== Type definition @@ -100,7 +100,7 @@ type TypeWithCartesianPoint @node { The `CartesianPoint` type is automatically added to your schema, in addition to the input and output types that you need to query and manipulate spatial types through your API. -See xref::queries-aggregations/filtering.adoc#_filtering_spatial_types[Filtering spatial types] for filter options. +See xref::filtering.adoc#_filtering_spatial_types[Filtering spatial types] for filter options. ==== Type definition