Graphql queries

From wikinotes

Queries retrieve information without causing side-effects.

Basics

Graphql objects are arranged in a DAG.
Top-level nodes can be queried directly,
other objects are accessed through fields on top-level items, optionally passing through an arbitrary number of child node-fields.

Queries are issued as POST requests with a json object as the payload.

curl -X POST \
  -H 'Content-Type: application/json' \
  -d '{"query":    "query queryMembers($search: String){ members(search: $search){ firstName lastName } }", \
       "variables" { "search": "al*" }}' \
  example.com/graphql

Most of the time you'll just work with the query language.

query {
  members($search: String){
    firstName
    lastName
  }
}

And optionally JSON variables

{ "search": "al*" }

Without Params

Some fields may be implied by the REST API path, so no params are required.
This URL probably refers to project 1.

# https://tracking-system/projects/1/graphql
{
  name
  createdAt
}

With Params

Other times, you may need to use parameters in your query.
The value passed to each parameter can be hard-coded, or provided in a JSON object.


In Schema

type Query {
  task(name: String!): Task!
}

type Task {
  name:   String!
  status: String!
  id:     ID!
}

In Request

# hard-coded param
curl -X POST \
  -H 'Content-Type: application/json' \
  -d '{"query": "\
        { \
          task(name: "foo") { \
            status \
          } \
        }"' \
  https://domain.com/graphql

# param values can also be assigned in a JSON object
# (query's 'getTasks' name here is totally arbitrary, name as you please)
curl -X POST \
  -H 'Content-Type: application/json' \
  -d '{ \
        "query": "\
            query getTasks($name: String){ \
              task(name: $name) { \
                status \
              } \
            }",
         "variables": {"name": "foo"} \
       }' \
  https://domain.com/graphql

Fragments

Fragments are a named group of fields to select on a specific object-type.
Fragments let you:

  • Select type-specific fields in heterogenous collections
  • Concisely describe a group of fields, DRY out queries
  • Concisely describe Recursive/Nested nodes

TODO:

Example schema

named fragments

{
  children {

    ...nodeFields
    children {

      ...nodeFields {
        children {

          ...nodeFields
        }
      }
    }
  }
}


fragment nodeFields on Node {
  id
  text
  colour
  background-colour
}

inline fragments

{
  rentalInventory {
    vehicles {
      wheels               # select on both Car and Motorcycle
      passengers

      ... on Car {         # select on Car items only
        numSeatbelts
        numAirbags
      }

      ... on Motorcycle {  # select on Motorcycle items only
        numSaddleBags
      }
    }
  }
}

Connections/Edges

Directives

Directives are conditionals. You can select fields if a boolean expression evaluates to true. https://graphql.org/learn/queries/#directives

@include(if: Boolean)
@skip(if: Boolean)

Introspection

List Types

{ __schema { types { name } } }                   # list all types
{ __schema { mutationType { fields { name } } } }  # list all mutations
{ __schema { queryType { fields { name } } } }     # list all queries

Query Available Fields

{
  __type(name: "Droid") {  # GraphQL type we want fields from
    name
    fields {
      name
      type {
        name
        kind
      }
    }
  }
}

Returns all fields, and their type info.

Query Type info

{
  __type(name: "Shop") {
    fields {
      name
      description
    }
  }
}