Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
.scala_dependencies
.settings
.shell_history
.vscode/
Thumbs.db
\#*
bin/teamcity/
Expand Down
166 changes: 114 additions & 52 deletions modules/ROOT/pages/queries-aggregations/filtering.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ All types can be tested for either equality.
For non-equality, you *must* use the xref:/queries-aggregations/filtering.adoc#_combining_operators[`NOT`] logical operator.
For example:

.Filtering all Users named John
.Filtering all users named John
[source, graphql, indent=0]
----
query {
Expand All @@ -37,7 +37,7 @@ These are the operators available for numeric (`Int`, `Float`, xref::/types/scal

Here is an example of how to use them:

.Filtering Users younger than 50 years old
.Filtering users younger than 50 years old
[source, graphql, indent=0]
----
query {
Expand All @@ -50,10 +50,66 @@ query {
----

Spatial types use numerical filtering differently and they also have additional options.
See xref::/types/spatial.adoc#_filtering[Spatial types filtering] for more information.
See xref:filtering.adoc#_spatial_types[Spatial types] 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:
== Logical operators

All operators can be combined using the logical operators `AND`, `OR`, and `NOT`.
They can also be standalone operators, which means that they can be used as such and not be appended to field names.

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.

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]
----
query {
actors(where: {
AND: [
{
OR: [
{ name_CONTAINS: "Keanu" },
{ NOT: { name_ENDS_WITH: "Pantoliano" } }
]
},
{
movies_SOME: { title: "The Matrix" }
}
]}
) {
name
movies {
title
}
}
}
----


== String comparison

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
}
}
----

Additionally, numerical operators can be used for String comparisons.
They are disabled default.
To enable them, add them in the `filters` features options for `String`:

[source, javascript, indent=0]
----
Expand Down Expand Up @@ -85,28 +141,6 @@ const features = {
const neoSchema = new Neo4jGraphQL({ features, typeDefs, driver });
----


== String comparison

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

The filter `_MATCHES` is also available for comparison of `String` and `ID` types.
Expand Down Expand Up @@ -178,39 +212,67 @@ Conversely, the following operator is available on array fields, and accepts a s

These operators are available for all types apart from `Boolean`.

== Logical operators
== Filtering spatial types

All operators can be combined using the logical operators `AND`, `OR`, and `NOT`.
They can also be standalone operators, which means that they can be used as such and not be appended to field names.
Both the `Point` and the `CartesianPoint` types use xref::queries-aggregations/filtering.adoc#_numerical_operators[numerical operators] and have an additional `_DISTANCE` filter.
Here is a list of what each filter does for the two types:

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.
* `_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.
* `_LTE`: checks if a point is less than or equal to the distance in the `distance` field away (in meters) from the point specified by the `point` field.
* `_DISTANCE`: checks if a point is the exact distance in the `distance` field away (in meters) from the point specified by the `point` field.
* `_GT`: checks if a point is greater than the distance in the `distance` field away (in meters) from the point specified by the `point` field.
* `_GTE`: checks if a point is greater than or equal to the distance in the `distance` field away (in meters) from the point specified by the `point` field.

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:
For a `Point` type, all filters take the following type as an argument:

[source, graphql, indent=0]
----
query {
actors(where: {
AND: [
{
OR: [
{ name_CONTAINS: "Keanu" },
{ NOT: { name_ENDS_WITH: "Pantoliano" } }
]
},
{
movies_SOME: { title: "The Matrix" }
}
]}
) {
input PointDistance {
point: Point!
distance: Float!
}
----

In practice, you can construct queries like the following, which finds all users within a 5km (5000m) radius of a `Point`:

[source, graphql, indent=0]
----
query CloseByUsers($longitude: Float!, $latitude: Float!) {
users(where: { location_LTE: { point: { longitude: $longitude, latitude: $latitude }, distance: 5000 } }) {
name
movies {
title
location {
longitude
latitude
}
}
}
----

Similarly, for a `CartesianPoint` type, all filters take the following type as an argument:

[source, graphql, indent=0]
----
input CartesianPointDistance {
point: CartesianPoint!
distance: Float!
}
----

The same query for a `CartesianPoint`:

[source, graphql, indent=0]
----
query CloseByUsers($x: Float!, $y: Float!) {
users(where: { location_LTE: { point: { x: $x, y: $y }, distance: 5000 } }) {
name
location {
x
y
}
}
}
----

== Querying an interface

You can use the `typename_IN` filter to filter interfaces.
Expand Down Expand Up @@ -244,7 +306,7 @@ type Post {
likes: [User!]! @relationship(type: "LIKES", direction: IN)
}
----
=== In the case of `n..1` relationships
=== `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`.
Expand All @@ -270,12 +332,12 @@ query {
}
----

=== In the case of `n..m` relationships
=== `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"`
.Find all users where all of their posts contain search term: `"neo4j"`
[source, graphql, indent=0]
----
query {
Expand All @@ -285,7 +347,7 @@ query {
}
----

.Find all Users where none of their posts contains search term: `"cypher"`
.Find all users where none of their posts contains search term: `"cypher"`
[source, graphql, indent=0]
----
query {
Expand Down
70 changes: 6 additions & 64 deletions modules/ROOT/pages/types/spatial.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ The use of either of these types in a GraphQL schema automatically introduces th

The `Point` type is used to describe the two https://neo4j.com/docs/cypher-manual/current/values-and-types/spatial/#spatial-values-crs-geographic[Geographic coordinate reference systems] supported by Neo4j.

In order to use it in your schema, you quite simply add a field with a type `Point` to any type or types in schema, like the following:
In order to use it in your schema, add a field with a type `Point` to any other type(s) in your schema, like the following:

[source, graphql, indent=0]
----
Expand All @@ -23,9 +23,9 @@ type TypeWithPoint {
}
----

Once this has been done, the `Point` type is automatically added to your schema, in addition to all of the input and output types you need to query and manipulate spatial types through your API.
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.

These are the automatically generated types and how to use them:
See xref::queries-aggregations/filtering.adoc#_filtering_spatial_types[Filtering spatial types] for filter options.

==== Type definition

Expand Down Expand Up @@ -84,48 +84,12 @@ mutation CreateUsers($name: String!, $longitude: Float!, $latitude: Float!) {
}
----

==== Filtering

Besides the xref::queries-aggregations/filtering.adoc#filtering-numerical-operators[Numerical operators], the `Point` type has an additional `_DISTANCE` filter.
Here is a list of what each filter does:

* `_LT`: checks that the specified `Point` field is less than the `distance` away in meters from the `Point` being compared against.
* `_LTE`: checks that the specified `Point` field is less than or equal to the `distance` away in meters from the `Point` being compared against.
* `_DISTANCE`: checks that the specified `Point` field is the exact `distance` away in meters from the `Point` being compared against.
* `_GTE`: checks that the specified `Point` field is greater than the `distance` away in meters from the `Point` being compared against.
* `_GT`: checks that the specified `Point` field is greater than or equal to the `distance` away in meters from the `Point` being compared against.

All of the filters take the following type as an argument:

[source, graphql, indent=0]
----
input PointDistance {
point: Point!
distance: Float!
}
----

In practice, you can construct queries such as the following which can find all users within a 5km (5000m) radius of a `Point`:

[source, graphql, indent=0]
----
query CloseByUsers($longitude: Float!, $latitude: Float!) {
users(where: { location_LTE: { point: { longitude: $longitude, latitude: $latitude }, distance: 5000 } }) {
name
location {
longitude
latitude
}
}
}
----

[[cartesian-point]]
=== `CartesianPoint`

The `CartesianPoint` type is used to describe the two https://neo4j.com/docs/cypher-manual/current/values-and-types/spatial/#spatial-values-crs-cartesian[Cartesian coordinate reference systems] supported by Neo4j.

To use it in the schema, add a field with a type `CartesianPoint` to any type or types, such as in this example:
To use it in your schema, add a field with a type `CartesianPoint` to any type(s), such as in this example:

[source, graphql, indent=0]
----
Expand All @@ -134,9 +98,9 @@ type TypeWithCartesianPoint {
}
----

Once this has been done, the `CartesianPoint` type is automatically added to your schema, in addition to all of the input and output types you will need to query and manipulate spatial types through your API.
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.

These are the automatically generated types and how to use them:
See xref::queries-aggregations/filtering.adoc#_filtering_spatial_types[Filtering spatial types] for filter options.

==== Type definition

Expand All @@ -162,25 +126,3 @@ input CartesianPointInput {
z: Float
}
----

==== Filtering

Besides the xref::queries-aggregations/filtering.adoc#filtering-numerical-operators[Numerical operators], the `CartesianPoint` type has an additional `_DISTANCE` filter.

Here is a list of what each filter does:

* `_LT`: checks that the specified `Point` field is less than the `distance` away from the `CartesianPoint` being compared against, in the units used to specify the points.
* `_LTE`: checks that the specified `Point` field is less than or equal to the `distance` away from the `CartesianPoint` being compared against, in the units used to specify the points.
* `_DISTANCE`: checks that the specified `Point` field is the exact `distance` away from the `CartesianPoint` being compared against, in the units used to specify the points.
* `_GTE`: checks that the specified `Point` field is greater than the `distance` away from the `CartesianPoint` being compared against, in the units used to specify the points.
* `_GT`: checks that the specified `Point` field is greater than or equal to the `distance` away from the `CartesianPoint` being compared against, in the units used to specify the points.

All of the filters take the following type as an argument:

[source, graphql, indent=0]
----
input CartesianPointDistance {
point: CartesianPoint!
distance: Float!
}
----