# Queries

Hygraph automatically generates queries for fetching single, and multiple entries for each defined content type belonging to your project.

## Overview

Hygraph automatically generates queries for fetching single, and multiple entries for each defined content type belonging to your project.

You will need a [Permanent Auth Token](https://hygraph.com/docs/api-reference/basics/authorization#permanent-auth-tokens), or your [Public API Permissions](https://hygraph.com/docs/api-reference/basics/authorization#public-api-permissions) configured to query any data from your project.

## Auto-generated queries

When a new model is added to your project, there are two generated GraphQL queries added to your schema. The queries are named after the `API ID`, and `Plural API ID`.

**Warning:**
Both the single, and plural queries come with their own generated arguments for filtering, ordering, paginated, and getting content via their stage, revision, or locale.

For example, let's assume we have the model `Post` in our schema, and opted to keep the default generated API ID, and Plural API ID. The following queries would be generated by the API automatically:

- `post`
- `posts`
- `postVersion`
- `postsConnection`

## Fetching a single entry

The `post` query is what you would use to fetch one entry from the CMS.

You can fetch an individual entry by `id`, or any unique non-localized field defined in your content type.

```graphql
{
  post(where: { id: "..." }) {
    id
    title
  }
}
```

## Fetching multiple entries

The `posts` query is what you should use to fetch multiple entries from the CMS.

```graphql
{
  posts {
    id
  }
}
```

## Fetching relations

Imagine `posts` have a [one to many](https://hygraph.com/docs/api-reference/schema/field-types#one-to-many) relation with comments. With GraphQL you can query the related `comments` in the same request.

Here we will get all posts, and their comments.

```graphql
{
  posts {
    id
    comments {
      id
      author
    }
  }
}
```

Learn more about [Relations](https://hygraph.com/docs/api-reference/schema/field-types#reference).

## Fetching localizations

When fetching one or more entry, you can also fetch the localized entries. The default locale is set to `en`.

```graphql
{
  post(where: { id: "..." }, locales: [en, fr, de]) {
    title
  }

  posts(locales: [en, fr, de]) {
    title
  }
}
```

Learn more about [Localization](https://hygraph.com/docs/api-reference/content-api/localization).

### Locales inside components

When Localized fields only exist inside components, querying for content can be a bit misleading, especially when querying for locales. For instance, to query for the “Russian” Locale inside the components, specifying the locale in the query like the example below, will return null:

  **Query**

```graphql
query MyQuery {
  pages(locales: ru) {
    id
    title
    slug
    pageElements {
      ... on Header {
        title
        contacts
      }
      ... on Footer {
        title
        texts
      }
    }
  }
}
```

  
  **Response**

```json
{
  "data": {
    "pages": []
  }
}
```


The reason for this is that the parent entry - Page - does not exist in the requested locale. Instead, asking for the "German" locale will return results like the one shown below, as this is the default - Base - locale, and entries will always exist in the default locale:

  **Query**

```graphql
query MyQuery {
  pages(locales: de) {
    id
    title
    slug
    pageElements {
      ... on Header {
        title
        contacts
      }
      ... on Footer {
        title
        texts
      }
    }
  }
}
```

  
  **Response**

```json
{
  "data": {
    "pages": [
      {
        "id": "cl793mb8unoao0buuop235856",
        "title": "Pricing Page",
        "slug": "pricing",
        "pageElements": [
          {
            "title": "Subscription",
            "contacts": 430
          },
          {
            "title": "Contact",
            "texts": ["text 1", "text 2"]
          }
        ]
      }
    ]
  }
}
```


The Page model - parent entry in this example - has two fields, **Title** and **Slug**, that are not localized, as well as components. In turn, the components - children - have localized fields inside.
So, when you create an entry, only the components - children - have localization and not the parent entry. This means that, when you query for pages in a locale that is not the default and the parent entry does not exist in that locale, the query will return null.

There are three workarounds to query locales inside components:

- [Specify the locale for the component](https://hygraph.com/docs/api-reference/content-api/queries#specify-locale-for-the-component)
- [Use localizations inside the component in your query](https://hygraph.com/docs/api-reference/content-api/queries#use-localizations-inside-the-component-in-your-query)
- [Add a localized field to the parent entry](https://hygraph.com/docs/api-reference/content-api/queries#add-a-localized-field-to-the-parent-entry)

Here are some examples of these workarounds, following the German/Russian locales example we used before:

#### Specify locale for the component

To query for the Russian locale in our example, you simply need to specify the locale for the component, as shown below:

  **Query**

```graphql
query MyQuery {
  pages {
    id
    title
    slug
    pageElements(locales: ru) {
      ... on Header {
        title
        contacts
      }
    }
  }
}
```

  
  **Response**

```json
{
  "data": {
    "pages": [
      {
        "id": "cl7g3mb8unoao0buuop235856",
        "title": "Pricing Page",
        "slug": "pricing",
        "pageElements": [
          {
            "title": "Подписка",
            "contacts": 320
          }
        ]
      }
    ]
  }
}
```


#### Use localizations inside the component in your query

Another way to query for all the locales inside the component is to use **localizations** inside the component in your query, as follows:

  **Query**

```graphql
query MyQuery {
  pages {
    id
    title
    slug
    pageElements {
      ... on Header {
        id
        localizations(includeCurrent: true, locales: [de, ru]) {
          title
          contacts
          locale
        }
      }
      ... on Footer {
        title
        texts
      }
    }
  }
}
```

  
  **Response**

```json
{
  "data": {
    "pages": [
      {
        "id": "cl7g3mb8unoao0buuop23586",
        "title": "Pricing Page",
        "slug": "pricing",
        "pageElements": [
          {
            "id": "cl7g3mb8unoap0buuwzpoipja",
            "localizations": [
              {
                "title": "Subscription",
                "contacts": 430,
                "locale": "de"
              },
              {
                "title": "Подписка",
                "contacts": 320,
                "locale": "ru"
              }
            ]
          },
          {
            "title": "Contact",
            "texts": ["text 1", "text 2"]
          }
        ]
      }
    ]
  }
}
```


#### Add a localized field to the parent entry

The third and final workaround would be to add a localized field to the parent entry, as shown in the example below:

![Add a localized field to the parent entry](https://hygraph.com/images/docs/api-reference/content-api/locales-in-components-3rdworkaround-a.png)

This makes it possible to request the locale at the beginning of the query.

  **Query**

```graphql
query MyQuery {
  pages(locales: ru) {
    id
    title
    slug
    pageElements {
      ... on Header {
        localizations(includeCurrent: true, locales: [de, ru]) {
          title
          contacts
          locale
        }
      }
      ... on Footer {
        title
        texts
      }
    }
  }
}
```

  
  **Response**

```json
{
  "data": {
    "pages": [
      {
        "id": "cl7g3mb8unoao0buuop23586",
        "title": "Pricing Page",
        "slug": "adding-russian-locale",
        "pageElements": [
          {
            "localizations": [
              {
                "title": "Subscription",
                "contacts": 430,
                "locale": "de"
              },
              {
                "title": "Подписка",
                "contacts": 320,
                "locale": "ru"
              }
            ]
          },
          {
            "title": "Contact",
            "texts": ["text 1", "text 2"]
          }
        ]
      }
    ]
  }
}
```


## Fetching stages

When fetching entries, you can also specify the content `stage`.

The default content stage is set to `DRAFT`.

```graphql
{
  post(where: { id: "..." }, stage: PUBLISHED) {
    title
  }

  posts(stage: PUBLISHED) {
    title
  }
}
```

Learn more about [Content Stages](https://hygraph.com/docs/api-reference/content-api/content-stages).

## Fetching versions

You can fetch all data of a specific entry at a point in time using the automatically generated version query.

For example, using the `postVersion` query from above, we can make a request to get the specific revision through a query:

```graphql
{
  postVersion(where: { id: "abc123", revision: 1, stage: PUBLISHED }) {
    id
    revision
    data
  }
}
```

Learn more about [Versioning](https://hygraph.com/docs/api-reference/content-api/content-stages#versioning).

## Fetching workflow step

You can fetch the workflow step for an entry.

For example, for the model `Post` with workflow enabled, we can make a request to get the workflow step for an entry:

```graphql
{
  posts {
    id
    workflowStep
  }
}
```

Learn more about [Content workflows](https://hygraph.com/docs/developer-guides/project/content-workflows).

## Combining arguments

It is also possible to pass more than one query argument at a time.

For example, here we can get the first 3 posts, ordered by the created timestamp, where the title contains "Hygraph", and is published.

```graphql
{
  posts(
    where: { title_contains: "Hygraph" }
    orderBy: createdAt_DESC
    first: 3
    stage: PUBLISHED
  ) {
    id
  }
}
```

Learn more about these query arguments:

- [Filtering](https://hygraph.com/docs/api-reference/content-api/filtering)
- [Ordering](https://hygraph.com/docs/api-reference/content-api/ordering)
- [Pagination](https://hygraph.com/docs/api-reference/content-api/pagination)
- [Content Stage](https://hygraph.com/docs/api-reference/content-api/content-stages)

## Combining queries

Multiple queries can be executed in parallel via a single request to your endpoint.

For example, let's fetch our a single, and multiple posts in one request.

```graphql
{
  post(where: { id: "..." }) {
    id
    title
  }

  posts {
    id
    title
  }
}
```

For example, here we query for all events, and alias a second query with `previous` to better represent the applied filter.

```graphql
{
  events(where: { start_gt: "2020-10-07T09:00:00+00:00" }) {
    start
  }

  previous: events(where: { start_lt: "2020-10-07T09:00:00+00:00" }) {
    start
  }
}
```

## Fetching with Relay

Hygraph also implements the Relay specification for querying records for all projects. You can fetch a single entry using the `node` query, or multiple entries with the `postsConnection` type.

When fetching a single entry with `node`, you will need to also pass the Edge Type inside the query.

### Node

```graphql
{
  node(id: "...") {
    ... on Post {
      id
      title
    }
  }
}
```

You can use the generated Relay connection query for querying multiple entries.

### Connection / Edges

```graphql
{
  postsConnection {
    edges {
      cursor
      node {
        id
        title
      }
    }
  }
}
```

Learn more about the [system fields](https://hygraph.com/docs/api-reference/schema/system-fields#connection-type-fields) for connection type queries.

## Directives

We support both the `@skip` and `@include` directives for use in your schema. This allows you to skip or include a field based on the value of the `if` argument you provide.

### @skip

For example, below can use the `@skip` directive to skip including a field based on the `skipTitle` variable value.

  **Query**

```graphql
query ($skipTitle: Boolean!) {
  posts {
    id
    title @skip(if: $skipTitle)
  }
}
```

  
  **Variables**

```json
{
  "skipTitle": true
}
```


### @include

For example, below can use the `@include` directive to include a field (including relations) based on the `includeAuthor` variable value.

  **Query**

```graphql
query ($includeAuthor: Boolean!) {
  posts {
    id
    title
    author @include(if: $includeAuthor) {
      name
    }
  }
}
```

  
  **Variables**

```json
{
  "includeAuthor": true
}
```


## Variables

It's recommended you use GraphQL variables when working with queries that use any variable data values. This is useful for reusing queries across your application.

For example, to fetch a post by slug, you'd first need to define the query name, and the arguments with the type, and pass that along to the query itself.

```graphql
query GetPostBySlug($slug: String!) {
  post(where: { slug: $slug }) {
    id
    title
  }
}
```

When working with a GraphQL client, this is how you'd typically work with variables:

  **GraphQL Request**

```js
import { request, gql } from 'graphql-request';

const endpoint = 'YOUR_HYGRAPH_ENDPOINT';

const query = gql`
  query GetPostBySlug($slug: String!) {
    post(where: { slug: $slug }) {
      id
      title
    }
  }
`;

const variables = {
  slug: 'hygraph-is-awesome',
};

const data = await request(endpoint, query, variables);
```

  
  **Apollo Client (React)**

```js
import { gql, useQuery } from '@apollo/client';

const query = gql`
  query GetPostBySlug($slug: String!) {
    post(where: { slug: $slug }) {
      id
      title
    }
  }
`;

function PostPage({ breed }) {
  const { loading, error, data } = useQuery(query, {
    variables: { slug: 'hygraph-is-awesome' },
  });

  if (loading) return null;
  if (error) return `Error! ${error}`;

  return <pre>{JSON.stringify(data, null, 2)}</pre>;
}
```
