> ## Documentation Index
> Fetch the complete documentation index at: https://www.nestjs-query.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Aggregations

> When aggregations are enabled  will expose a new query that enables using the following common aggregations , , , , and .

> [!NOTE]
>
> Only fields decorated with `@FilterableField` will be exposed in aggregate queries.

All examples will be based on the following `TodoItem` DTO. All fields except `age`, because it is not decorated with `@FilterableField` or `@IDField`, will be exposed in aggregate queries.

```ts todo-item/dto/todo-item.dto.ts theme={null}
import { FilterableField, IDField } from '@ptc-org/nestjs-query-graphql'
import { ObjectType, ID, GraphQLISODateTime, Field } from '@nestjs/graphql'

@ObjectType('TodoItem')
export class TodoItemDTO {

  @IDField(() => ID)
  id!: number

  @FilterableField()
  title!: string

  @FilterableField({ nullable: true })
  description?: string

  @FilterableField()
  completed!: boolean

  @FilterableField(() => GraphQLISODateTime)
  created!: Date

  @FilterableField(() => GraphQLISODateTime)
  updated!: Date

  @Field()
  age!: number

  @FilterableField()
  priority!: number
}
```

### Enabling Aggregate Queries[​](#enabling-aggregate-queries "Direct link to Enabling Aggregate Queries")

To enable aggregate queries you can set the `enableAggregate` option in your resolver

```ts todo-item/todo-item.module.ts theme={null}
import { NestjsQueryGraphQLModule } from '@ptc-org/nestjs-query-graphql'
import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm'
import { Module } from '@nestjs/common'
import { TodoItemInputDTO } from './dto/todo-item-input.dto'
import { TodoItemUpdateDTO } from './dto/todo-item-update.dto'
import { TodoItemDTO } from './dto/todo-item.dto'
import { TodoItemEntity } from './todo-item.entity'

@Module({
  imports: [
    NestjsQueryGraphQLModule.forFeature({
      imports: [NestjsQueryTypeOrmModule.forFeature([TodoItemEntity])],
      resolvers: [
        {
          DTOClass: TodoItemDTO,
          EntityClass: TodoItemEntity,
          CreateDTOClass: TodoItemInputDTO,
          UpdateDTOClass: TodoItemUpdateDTO,
          enableAggregate: true
        }
      ]
    })
  ]
})
export class TodoItemModule {}
```

All aggregate queries use the following naming convention `${objectName}Aggregate`.

Below is a fragment from the generated schema for `TodoItem`

> [!NOTE]
>
> `nestjs-query` will only expose number fields for `avg` and `sum`.

```graphql theme={null}
type Query {
  todoItem(id: ID!): TodoItem
  todoItems(paging: CursorPaging = { first: 10 }, filter: TodoItemFilter = {}, sorting: [TodoItemSort!] = []): TodoItemConnection!
  todoItemAggregate(filter: TodoItemAggregateFilter): [TodoItemAggregateResponse!]!
}
input TodoItemAggregateFilter {
  and: [TodoItemAggregateFilter!]
  or: [TodoItemAggregateFilter!]
  id: IDFilterComparison
  title: StringFieldComparison
  description: StringFieldComparison
  completed: BooleanFieldComparison
  created: DateFieldComparison
  updated: DateFieldComparison
  priority: NumberFieldComparison
}
type TodoItemAggregateResponse {
  groupBy: TodoItemAggregateGroupBy
  count: TodoItemCountAggregate
  sum: TodoItemSumAggregate
  avg: TodoItemAvgAggregate
  min: TodoItemMinAggregate
  max: TodoItemMaxAggregate
}
type TodoItemAvgAggregate {
  id: Float
  priority: Float
}
type TodoItemAggregateGroupBy {
  id: ID
  title: String
  description: String
  completed: Boolean
  created(by: GroupBy = DAY): DateTime
  updated(by: GroupBy = DAY): DateTime
  priority: Float
  createdBy: String
  updatedBy: String
}
type TodoItemCountAggregate {
  id: Int
  title: Int
  description: Int
  completed: Int
  created: Int
  updated: Int
  priority: Int
}
type TodoItemMaxAggregate {
  id: ID
  title: String
  description: String
  created: DateTime
  updated: DateTime
  priority: Float
}
type TodoItemMinAggregate {
  id: ID
  title: String
  description: String
  created: DateTime
  updated: DateTime
  priority: Float
}
type TodoItemSumAggregate {
  id: Float
  priority: Float
}
```

