Anatomy of a Query

This article explains the anatomy of a GraphQL query when using Prismic + Gatsby.


What is a GraphQL query?

The basic operation that GraphQL syntax has to retrieve data is called Query, a read‐only kind of fetch.

Basic GraphQL query parts

We use queries inside Gatsby pages to declare which data each one of them needs. We're going to go over all the sections that make up a query:

Run your project

Visualize your endpoint's schema while reading this article so that you have a real example to test with. Just go to the GraphQL Playground of your project while running in development. It will be accessible at http://localhost:8000/__graphql, and then click the Explorer button.

Query type

This is the operation type that defines the kind of operation that you're performing. There are other operation types in GraphQL. The Prismic API is read-only, so we will only ever use query. Check out the GraphQL official documentation about queries to learn more about this.

You can use it alone or along with the Query name (explained below). So if you're making an anonymous query, this value can be omitted.

Example in the diagram: query

Query name

This is the operation you'll use to name your queries. You could choose to leave queries unnamed, but the official GraphQL docs recommend you not to do it because names are useful when tracking a certain query's retrieved data and debugging a project.

Example in the diagram: MyQuery

Fields (Root-level)

Root level fields initiate a query that is defined by the GraphQL schema definition. When querying your Prismic API endpoint, this field will always be unique to your Custom types, so say you have a Custom type with the name of 'Post', then your fields will be:

  • allPrismicPost
  • prismicPost

That's how Gatsby knows you're looking for your Prismic content.

Example in the diagram: allPrismicPage

Root type fields provided by the schema

A Gatsby schema provides a root type for each kind of operation.

Example in the diagram: The edges,  node, data, and body fields are Root type fields provided by the schema when querying multiple documents.

Arguments

Arguments serve as parameters that you can add to filter the response. They can be optional or required depending on the schema definition.

Example in the diagram: filter, uid, and eq (note that UID can also. be a Top-level field type, one of which can be used as an argument).

Variables

Variables are passed as the value of a given argument. They can be static or dynamic:

  • Static: In the diagram above, we're using the UID "sample" to find a type Page document as an example of a static search parameter.
  • Dynamic: Dynamic variables are also passed as the value of a given argument. In Gatsby, you use dynamic variables to generate pages dynamically. The data passed into the query variables comes from gatsby-node. How dynamic variables work is beyond the scope of this article. If you'd like to learn more about this, check out the official Gatsby documentation on variables.

Fields (Top-level)

These represent available fields in your documents that you can retrieve from the Prismic API through the schema.

Example in the diagram: title, which is a Title field.

Union type

Unions in Prismic are used to retrieve Linked content or Slices. You can use unions to perform something similar to a switch conditional statement. After adding a Union, you can then specify the fields that you need from a given type.

Example in the diagram: The ...on PrismicPageBodySlice union is calling a Slice with the name of Gallery. Then we specify all the fields that exist in this document. In this case, we're just calling an Image field with the API ID of illustration.

The lifecycle of a query

With everything you've learned so far, we'll now look into a complete example that will show you what working with a query looks like from start to finish. Browse each tab to learn each step:

  1. Writing the query: We create a page query with a query with the Query name of MyPages. Then allPrismicPage indicates that It is going to filter all documents of the type Page. We then use the filter argument to get the doc that matches the UID of sample. Then we retrieve a Slice with Text Info's name using a Union type ...on PrismicPageBodyTextInfo, and retrieve a Rich Text a Title and an Image.
  2. Retrieve the data: An example of what the response of a query looks like. You can see that the JSON structure is similar to the query itself.
  3. Template the data: An example of how you could use and template the retrieved data from the query.
  4. The full-page example with the query and the render section.
  • Writing the query
  • Retrieved data
  • Template the data
Copy
import React from 'react'
import { graphql } from 'gatsby'

export const query = graphql `
query MyPages {
  allPrismicPage(filter: {uid: {eq: "sample"}}) {
    edges {
      node {
        data {
          body {
            ... on PrismicPageBodyTextInfo {
              primary {
                title {
                  raw
                }
                description {
                  raw
                }
                illustration {
                  url
                }
              }
            }
          }
        }
      }
    }
  }
}
`
Copy
{
  "data": {
    "allPrismicPage": {
      "edges": [
        {
          "node": {
            "data": {
              "body": [
                {
                  "primary": {
                    "title": {
                      "raw": "Welcome to my art blog"
                    },
                    "description": {
                      "raw": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
                    },
                    "illustration": {
                      "url": "ttps://images.prismic.io/query-test/a5960fab-1e34-4f3d-b056-ef0aff09f772_kelli-tungay-Sj0nhVIb4eY-unsplash.jpg?auto=compress,format"
                    }
                  }
                }
              ]
            }
          }
        }
      ]
    }
  }
}
Copy
export const PageTemplate = ({ data }) => {
  if (!data) return null
  const document = data.allPrismicPage.edges[0].node.data

  return (
    <div>
      {RichText.render(document.title.raw)}
      {RichText.render(document.description.raw)}
      <img src={document.image.url} alt={document.image.alt} />
    </div>
  )
}

export default PageTemplate
Copy
import React from 'react'
import { graphql } from 'gatsby'
import { RichText } from 'prismic-reactjs'

const Post = ({ data }) => {
  if (!data) return null
  const document = data.allPrismicPage.edges[0].node.data.body.primary

  return (
    <div>
      {RichText.render(document.title.raw)}
      {RichText.render(document.description)}
      <img src={document.image.url} alt={document.image.alt} />
    </div>
  )
}

export const query = graphql `
query MyPages {
  allPrismicPage(filter: {uid: {eq: "sample"}}) {
    edges {
      node {
        data {
          body {
            ... on PrismicPageBodyTextInfo {
              primary {
                title {
                  raw
                }
                description {
                  raw
                }
                illustration {
                  url
                }
              }
            }
          }
        }
      }
    }
  }
}
`

export default Post

Browser view: Finally, we run our project and voilà! — our data is now visible in the browser for everyone to see.

The final rendered content