{: .-three-column}
{ status }
{ status: 'available' }
{: .-setup}
{ hero { name height } }
{ hero:
{ name: "Luke Skywalker",
height: 1.74 } }
{: .-setup}
{ friends { name } }
{ friends:
[ { name: "Luke Skywalker" },
{ name: "Han Solo" },
{ name: "R2D2" } ] }
{: .-setup}
GraphQL queries look the same for both single items or lists of items.
{
hero(id: "1000") { id name }
}
{ hero:
{ id: "1000",
{ name: "Luke Skywalker" } }
{: .-setup}
{
luke: hero(id: "1000") { name }
han: hero(id: "1001") { name }
}
{ luke:
{ name: "Luke Skywalker" },
han:
{ name: "Han Solo" } }
{: .-setup}
query FindHero($id: String!) {
hero(id: $id) { name }
}
Just to make things less ambiguous. Also, to use variables, you need an operation name.
{ id: '1000' }
{ createReview($review) { id } }
{ review: { stars: 5 } }
{ createReview: { id: 5291 } }
Mutations are just fields that do something when queried.
{
search(q: "john") {
id
... on User { name }
... on Comment { body author { name } }
}
}
Great for searching.
fetch('http://myapi/graphql?query={ me { name } }')
fetch('http://myapi/graphql', {
body: JSON.stringify({
query: '...',
operationName: '...',
variables: { ... }
})
})
{: .-three-column}
type Query {
me: User
users(limit: Int): [User]
}
type User {
id: ID!
name: String
}
See: sogko/graphql-shorthand-notation-cheat-sheet
| Int
| Integer |
| Float
| Float |
| String
| String |
| Boolean
| Boolean |
| ID
| ID |
| scalar
| Scalar type |
| type
| Object type |
| interface
| Interface type |
| union
| Union type |
| enum
| Enumerable type |
| input
| Input object type |
| String
| Nullable string |
| String!
| Required string |
| [String]
| List of strings |
| [String]!
| Required list of strings |
| [String!]!
| Required list of required strings |
type Mutation {
users(params: ListUsersInput) [User]!
}
interface Entity {
id: ID!
}
type User implements Entity {
id: ID!
name: String
}
enum DIRECTION {
LEFT
RIGHT
}
type Root {
direction: DIRECTION!
}
{: data-line="1,2,3,4"}
type Artist { ··· }
type Album { ··· }
union Result = Artist | Album
type Query {
search(q: String) [Result]
}
{: data-line="4"}
Function for each field on each type
type Query {
me: User
}
type User {
id: ID
name: String
}
function Query_me(request) {
return request.auth.user;
}
function User_name(user) {
return user.getName();
}
Example Query
{
me {
name
}
}
JSON result
{
"me": {
"name": "Luke Skywalker"
}
}
Example Query
{
hero {
name
}
}
JSON result
{
"data": {
"hero": {
"name": "R2-D2"
}
}
}
Query
{
hero {
name
# Queries can have comments!
friends {
name
}
}
}
JSON result
{
"data": {
"hero": {
"name": "R2-D2",
"friends": [
{
"name": "Luke Skywalker"
},
{
"name": "Han Solo"
},
{
"name": "Leia Organa"
}
]
}
}
}
Query
{
human(id: "1000") {
name
height
}
}
JSON result
{
"data": {
"human": {
"name": "Luke Skywalker",
"height": 1.72
}
}
}
Query
{
human(id: "1000") {
name
height(unit: FOOT) # Enumeration type
}
}
JSON result
{
"data": {
"human": {
"name": "Luke Skywalker",
"height": 5.6430448
}
}
}
Aliases let you rename the result of a field to anything you want
{
empireHero: hero(episode: EMPIRE) {
name
}
jediHero: hero(episode: JEDI) {
name
}
}
JSON result
{
"data": {
"empireHero": {
"name": "Luke Skywalker"
},
"jediHero": {
"name": "R2-D2"
}
}
}
{
leftComparison: hero(episode: EMPIRE) {
...comparisonFields
}
rightComparison: hero(episode: JEDI) {
...comparisonFields
}
}
fragment comparisonFields on Character {
name
appearsIn
friends {
name
}
}
JSON result
{
"data": {
"leftComparison": {
"name": "Luke Skywalker",
"appearsIn": [
"NEWHOPE",
"EMPIRE",
"JEDI"
],
"friends": [
{
"name": "Han Solo"
},
{
"name": "Leia Organa"
},
{
"name": "C-3PO"
},
{
"name": "R2-D2"
}
]
},
"rightComparison": {
"name": "R2-D2",
"appearsIn": [
"NEWHOPE",
"EMPIRE",
"JEDI"
],
"friends": [
{
"name": "Luke Skywalker"
},
{
"name": "Han Solo"
},
{
"name": "Leia Organa"
}
]
}
}
}
query HeroComparison($first: Int = 3) {
leftComparison: hero(episode: EMPIRE) {
...comparisonFields
}
rightComparison: hero(episode: JEDI) {
...comparisonFields
}
}
fragment comparisonFields on Character {
name
friendsConnection(first: $first) {
totalCount
edges {
node {
name
}
}
}
}
Variable
{"first": 2}
JSON result
{
"data": {
"leftComparison": {
"name": "Luke Skywalker",
"friendsConnection": {
"totalCount": 4,
"edges": [
{
"node": {
"name": "Han Solo"
}
},
{
"node": {
"name": "Leia Organa"
}
}
]
}
},
"rightComparison": {
"name": "R2-D2",
"friendsConnection": {
"totalCount": 3,
"edges": [
{
"node": {
"name": "Luke Skywalker"
}
},
{
"node": {
"name": "Han Solo"
}
}
]
}
}
}
}
"Name your queries to make the code less ambigous"
query HeroNameAndFriends {
hero {
name
friends {
name
}
}
}
Steps for using variables
$variableName
$variableName
as an accepted variablevariableName: value
(usually) as JSONQuery with variable definition
query HeroNameAndFriends($episode: Episode) {
hero(episode: $episode) {
name
friends {
name
}
}
}
Variable
{
"episode": "JEDI"
}
JSON result
{
"data": {
"hero": {
"name": "R2-D2",
"friends": [
{
"name": "Luke Skywalker"
},
{
"name": "Han Solo"
},
{
"name": "Leia Organa"
}
]
}
}
}
($episode: Episode)
($episode: Episode!)
are suffixed with " sign ($episode: Episode = JEDI)
query HeroNameAndFriends($episode: Episode = JEDI) {
hero(episode: $episode) {
name
friends {
name
}
}
}
Two directives built into the spec:
include(if: Boolean)
- Includes this field only if the argument is true
skip(if: Boolean)
- Skips this field if the argument is true
query Hero($episode: Episode, $withFriends: Boolean!) {
hero(episode: $episode) {
name
friends @include(if: $withFriends) {
name
}
}
}
Summarized view
Variables
{
"episode": "JEDI",
"withFriends": false
}
JSON result
{
"data": {
"hero": {
"name": "R2-D2"
}
}
}
Detailed view
Variables
{
"episode": "JEDI",
"withFriends": true
}
JSON result
{
"data": {
"hero": {
"name": "R2-D2",
"friends": [
{
"name": "Luke Skywalker"
},
{
"name": "Han Solo"
},
{
"name": "Leia Organa"
}
]
}
}
}
createReview
field returns the stars
and commentary
fields of the newly created reviewThe review
variable is not a scalar - It's an input object type
mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) {
createReview(episode: $ep, review: $review) {
stars
commentary
}
}
Variables
{
"ep": "JEDI",
"review": {
"stars": 5,
"commentary": "This is a great movie!"
}
}
JSON result
{
"data": {
"createReview": {
"stars": 5,
"commentary": "This is a great movie!"
}
}
}
incrementCredits
mutations in one request mean: the first is guaranteed to finish before the second beginshero
field returns the type Character
, which might be either a Human
or a Droid
depending on the episode
argumentname
exists on both so you can directly ask for that in the queryTo ask for a field on the concrete type, you need to use an inline fragment with a type condition
query HeroForEpisode($ep: Episode!) {
hero(episode: $ep) {
name
... on Droid {
primaryFunction
}
... on Human {
height
}
}
}
Variables
{
"ep": "JEDI"
}
JSON result
{
"data": {
"hero": {
"name": "R2-D2",
"primaryFunction": "Astromech"
}
}
}