## Examples[​](#examples "Direct link to Examples")

### Basic[​](#basic "Direct link to Basic")

> [tab] GraphQL
>
> ```graphql theme={null}
> {
>   todoItemAggregate {
>     count {
>       id
>     }
>     sum {
>       id
>     }
>     avg {
>       id
>     }
>     min {
>       id
>       title
>       created
>     }
>     max {
>       id
>       title
>       created
>     }
>   }
> }
> ```

> [tab] Response
>
> ```json theme={null}
> {
>   "data": {
>     "todoItemAggregate": [
>       {
>         "count": {
>           "id": 5
>         },
>         "sum": {
>           "id": 15
>         },
>         "avg": {
>           "id": 3
>         },
>         "min": {
>           "id": "1",
>           "title": "Add Todo Item Resolver",
>           "created": "2021-03-29T06:51:26.061Z"
>         },
>         "max": {
>           "id": "5",
>           "title": "How to create item With Sub Tasks",
>           "created": "2021-03-29T06:51:26.061Z"
>         }
>       }
>     ]
>   }
> }
> ```

### With GroupBy[​](#with-groupby "Direct link to With GroupBy")

To group your aggregate queries you can add a `groupBy` to specify one or more fields to group on.

> [tab] GraphQL
>
> ```graphql theme={null}
> {
>   todoItemAggregate {
>     groupBy {
>       completed
>     }
>     count {
>       id
>     }
>     sum {
>       id
>     }
>     avg {
>       id
>     }
>     min {
>       id
>       title
>       created
>     }
>     max {
>       id
>       title
>       created
>     }
>   }
> }
> ```

> [tab] Response
>
> ```json theme={null}
> {
>   "data": {
>     "todoItemAggregate": [
>       {
>         "groupBy": {
>           "completed": false
>         },
>         "count": {
>           "id": 4
>         },
>         "sum": {
>           "id": 14
>         },
>         "avg": {
>           "id": 3.5
>         },
>         "min": {
>           "id": "2",
>           "title": "Add Todo Item Resolver",
>           "created": "2021-03-29T06:51:26.061Z"
>         },
>         "max": {
>           "id": "5",
>           "title": "How to create item With Sub Tasks",
>           "created": "2021-03-29T06:51:26.061Z"
>         }
>       },
>       {
>         "groupBy": {
>           "completed": true
>         },
>         "count": {
>           "id": 1
>         },
>         "sum": {
>           "id": 1
>         },
>         "avg": {
>           "id": 1
>         },
>         "min": {
>           "id": "1",
>           "title": "Create Nest App",
>           "created": "2021-03-29T06:51:26.061Z"
>         },
>         "max": {
>           "id": "1",
>           "title": "Create Nest App",
>           "created": "2021-03-29T06:51:26.061Z"
>         }
>       }
>     ]
>   }
> }
> ```

### With Filter[​](#with-filter "Direct link to With Filter")

You can also provide a filter to only aggregate on a subset of data.

> [tab] GraphQL
>
> ```graphql theme={null}
> {
>   todoItemAggregate(filter: { completed: { is: false } }) {
>     count {
>       id
>     }
>     min {
>       id
>       title
>       created
>     }
>     max {
>       id
>       title
>       created
>     }
>   }
> }
> ```

> [tab] Response
>
> ```json theme={null}
> {
>   "data": {
>     "todoItemAggregate": [
>       {
>         "count": {
>           "id": 4
>         },
>         "min": {
>           "id": "2",
>           "title": "Add Todo Item Resolver",
>           "created": "2021-03-29T06:51:26.061Z"
>         },
>         "max": {
>           "id": "5",
>           "title": "How to create item With Sub Tasks",
>           "created": "2021-03-29T06:51:26.061Z"
>         }
>       }
>     ]
>   }
> }
> ```

When using the `count` aggregate only non-null fields will be counted.

For example assume description is null for all todo items you will get `0` back.

> [tab] GraphQL
>
> ```graphql theme={null}
> {
>   todoItemAggregate(filter: { completed: { is: false } }) {
>     count {
>       id
>       title
>       description
>     }
>   }
> }
> ```

> [tab] Response
>
> ```json theme={null}
> {
>  "data": {
>    "todoItemAggregate": [
>      {
>        "count": {
>          "id": 4,
>          "title": 4,
>          "description": 0
>        }
>      }
>    ]
>  }
> }
> ```

