> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cognite.com/llms.txt
> Use this file to discover all available pages before exploring further.

# GraphQL queries

> Learn how to query instances using GraphQL including list, get, search, and aggregate operations.

## Overview

You can query the instances with [GraphQL](https://graphql.org/learn). The query capabilities of the GraphQL API interface represent a subset of the capabilities available from the DMS [query](/cdf/dm/dm_concepts/dm_querying) endpoints.

A query has these key sections:

* A **query intent** `query MyQueryName {` (or just `{` as shorthand).

* The **query to run**. This can be one of four types of queries (with an optional alias, for example, `myAlias: listActor`):

  * `list<type>`, for example, `listActor` lists based on filter parameters.
  * `get<type>ById`, for example, `getActorById` lists based on filter parameters.
  * `search<type>`, for example, `searchActor` searches based on a query parameter.
  * `aggregate<type>`, for example, `aggregateActor` aggregates (count, average etc.) based on a field.

    See the [query types](#query-types) section for more details.

* The **query parameters**. For example, `filter: {...}` or `limit: 1000`.

* The **properties to return** at a specified depth.

<Warning>
  GraphQL `list` and `getById` queries aren't designed for retrieving large datasets. Refer to [GraphQL list and getbyid queries with subqueries](#graphql-list-and-getbyid-queries-with-subqueries) for more information.
</Warning>

## Endpoint

Send **`POST`** requests with a JSON body in the form `{ "query": "<GraphQL>", "variables": { ... } }` to:

```
https://{cluster}.cognitedata.com/api/v1/projects/{project}/userapis/spaces/{spaceExternalId}/datamodels/{dataModelExternalId}/versions/{dataModelVersion}/graphql
```

`{cluster}` is your CDF API hostname (for example `api` or a regional cluster such as `westeurope-1`). See [IP addresses for the API](/dev/use_the_API#ip-addresses-for-the-api) for more information. `{project}` is your project name. `{spaceExternalId}`, `{dataModelExternalId}`, and `{dataModelVersion}` identify the published data model.

[Authenticate](/cdf/access/concepts/authentication_flows_oidc) with a bearer token.

DML **schema** operations use `.../projects/{project}/dml/graphql` instead. See [DML HTTP endpoint](/cdf/dm/dm_graphql/dm_data_modeling_language#dml-http-endpoint) for details.

## GraphQL example

```graphql wrap theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
query myQuery {
  listCountry {
    items {
      name
      demographics {
        populationSize
        growthRate
      }
      deaths {
        datapoints(limit: 100) {
          timestamp
          value
        }
      }
    }
    pageInfo {
      endCursor
    }
  }
  listDemographics(
    filter: {
      and: [{ populationSize: { gte: 2 } }, { populationSize: { lte: 10 } }]
    }
  ) {
    items {
      populationSize
      growthRate
      metadata {
        key
        value
      }
    }
  }
}
```

Where:

* `myQuery` declares the **query intent**.
* `listCountry` and `listDemographics` are the **queries to run**.
* The **parameters** are `Country`:`100` for the `deaths` time series data points, and the `Demographics`: filter of `populationSize` between 2 and 10.
* The **properties to return**, for `Country`: `items` -> `name`, `demographic` -> `populationSize`, `growthRate`, etc.

For more information, see the [GraphQL documentation](https://graphql.org/learn).

## Query types

Use these basic query types: "list", "getById", "search" and "aggregate".

### `list` queries

`list<type>` lets you filter and sort data quickly. For `list<type>` you can use these
properties and parameters:

* **Properties**

  * `items`: specify the properties to return data for
  * `pageInfo`: details about the current set of returned items and cursors used to paginate to the next page of data.

* **Parameters**

  * `filter`: the filter you want to use based on the `properties` in your graph. You can use `and`, `or`, and `not` operators to create complex queries.
  * `sort`: the ordering of the returned data you want. Specify an array of one or more `properties` to sort the data on, and whether the data should be sorted in `ASC` or `DESC` order.
  * `after`: where in the result set to continue from, using the `endCursor` value from the previous query.
  * `first`: the maximum number of items to return. To fetch more items use a new query, and supply the value from the previous query's `endCursor` parameter. (**Default maximum**: 1000 instances)

#### Pagination

Pagination is only supported at the top level when using `list<type>` queries.

For a query like the one below, cursors will only be returned to paginate through the data returned from `Movies`, but not from `Actors`. If you need to paginate through nested types, for `actors` in this example, use the `get<type>ById` queries instead:

```graphql theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
query ListMovies {
  listMovie {
    items {
      title
      actors {
        name
      }
    }
    pageInfo {
      endCursor
    }
  }
}
```

### `getById` queries

Use `get<type>ById` to fetch a specific item by its `externalId`. For `get<type>ById`, you can use similar properties and parameters as [`list`](#list-queries) queries. Pagination for nested items is available when using `get<type>ById`.

* **Properties**

  * `items`: specify which properties to return.

### `search` queries

Use `search<type>` to search and query data quickly. For `search<type>` you can use these properties and parameters:

* **Properties** - The same as for the [`list`](#list-queries) queries.

* **Parameters**

  * `filter`: the filter you want to provide based on the `properties` in your data model. You can use an array of `and`, `or`, and `not` to create more complex queries.
  * `fields`: the properties you want to search on. This can be an array of `properties`.
  * `query`: the actual search queries. Wildcards are supported.
  * `first`: the maximum number of items to return. To fetch more items, use a new query using the `endCursor` parameter.(**Default**: 1000)

### `aggregate` queries

Use `aggregate<type>` to aggregate data and compute rollups on the instances in a type. For `aggregate<type>`, you can use these properties and parameters:

* **Properties**

  * `group`: depending on the `groupBy` parameter, this indicates the group. The group is the name of each aggregation bucket based on the value(s) of the field(s) used in the `groupBy` parameter.
  * `avg`: for number properties, you can ask for the average.
  * `count`: for any type of properties, you can ask for the total count.
  * `histogram(interval: <number>)`: for number properties, you can ask for the histogram for an interval.
  * `max`: for number properties, you can ask for the maximum value.
  * `min`: for number properties, you can ask for the minimum value.
  * `sum`: for number properties, you can ask for the total sum.
  * `pageInfo`: the details about the current set of returned items. The existence of `endCursor` indicates that there is another page of data.

* **Parameters**

  * `filter`: perform the aggregation on instances matching a logical expression. This filter is applied to the `fields` in your data type as described below, and you can use an array of `and`, `or`, and `not` to create more complex queries. For text field searches other than prefix matching, use `query`.
  * `query`: applies a full-text search to text `fields` in the type and performs the aggregation on instances matching the query and filter. The query is, by default, applied to all text fields in the type, but can be constrained to a subset of the `field`s using the `fields` parameter.
  * `fields`: the properties or fields you want to search in with the `query` search. This can be an array of `field`s.
  * `groupBy`: the `field`(s) to group by (no relationship allowed).
  * `after`: the `nextCursor` from the previous query, for pagination.

### Filter specifications

|                   | Field                     | Filter   | How to use                                       |
| ----------------- | ------------------------- | -------- | ------------------------------------------------ |
| Top level filters | Any                       | `and`    | `{and: [{...},{...}]}` = if everything is true.  |
|                   |                           | `or`     | `{or: [{...},{...}]}` = if at least one is true. |
|                   |                           | `not`    | `{not: {...}}` = if false.                       |
| Primitives        | Any                       | `eq`     | `{eq: ...}`                                      |
|                   |                           | `in`     | `{in: ["..."]}` = if any of term.                |
|                   | Nullable                  | `isNull` | `{isNull: True}` = if the field is empty.        |
|                   | String                    | `prefix` | `{prefix: "..."}` = starts with.                 |
|                   | Int/Int64/Float/Timestamp | `lt`     | `{lt: ...}` = less than.                         |
|                   |                           | `gt`     | `{gt: ...}` = greater than.                      |
|                   |                           | `lte`    | `{lte: ...}` = less than or equals.              |
|                   |                           | `gte`    | `{gte: ...}` = greater than or equals.           |
|                   | TimeSeries                | ❌        | Not supported.                                   |
| User defined type |                           | ❌        | Not supported.                                   |
| Lists(\[XXX])     |                           | ❌        | Not supported.                                   |

### Unit conversion

Fields that are enabled for unit conversion will contain `targetUnit` and `targetUnitSystem` attributes.

* `targetUnit`: specifies the external ID of the unit that the retrieved data will be converted to.
* `targetUnitSystem`: specifies the unit by the unit system the retrieved data will be converted to.

See [Units](/dev/concepts/resource_types/units/units) for more information and examples.

### Unit information

`unitInfo` object contains unit information, `unitExternalId`, `sourceUnit` for unit enabled fields.
See [Units](/dev/concepts/resource_types/units/units) for more information and examples.

### Pagination in `list` and `getById` queries

GraphQL `list` and `getById` queries support cursoring. In `list` queries, you can cursor only at the top-level.
In `getById` queries, you can cursor only at the first sub-query level.

The `hasNextPage` field in `pageInfo` will under certain conditions be `true` even when there is not more data.
Specifically if the total number of items is divisible by `first`. You should therefore always exhaust
cursors until no items are returned, and not rely upon `hasNextPage`.

### GraphQL `list` and `getById` queries with subqueries

GraphQL `list` and `getById` queries include subqueries on fields backed by direct relations or edges. When querying these fields, a maximum result set size of **10,000** items applies. This limit refers to the *total* number of items returned by a subquery, not per item in the parent subquery.

For example:

```graphql theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
query ListActors {
  listActors(first: 100) {
    name
    actedTogether(first: 10) {
      items {
        name
        actedTogether(first: 15) {
          items {
            name
          }
        }
      }
    }
  }
}
```

Here, `Actors` is a type with fields `name` and `actedTogether`, where `actedTogether` is an edge property.

* The root `listActors` query returns up to 100 items.
* The first nested `actedTogether` subquery has a limit of 10 items.
* The second nested `actedTogether` subquery has a limit of 15 items.

If the dataset exceeds the subquery limits, the root query will still return 100 items, each item containing 10 `actedTogether` items, and each of those containing 15 more `actedTogether` items.

The total number of items returned in the `actedTogether` subquery would be:

```graphql wrap theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
100 (root) × 10 (actedTogether level 1) × 15 (actedTogether level 2) = 15,000 items
```

This exceeds the maximum allowed result set size of 10,000 items.

When the result set size limit is exceeded, any additional items beyond the limit will be excluded from the response.

### Risks of using `first` in GraphQL subqueries

Cognite supports using the `first` parameter at the top-level in a "list" query and at the first subquery level of a "getById" query. The parameter limits the number of returned items, and you can use it in combination with a sort to pick the first/last items of a query. For other subqueries, `first` is allowed for legacy support, but shouldn't be used.

* In subqueries targeting a list of direct relations, or a reverse direct relation, `first` is allowed but not implemented. Supplying the parameter has no effect on the result.
* In subqueries targeting edges, `first` is allowed and implemented, but isn't compatible with `sort`. The limit imposed by `first` is applied **before** the items are sorted.

#### Example of using `first` in a list query

In a `list` query, `first` is correctly applied if it's used at the top-level of the query, but not if it follows a list of direct relations or a reverse direct relation in a subquery.

For example:

```graphql theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
query MyQuery {
  listMovie(first: 1) {
    items {
      producers(first: 1) {
        items {
          name
        }
      }
    }
  }
}
```

In this example, "Movie" is a type with a "producers" field that's backed by either a list of direct
relations or a reverse direct relation. The result of the top level list query "listMovie" will be correctly
limited to a single result. The "producers" subquery, however, won't be limited.

Example output:

```json theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
{
  "listMovie": {
    "items": [
      {
        "producers": {
          "items": [
            {
              "name": "producer_1"
            },
            {
              "name": "producer_0"
            }
          ]
        }
      }
    ]
  }
}
```

#### Example of using `first` in a getById query

In a `getById` query, you can use `first` at the first subquery level.

For example:

```graphql theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
query MyQuery {
  getMovieById(instances: {
    space: "movies",
    externalId: "movie_0"
  }) {
    items {
      producers(first: 1) {
        items {
          externalId
        }
      }
    }
  }
}
```

Where "producers" could be a subquery targeting either a list of direct relations,
a reverse direct relation, or an edge connection property.

Example output:

```json theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
{
  "getMovieById": {
    "items": [
      {
        "producers": {
          "items": [
            {
              "externalId": "producer_0"
            }
          ]
        }
      }
    ]
  }
}
```

However, you can't use `first` in further nested subqueries. For example, the following
query, where we use `first` for a nested subquery, "movies", won't work as expected:

```graphql theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
query MyQuery {
  getMovieById(instances: {
    space: "movies",
    externalId: "movie_0"
  }) {
    items {
      producers(first: 1) {
        items {
          externalId
          movies(first: 1) {
            items {
              externalId
            }
          }
        }
      }
    }
  }
}
```

The result of the "movies" subquery won't be limited to a single item. Example output:

```json theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
{
  "getMovieById": {
    "items": [
      {
        "producers": {
          "items": [
            {
              "externalId": "producer_0",
              "movies": {
                "items": [
                  {
                    "externalId": "movie_0"
                  },
                  {
                    "externalId": "movie_1"
                  }
                ]
              }
            }
          ]
        }
      }
    ]
  }
}
```
