GraphQL Query Cheatsheet
View SourceThis cheatsheet provides quick reference for the basic and common GraphqlQuery usage.
use GraphqlQuery
Basic Usage
defmodule MyApp.Queries do
use GraphqlQuery
# You have access to ~GQL sigil and other macros
endWith Options
defmodule MyApp.Queries do
use GraphqlQuery,
schema: MyApp.Schema,
runtime: false,
ignore: false,
evaluate: false,
fragments: [],
format: false,
federation: false
enduse GraphqlQuery.Schema
Load schema from a graphql file
schema.ex
defmodule MyApp.Schema do
use GraphqlQuery.Schema,
schema_path: "priv/schema.graphql"
endpriv/schema.graphql
schema {
query: RootQueryType
}
"An item"
type Item {
id: ID
name: String
}
type RootQueryType {
item(id: ID!): Item
}Manual schema module
defmodule MyApp.Schema do
use GraphqlQuery.Schema
@impl GraphqlQuery.Schema
def schema do
# Suffix "s" to parse as schema
~GQL""s
end
# Optional: By default is this module's file path
# Can be nil, or a string. It's used for validation errors
@impl GraphqlQuery.Schema
def schema_path, do: nil
endLoad schema from an Absinthe schema
schema.ex
defmodule MyApp.Schema do
use GraphqlQuery.Schema, absinthe_schema: MyAppWeb.Graphql.Schema
endmy_app_web/graphql/schema.ex
defmodule MyAppWeb.Graphql.Schema do
use Absinthe.Schema
@desc "An item"
object :item do
field(:id, :id)
field(:name, :string)
end
query do
field :item, :item do
arg(:id, non_null(:id))
resolve(&Resolvers.resolve_item/3)
end
end
end~GQL Sigil
Queries
~GQL"""
query GetUser($id: ID!) {
user(id: $id) {
id
name
email
}
}
"""Fragments
~GQL"""
fragment UserFields on User {
id
name
email
}
"""f # <- Important the "f" optionMutation
~GQL"""
mutation CreateUser($input: UserInput!) {
createUser(input: $input) {
id
name
}
}
"""Schema Definitions
~GQL"""
type User {
id: ID!
name: String!
email: String!
}
type Query {
user(id: ID!): User
}
"""s # <- Important the "s" optionSigil Modifiers
# Ignore validation warnings
~GQL""i
# Runtime validation
~GQL""r
# Query document (default)
~GQL""q
# Fragment document
~GQL""f
# Schema document
~GQL""s
# Federation support (for schemas)
~GQL""sFValidate with Schema
defmodule MyApp.Queries do
use GraphqlQuery, schema: MyApp.Schema
def get_user do
~GQL"""
query GetUser($id: ID!) {
user(id: $id) {
id
name
}
}
"""
end
endgql_from_file
Basic File Loading
# Load query from file
query = gql_from_file("priv/queries/get_user.graphql")Other Options
# Load fragment from file
fragment = gql_from_file("priv/fragments/user.gql", type: :fragment)
# Load schema from file
schema = gql_from_file("priv/schema.graphql", type: :schema)
# Validate with a schema
fragment = gql_from_file("priv/fragments/user.gql", schema: MyApp.Schema)
# Add fragments
fragment = gql_from_file("priv/fragments/user.gql", fragments: [@fragments])
# Skip validation
query = gql_from_file("priv/queries/get_user.graphql", ignore: true)
# Runtime validation
query = gql_from_file("priv/queries/get_user.graphql", runtime: true)
# Apply formatting when transformed to string
query = gql_from_file("priv/queries/get_user.graphql", format: true)
# Enable Apollo Federation directives (for schemas)
schema = gql_from_file("priv/federated_schema.graphql", type: :schema, federation: true)document_with_options
With ~GQL sigil to validate with schema
document_with_options schema: MySchema do
~GQL"""
query GetUser { user { ...UserFragment } }
"""
endWith ~GQL sigil to add fragments
@user_fragment ~GQL"""
fragment UserFields on User {
id
name
email
}
"""f
document_with_options fragments: [@user_fragment] do
~GQL"""
query GetUserWithFragment {
user {
...UserFields
}
}
"""
endgql Macro
With string interpolation
# Used only when you need to interpolate data
# But it's prefered to use variables and fragments
@fields "id name email"
query = gql "query { user { #{@fields} } }"With Options
# With schema validation
query = gql [schema: MyApp.Schema], ""
# With fragments
query = gql [fragments: [@user_fragment]], ""
# Skip validation
query = gql [ignore: true], ""
# Runtime validation
query = gql [runtime: true], ""
# Apply automatic formatting when transforming to string
query = gql [format: true], "query{user{id name}}"
# Enable Apollo Federation directives (for schemas)
schema = gql [type: :schema, federation: true], ""Dynamic Content
# Useful for testing if you want to build a query with dynamic fields
def build_user_query(field_list) do
fields = Enum.join(field_list)
gql [runtime: true], "query { user { #{fields} }"
endWith Module Schema
defmodule MyApp.Queries do
use GraphqlQuery, schema: MyApp.Schema
def build_query(fields) do
gql "query { user { #{fields} } }"
end
endJSON encoding
With Jason
# All macros return a GraphqlDocument struct that implements Jason.Encoder
query = ~GQL"..."
Jason.encode!(query)
# {"query": "...", "variables": {}}
# You can add fragments or variables!
query
|> GraphqlQuery.Document.add_fragment(fragment)
|> GraphqlQuery.Document.add_variables(id: 123, sort: :ASC)
|> Jason.encode!()
# {"query": "... with fragment if used", "variables": {"id": 123, "sort": "ASC"}}With JSON (Elixir >= 1.18)
# Just like Jason, it implements JSON.Encoder too and support the same features
query = ~GQL"..."
JSON.encode!(query)
# {"query": "...", "variables": {}}to_string
Transform a document to string
# GraphqlQuery.Document and GraphqlQuery.Fragment implements `to_string`, so you can do:
# it returns the query with the needed fragments
query = ~GQL"..."
to_string(query)
"#{query}"Format when doing to_string
# GQL sigil content is formatted automatically with mix format
# But other macros are not, if you want to format the content when
# doing to_string, you have the `format` option
# this is useful specially on testing
query = gql [format: true], ""
fragment = gql_from_document "", [format: true]
# Now it will format the content correctly!
to_string(query)
"#{fragment}"
# Even when encoding to JSON
Jason.encode!(query)Apollo Federation
Federation Schema with Sigil
# Use the "F" modifier to enable federation directives
~GQL"""
extend schema
@link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@key", "@shareable"])
type User @key(fields: "id") {
id: ID!
name: String! @shareable
email: String!
}
"""sF # <- "s" for schema, "F" for federationFederation with gql Macro
# Use federation: true option
schema = gql [type: :schema, federation: true], """
extend schema
@link(url: "https://specs.apollo.dev/federation/v2.5",
import: ["@key", "@authenticated"])
type Product @key(fields: "id") @authenticated {
id: ID!
name: String!
price: Float
}
"""Federation with gql_from_file
# Load federated schema from file
schema = gql_from_file(
"priv/federated_schema.graphql",
type: :schema,
federation: true
)Federation with document_with_options
document_with_options type: :schema, federation: true do
~GQL"""
extend schema
@link(url: "https://specs.apollo.dev/federation/v2.0",
import: ["@key"])
type Order @key(fields: "id") {
id: ID!
total: Float
}
"""s
endModule-level Federation
defmodule MyApp.FederatedSchema do
use GraphqlQuery, federation: true
def schema do
~GQL"""
extend schema
@link(url: "https://specs.apollo.dev/federation/v2.0",
import: ["@key", "@external"])
type User @key(fields: "id") {
id: ID!
reviews: [Review!]! @external
}
"""s
end
endSupported Federation Versions
# Federation v2.0 - Base directives
~GQL"""
extend schema
@link(url: "https://specs.apollo.dev/federation/v2.0",
import: ["@key", "@requires", "@provides", "@external",
"@tag", "@extends", "@shareable", "@inaccessible",
"@override"])
"""sF
# Federation v2.5 - Adds authentication
~GQL"""
extend schema
@link(url: "https://specs.apollo.dev/federation/v2.5",
import: ["@authenticated", "@requiresScopes"])
"""sF
# Federation v2.9 - Adds cost control
~GQL"""
extend schema
@link(url: "https://specs.apollo.dev/federation/v2.9",
import: ["@cost", "@listSize"])
"""sFFederation with Renamed Directives
# Rename directives with "as:"
~GQL"""
extend schema
@link(url: "https://specs.apollo.dev/federation/v2.0",
import: [{name: "@key", as: "@primaryKey"}])
type Product @primaryKey(fields: "id") {
id: ID!
name: String!
}
"""sFFederation with Custom Namespace
# Use custom namespace prefix
~GQL"""
extend schema
@link(url: "https://specs.apollo.dev/federation/v2.0",
import: ["@key"], as: "fed")
type User @key(fields: "id") {
id: ID!
# Non-imported directives use the prefix
name: String! @fed__shareable
}
"""sFFederation Options in use GraphqlQuery
defmodule MyApp.Schemas do
use GraphqlQuery,
federation: true,
# ... other options
schema: nil,
runtime: false
endFull example!
schema.ex
defmodule Schema do
use GraphqlQuery.Schema, schema_path: "priv/schema.graphql"
endfragments.ex
defmodule Fragments do
use GraphqlQuery, schema: Schema
def user_fragment do
~GQL"""
fragment UserFragment on User {
id
name
email
}
"""f
end
def company_fragment do
~GQL"""
fragment CompanyFragment on Company {
id
name
}
"""f
end
endpriv/queries/get_user_with_company_by_id.graphql
query GetUserById($id: ID!) {
user(id: $id) {
...UserFragment
company {
...CompanyFragment
}
}
}queries.ex
defmodule Queries do
# The library is smart and will only add used fragments to the final query
use GraphqlQuery, schema: Schema, fragments: [Fragments.user_fragment(), Fragments.company_fragment()]
def user_by_id do
~GQL"""
query GetUserById($id: ID!) {
user(id: $id) {
...UserFragment
}
}
"""
end
def user_and_company_by_id do
gql_from_file "priv/queries/get_user_with_company_by_id.graphql"
end
@post_fragment ~GQL"""
fragment PostFragment on Post {
id
title
content
}
"""f
def user_posts do
# You can override the available fragments to one specific query
document_with_options fragments: [@post_fragment] do
~GQL"""
query UserPosts($id: ID!) {
posts {
...PostFragment
}
}
"""
end
end
endrequests.ex
defmodule Requests do
alias GraphqlQuery.Document
def user_by_id(user_id) do
query = Queries.user_by_id() |> Document.add_variables(id: user_id)
Req.post!("/graphql", json: query)
end
def user_and_company_by_id(user_id) do
query = Queries.user_and_company_by_id() |> Document.add_variables(id: user_id)
Req.post!("/graphql", json: query)
end
def user_posts(user_id) do
query = Queries.user_posts() |> Document.add_variables(id: user_id)
Req.post!("/graphql", json: query)
end
end