## Aggregating Relations[​](#aggregating-relations "Direct link to Aggregating Relations")

When using the `enableAggregate` option any defined `many` relations will also expose a aggregate query `{relationName}Aggregate`

Building on the previous example assume `TodoItem` has a `subTasks` connection.

The following schema fragment will be created

```graphql theme={null}
type TodoItem {
  id: ID!
  title: String!
  description: String
  completed: Boolean!
  created: DateTime!
  updated: DateTime!
  age: Float!
  priority: Float!
  subTasks(
    paging: CursorPaging = { first: 10 }
    filter: SubTaskFilter = {}
    sorting: [SubTaskSort!] = []
  ): TodoItemSubTasksConnection!
  subTasksAggregate(filter: SubTaskAggregateFilter): [TodoItemSubTasksAggregateResponse!]!
}
type TodoItemSubTasksAggregateResponse {
  groupBy: TodoItemSubTasksAggregateGroupBy
  count: TodoItemSubTasksCountAggregate
  sum: TodoItemSubTasksSumAggregate
  avg: TodoItemSubTasksAvgAggregate
  min: TodoItemSubTasksMinAggregate
  max: TodoItemSubTasksMaxAggregate
}
type TodoItemSubTasksAggregateGroupBy {
  id: ID
  title: String
  description: String
  completed: Boolean
  created: DateTime
  updated: DateTime
  todoItemId: String
  createdBy: String
  updatedBy: String
}
type TodoItemSubTasksAvgAggregate {
  id: Float
}
type TodoItemSubTasksCountAggregate {
  id: Int
  title: Int
  description: Int
  completed: Int
  created: Int
  updated: Int
  todoItemId: Int
}
type TodoItemSubTasksMaxAggregate {
  id: ID
  title: String
  description: String
  created: DateTime
  updated: DateTime
  todoItemId: String
}
type TodoItemSubTasksMinAggregate {
  id: ID
  title: String
  description: String
  created: DateTime
  updated: DateTime
  todoItemId: String
}
type TodoItemSubTasksSumAggregate {
  id: Float
}
```

## Examples[​](#examples-1 "Direct link to Examples")

### Basic[​](#basic-1 "Direct link to Basic")

In this example we'll aggregate on all related `subTasks`.

> [tab] GraphQL
>
> ```graphql theme={null}
> {
>   todoItem(id: 5) {
>     subTasksAggregate {
>       count {
>         id
>       }
>       sum {
>         id
>       }
>       avg {
>         id
>       }
>       min {
>         id
>         title
>       }
>       max {
>         id
>         title
>       }
>     }
>   }
> }
> ```

> [tab] Response
>
> ```json theme={null}
> {
>  "data": {
>    "todoItem": {
>      "subTasksAggregate": [
>        {
>          "count": {
>            "id": 3
>          },
>          "sum": {
>            "id": 42
>          },
>          "avg": {
>            "id": 14
>          },
>          "min": {
>            "id": "13",
>            "title": "How to create item With Sub Tasks - Sub Task 1"
>          },
>          "max": {
>            "id": "15",
>            "title": "How to create item With Sub Tasks - Sub Task 3"
>          }
>        }
>      ]
>    }
>  }
> }
> ```

### With GroupBy[​](#with-groupby-1 "Direct link to With GroupBy")

In this example we'll aggregate on all related `subTasks` and group by `completed`.

> [tab] GraphQL
>
> ```graphql theme={null}
> {
>   todoItem(id: 5) {
>     subTasksAggregate {
>       groupBy {
>         completed
>       }
>       count {
>         id
>       }
>       sum {
>         id
>       }
>       avg {
>         id
>       }
>       min {
>         id
>         title
>       }
>       max {
>         id
>         title
>       }
>     }
>   }
> }
> ```

> [tab] Response
>
> ```json theme={null}
> {
>  "data": {
>    "todoItem": {
>      "subTasksAggregate": [
>        {
>          "groupBy": {
>            "completed": false
>          },
>          "count": {
>            "id": 2
>          },
>          "sum": {
>            "id": 29
>          },
>          "avg": {
>            "id": 14.5
>          },
>          "min": {
>            "id": "14",
>            "title": "How to create item With Sub Tasks - Sub Task 2"
>          },
>          "max": {
>            "id": "15",
>            "title": "How to create item With Sub Tasks - Sub Task 3"
>          }
>        },
>        {
>          "groupBy": {
>            "completed": true
>          },
>          "count": {
>            "id": 1
>          },
>          "sum": {
>            "id": 13
>          },
>          "avg": {
>            "id": 13
>          },
>          "min": {
>            "id": "13",
>            "title": "How to create item With Sub Tasks - Sub Task 1"
>          },
>          "max": {
>            "id": "13",
>            "title": "How to create item With Sub Tasks - Sub Task 1"
>          }
>        }
>      ]
>    }
>  }
> }
> ```

