Skip to content

Commit baf1eef

Browse files
Aggregations section in GraphQL API documentation (#2810)
* Add aggregations section in GraphQL API docs * Add section in GraphQL advanced queries * Fix mistakes * Fix inexistent anchor link/wrong page link --------- Co-authored-by: Pierre Wizla <[email protected]>
1 parent fe1e379 commit baf1eef

File tree

2 files changed

+142
-0
lines changed

2 files changed

+142
-0
lines changed

docusaurus/docs/cms/api/graphql.md

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,119 @@ query Query($status: PublicationStatus) {
425425
}
426426
```
427427
428+
## Aggregations
429+
430+
Aggregations can be used to compute metrics such as counts, sums, or grouped totals without fetching every document individually. Aggregations are exposed through <ExternalLink to="https://www.apollographql.com/docs/technotes/TN0029-relay-style-connections/" text="Relay-style"/> connection queries: every collection type includes an `aggregate` field under its `<plural>_connection` query.
431+
432+
```graphql title="Example: Total restaurants matching a filter"
433+
{
434+
restaurants_connection(filters: { categories: { documentId: { eq: "food-trucks" } } }) {
435+
aggregate {
436+
count
437+
}
438+
}
439+
}
440+
```
441+
442+
Aggregations follow the same filters, locale, publication status, and permissions as the parent query. For example, setting `locale: "fr"` or `status: DRAFT` on the connection limits the aggregation to those documents, and users can only aggregate content they are allowed to read.
443+
444+
The table below lists all supported aggregation operators:
445+
446+
| Operator | Description | Supported field types |
447+
| --- | --- | --- |
448+
| `count` | Returns the number of documents that match the query. | All content-types |
449+
| `avg` | Computes the arithmetic mean per numeric field. | Number, integer, decimal |
450+
| `sum` | Computes the total per numeric field. | Number, integer, decimal |
451+
| `min` | Returns the smallest value per field. | Number, integer, decimal, date, datetime |
452+
| `max` | Returns the largest value per field. | Number, integer, decimal, date, datetime |
453+
| `groupBy` | Buckets results by unique values and exposes nested aggregations for each bucket. | Scalar fields (string, number, boolean, date, datetime), relations |
454+
455+
:::note
456+
Strapi ignores `null` values for `avg`, `sum`, `min`, and `max`. When aggregating relations, the operators run on the target documents and still respect their locales and permissions.
457+
:::
458+
459+
:::info Performance & limits
460+
Aggregations operate server-side, so they are generally faster than downloading and processing large result sets on the client. However, complex `groupBy` trees and wide projections can still be expensive. Use filters to restrict the data set and consider setting up `depthLimit` and `amountLimit` values accordingly (see [available options](/cms/plugins/graphql#available-options)) to protect your API. Errors such as `You are not allowed to perform this action` usually mean the requester lacks the `Read` permission on the target collection.
461+
:::
462+
463+
### Aggregate multiple metrics in one request
464+
465+
Aggregations can be combined so that one network round trip returns several metrics:
466+
467+
```graphql title="Example: Average delivery time and minimum price"
468+
{
469+
restaurants_connection(filters: { takeAway: { eq: true } }) {
470+
aggregate {
471+
avg {
472+
delivery_time
473+
}
474+
min {
475+
price_range
476+
}
477+
max {
478+
price_range
479+
}
480+
}
481+
}
482+
}
483+
```
484+
485+
### Group results
486+
487+
Use `groupBy` to derive grouped metrics while optionally chaining further aggregations inside each group. Each group exposes the unique `key` and a nested connection that can be used for drilling down or counting the grouped items:
488+
489+
```graphql title="Example: Count restaurants per category"
490+
{
491+
restaurants_connection {
492+
aggregate {
493+
groupBy {
494+
categories {
495+
key
496+
connection {
497+
aggregate {
498+
count
499+
}
500+
}
501+
}
502+
}
503+
}
504+
}
505+
}
506+
```
507+
508+
Groups inherit the top-level filters. To further refine a specific group, apply filters on the nested `connection`.
509+
510+
### Combine with pagination and sorting
511+
512+
Aggregations run on the entire result set that matches the query filters, not only on the current page. When a request includes pagination arguments and aggregations, the documents in `nodes` follow the pagination limits, but the values inside `aggregate` ignore `pageSize` or `limit` so they describe the whole set. You can still add sorting to order the documents returned with the aggregation results.
513+
514+
```graphql title="Example: Paginate takeaway restaurants and count all matches"
515+
{
516+
restaurants_connection(
517+
filters: { takeAway: { eq: true } }
518+
pagination: { page: 2, pageSize: 5 }
519+
sort: "name:asc"
520+
) {
521+
nodes {
522+
documentId
523+
name
524+
rating
525+
}
526+
pageInfo {
527+
page
528+
pageSize
529+
total
530+
}
531+
aggregate {
532+
count
533+
avg {
534+
rating
535+
}
536+
}
537+
}
538+
}
539+
```
540+
428541
## Mutations
429542
430543
Mutations in GraphQL are used to modify data (e.g. create, update, and delete data).

docusaurus/docs/cms/api/graphql/advanced-queries.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,32 @@ export default {
5050
```
5151

5252
In this example the parent resolver fetches restaurants using the [Document Service API](/cms/api/document-service), then delegates to the generated `Restaurant` resolver provided by the plugin so default behavior such as field selection still applies.
53+
54+
## Aggregation drilldowns
55+
56+
<ExternalLink to="https://www.apollographql.com/docs/technotes/TN0029-relay-style-connections/" text="Relay-style"/> connections expose an `aggregate` field. You can use it to show high-level metrics and still let users drill into a specific group. Combine `groupBy` with pagination variables to keep responses small:
57+
58+
```graphql
59+
query RestaurantsByCity($first: Int, $after: String) {
60+
restaurants_connection(pagination: { limit: $first, start: $after }) {
61+
aggregate {
62+
groupBy {
63+
city {
64+
key
65+
connection(pagination: { limit: 5 }) {
66+
aggregate {
67+
count
68+
}
69+
nodes {
70+
documentId
71+
name
72+
}
73+
}
74+
}
75+
}
76+
}
77+
}
78+
}
79+
```
80+
81+
Use query variables to adjust the nested pagination when a user selects a group. Strapi runs the aggregation on the server, which is why the client only downloads the summary rows it needs: this keeps dashboards responsive even with large data sets.

0 commit comments

Comments
 (0)