mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-09-19 16:06:32 +02:00
325 lines
6.9 KiB
Markdown
325 lines
6.9 KiB
Markdown
|
---
|
||
|
title: DataObject query plugins
|
||
|
summary: Learn about some of the useful goodies that come pre-packaged with DataObject queries
|
||
|
---
|
||
|
|
||
|
# Working with DataObjects
|
||
|
|
||
|
[CHILDREN asList]
|
||
|
|
||
|
[alert]
|
||
|
You are viewing docs for a pre-release version of silverstripe/graphql (4.x).
|
||
|
Help us improve it by joining #graphql on the [Community Slack](https://www.silverstripe.org/blog/community-slack-channel/),
|
||
|
and report any issues at [github.com/silverstripe/silverstripe-graphql](https://github.com/silverstripe/silverstripe-graphql).
|
||
|
Docs for the current stable version (3.x) can be found
|
||
|
[here](https://github.com/silverstripe/silverstripe-graphql/tree/3)
|
||
|
[/alert]
|
||
|
|
||
|
## DataObject query plugins
|
||
|
|
||
|
This module has a [plugin system](../plugins) that affords extensibility to queries, mutations,
|
||
|
types, fields, and just about every other thread of the schema. Model types can define default
|
||
|
plugins to include, and for DataObject queries, these include:
|
||
|
|
||
|
* filter
|
||
|
* sort
|
||
|
* paginateList
|
||
|
* inheritance
|
||
|
* canView (read, readOne)
|
||
|
* firstResult (readOne)
|
||
|
|
||
|
When the `silverstripe/cms` module is installed, a plugin known as `getByLink` is also added.
|
||
|
Other modules, such as `silverstripe-versioned` may augment that list with even more.
|
||
|
|
||
|
### The pagination plugin
|
||
|
|
||
|
The pagination plugin augments your queries in two main ways:
|
||
|
|
||
|
* Adding `limit` and `offset` arguments
|
||
|
* Wrapping the return type in a "connection" type with the following fields:
|
||
|
* `nodes: '[YourType]'`
|
||
|
* `edges: '[{ node: YourType }]'`
|
||
|
* `pageInfo: '{ hasNextPage: Boolean, hasPreviousPage: Boolean: totalCount: Int }'`
|
||
|
|
||
|
Let's test it out:
|
||
|
|
||
|
```graphql
|
||
|
query {
|
||
|
readPages(limit: 10, offset: 20) {
|
||
|
nodes {
|
||
|
title
|
||
|
}
|
||
|
edges {
|
||
|
node {
|
||
|
title
|
||
|
}
|
||
|
}
|
||
|
pageInfo {
|
||
|
totalCount
|
||
|
hasNextPage
|
||
|
hasPrevPage
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
[notice]
|
||
|
If you're not familiar with the jargon of `edges` and `node`, don't worry too much about it
|
||
|
for now. It's just a pretty well-established convention for pagination in GraphQL, mostly owing
|
||
|
to its frequent use with [cursor-based pagination](https://graphql.org/learn/pagination/), which
|
||
|
isn't something we do in Silverstripe CMS.
|
||
|
[/notice]
|
||
|
|
||
|
#### Disabling pagination
|
||
|
|
||
|
Just set it to `false` in the configuration.
|
||
|
|
||
|
*app/_graphql/models.yml*
|
||
|
```yaml
|
||
|
MyProject\Models\ProductCategory:
|
||
|
operations:
|
||
|
read:
|
||
|
plugins:
|
||
|
paginateList: false
|
||
|
```
|
||
|
|
||
|
To disable pagination globally, use `modelConfig`:
|
||
|
|
||
|
*app/_graphql/modelConfig.yml*
|
||
|
```yaml
|
||
|
DataObject:
|
||
|
operations:
|
||
|
read:
|
||
|
plugins:
|
||
|
paginateList: false
|
||
|
```
|
||
|
|
||
|
### The filter plugin
|
||
|
|
||
|
The filter plugin (`SilverStripe\GraphQL\Schema\DataObject\Plugin\QueryFilter`) adds a
|
||
|
special `filter` argument to the `read` and `readOne` operations.
|
||
|
|
||
|
```yaml
|
||
|
query {
|
||
|
readPages(
|
||
|
filter: { title: { eq: "Blog" } }
|
||
|
) {
|
||
|
nodes {
|
||
|
title
|
||
|
created
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
In the above example, the `eq` is known as a *comparator*. There are several of these
|
||
|
included with the the module, including:
|
||
|
|
||
|
* `eq` (exact match)
|
||
|
* `ne` (not equal)
|
||
|
* `contains` (fuzzy match)
|
||
|
* `gt` (greater than)
|
||
|
* `lt` (less than)
|
||
|
* `gte` (greater than or equal)
|
||
|
* `lte` (less than or equal)
|
||
|
* `in` (in a given list)
|
||
|
* `startswith` (starts with)
|
||
|
* `endswith` (ends with)
|
||
|
|
||
|
Example:
|
||
|
```graphql
|
||
|
query {
|
||
|
readPages (
|
||
|
filter: {
|
||
|
title: { ne: "Home" },
|
||
|
created: { gt: "2020-06-01", lte: "2020-09-01" }
|
||
|
}
|
||
|
) {
|
||
|
nodes {
|
||
|
title
|
||
|
created
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
[notice]
|
||
|
While it is possible to filter using multiple comparators, segmenting them into
|
||
|
disjunctive groups (e.g. "OR" and "AND" clauses) is not yet supported.
|
||
|
[/notice]
|
||
|
|
||
|
Nested fields are supported by default:
|
||
|
|
||
|
```graphql
|
||
|
query {
|
||
|
readProductCategories(
|
||
|
filter: {
|
||
|
products: {
|
||
|
reviews: {
|
||
|
rating: { gt: 3 },
|
||
|
comment: { contains: "awesome" },
|
||
|
author: { ne: "Me" }
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
) {
|
||
|
nodes {
|
||
|
title
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
Filters are only querying against the database by default,
|
||
|
it is not possible to filter by fields with custom resolvers.
|
||
|
|
||
|
#### Customising the filter fields
|
||
|
|
||
|
By default, all fields on the dataobject, including relationships, are included. To customise
|
||
|
this, just add a `fields` config to the plugin definition:
|
||
|
|
||
|
*app/_graphql/models.yml*
|
||
|
```yaml
|
||
|
MyProject\Models\ProductCategory:
|
||
|
fields:
|
||
|
title: true
|
||
|
featured: true
|
||
|
operations:
|
||
|
read:
|
||
|
plugins:
|
||
|
filter:
|
||
|
fields:
|
||
|
title: true
|
||
|
```
|
||
|
|
||
|
#### Disabling the filter plugin
|
||
|
|
||
|
Just set it to `false` in the configuration.
|
||
|
|
||
|
*app/_graphql/models.yml*
|
||
|
```yaml
|
||
|
MyProject\Models\ProductCategory:
|
||
|
operations:
|
||
|
read:
|
||
|
plugins:
|
||
|
filter: false
|
||
|
```
|
||
|
|
||
|
To disable filtering globally, use `modelConfig`:
|
||
|
|
||
|
*app/_graphql/modelConfig.yml*
|
||
|
```yaml
|
||
|
DataObject:
|
||
|
operations:
|
||
|
read:
|
||
|
plugins:
|
||
|
filter: false
|
||
|
```
|
||
|
|
||
|
### The sort plugin
|
||
|
|
||
|
The sort plugin (`SilverStripe\GraphQL\Schema\DataObject\Plugin\QuerySort`) adds a
|
||
|
special `sort` argument to the `read` and `readOne` operations.
|
||
|
|
||
|
```graphql
|
||
|
query {
|
||
|
readPages (
|
||
|
sort: { created: DESC }
|
||
|
) {
|
||
|
nodes {
|
||
|
title
|
||
|
created
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
Nested fields are supported by default, but only for linear relationships (e.g `has_one`):
|
||
|
|
||
|
```graphql
|
||
|
query {
|
||
|
readProducts(
|
||
|
sort: {
|
||
|
primaryCategory: {
|
||
|
lastEdited: DESC
|
||
|
}
|
||
|
}
|
||
|
) {
|
||
|
nodes {
|
||
|
title
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
|
||
|
#### Customising the sort fields
|
||
|
|
||
|
By default, all fields on the dataobject, including `has_one` relationships, are included.
|
||
|
To customise this, just add a `fields` config to the plugin definition:
|
||
|
|
||
|
*app/_graphql/models.yml*
|
||
|
```yaml
|
||
|
MyProject\Models\ProductCategory:
|
||
|
fields:
|
||
|
title: true
|
||
|
featured: true
|
||
|
operations:
|
||
|
read:
|
||
|
plugins:
|
||
|
sort:
|
||
|
fields:
|
||
|
title: true
|
||
|
```
|
||
|
|
||
|
#### Disabling the sort plugin
|
||
|
|
||
|
Just set it to `false` in the configuration.
|
||
|
|
||
|
*app/_graphql/models.yml*
|
||
|
```yaml
|
||
|
MyProject\Models\ProductCategory:
|
||
|
operations:
|
||
|
read:
|
||
|
plugins:
|
||
|
sort: false
|
||
|
```
|
||
|
|
||
|
To disable sort globally, use `modelConfig`:
|
||
|
|
||
|
*app/_graphql/modelConfig.yml*
|
||
|
```yaml
|
||
|
DataObject:
|
||
|
operations:
|
||
|
read:
|
||
|
plugins:
|
||
|
sort: false
|
||
|
```
|
||
|
|
||
|
### The getByLink plugin
|
||
|
|
||
|
When the `silverstripe/cms` module is installed (it is in most cases), a plugin called `getByLink`
|
||
|
will ensure that queries that return a single DataObject model (e.g. readOne) get a new filter argument
|
||
|
called `link` (configurable on the `field_name` property of `LinkablePlugin`).
|
||
|
|
||
|
When the `filter` plugin is also activated for the query (it is by default for readOne), the `link` field will be added to the filter
|
||
|
input type. Note that all other filters won't apply in this case, as `link`, like `id`, is exclusive
|
||
|
by definition.
|
||
|
|
||
|
If the `filter` plugin is not activated for the query, a new `link` argument will be added to the query
|
||
|
on its own.
|
||
|
|
||
|
With the standard `filter` plugin applied:
|
||
|
```graphql
|
||
|
readOneSiteTree(filter: { link: "/about-us" }) {
|
||
|
title
|
||
|
}
|
||
|
```
|
||
|
|
||
|
When the `filter` plugin is disabled:
|
||
|
```graphql
|
||
|
readOneSiteTree(link: "/about-us" ) {
|
||
|
title
|
||
|
}
|
||
|
```
|
||
|
|
||
|
### Further reading
|
||
|
|
||
|
[CHILDREN]
|