### With Filter[​](#with-filter-1 "Direct link to With Filter")

This example will aggregate all related `subTasks` that are not completed.

> [tab] GraphQL
>
> ```graphql theme={null}
> {
>   todoItem(id: 5) {
>     subTasksAggregate(filter: { completed: { is: false } }) {
>       count {
>         id
>       }
>       min {
>         id
>         title
>       }
>       max {
>         id
>         title
>       }
>     }
>   }
> }
> ```

> [tab] Response
>
> ```json theme={null}
> {
>  "data": {
>    "todoItem": {
>      "subTasksAggregate": [
>        {
>          "count": {
>            "id": 2
>          },
>          "min": {
>            "id": "14",
>            "title": "How to create item With Sub Tasks - Sub Task 2"
>          },
>          "max": {
>            "id": "15",
>            "title": "How to create item With Sub Tasks - Sub Task 3"
>          }
>        }
>      ]
>    }
>  }
> }
> ```

## Advanced[​](#advanced "Direct link to Advanced")

### Enabling Aggregates Only For Root[​](#enabling-aggregates-only-for-root "Direct link to Enabling Aggregates Only For Root")

When using the `enableAggregate` option it will enable aggregates on the root type as well as all relations. If you only want to expose aggregate functionality on the root type you can specify the `aggregate` option.

```ts theme={null}
import { NestjsQueryGraphQLModule } from '@ptc-org/nestjs-query-graphql'
import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm'
import { Module } from '@nestjs/common'
import { TodoItemInputDTO } from './dto/todo-item-input.dto'
import { TodoItemUpdateDTO } from './dto/todo-item-update.dto'
import { TodoItemDTO } from './dto/todo-item.dto'
import { TodoItemEntity } from './todo-item.entity'

@Module({
  imports: [
    NestjsQueryGraphQLModule.forFeature({
      imports: [NestjsQueryTypeOrmModule.forFeature([TodoItemEntity])],
      resolvers: [
        {
          DTOClass: TodoItemDTO,
          EntityClass: TodoItemEntity,
          CreateDTOClass: TodoItemInputDTO,
          UpdateDTOClass: TodoItemUpdateDTO,
          aggregate: { enabled: true }
        }
      ]
    })
  ]
})
export class TodoItemModule {}
```

### Disable Aggregate for Single Relation[​](#disable-aggregate-for-single-relation "Direct link to Disable Aggregate for Single Relation")

You can also selectively disable aggregates on an individual relation by specifying the enableAggregate option when defining the relation.

```ts theme={null}
import { FilterableField, FilterableConnection, IDField } from '@ptc-org/nestjs-query-graphql'
import { ObjectType, ID, GraphQLISODateTime, Field } from '@nestjs/graphql'
import { SubTaskDTO } from '../../sub-task/dto/sub-task.dto'

@ObjectType('TodoItem')
@FilterableConnection('subTasks', () => SubTaskDTO, { enableAggregate: false })
export class TodoItemDTO {

  @IDField(() => ID)
  id!: number

  @FilterableField()
  title!: string

  @FilterableField({ nullable: true })
  description?: string

  @FilterableField()
  completed!: boolean

  @FilterableField(() => GraphQLISODateTime)
  created!: Date

  @FilterableField(() => GraphQLISODateTime)
  updated!: Date

  @Field()
  age!: number

  @FilterableField()
  priority!: number
}
```

### Group aggregate on DAY/WEEK/MONTH[​](#group-aggregate-on-dayweekmonth "Direct link to Group aggregate on DAY/WEEK/MONTH")

> [!WARNING]
>
> This functionality only works for typeorm!

You can change how datetime fields are grouped by passing `WEEK`, `MONTH` or `YEAR` to the date fields `by`.

```graphql theme={null}
{
  todoItemAggregate {
    groupBy {
      created(by: MONTH)
    }
    count {
      id
    }
    sum {
      id
    }
  }
}
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.