Working With Fragments
Fragments are essential part of writing robust GraphQL queries. Fragments let you construct sets of fields, and then include them in queries where you need to.
With Artemis you can easily include a fragment with your query by simplying adding it into the string to parse:
(parse-document
"query getPerson($id: String!) {
person(id: $id) {
id
...NameFields
}
}
Fragment NameFields on Person {
firstName
lastName
}")
But, what if you wanted to split your fragments out into a different file so that they can be used in various places in your application? How about something like this:
(ns app.fragments
(:require [artemis.document :refer [parse-document]]))
(def name-fields
(parse-document
"Fragment NameFields on Person {
firstName
lastName
}
"))
When we need to use a fragment within a query, we can just refer to it as app.fragments/name-fields
and compose it with our query document using artemis.document/compose
:
(ns app.core
(:require [artemis.core :as a]
[artemis.document :as d :refer [parse-document]]
[app.fragments :as fragments]))
(def get-person-doc
(parse-document
"query getPerson($id: String!) {
person(id: $id) {
id
...NameFields
}
}"))
(a/query! client
(d/compose get-person-doc fragments/name-fields)
{:id 1})
Inlining Fragments
Because Artemis produces an AST when you parse a document, it’s fairly straightforward to inline a fragment directly into a query selection set. For example, if we wanted to inline the firstName
and lastName
fields into our getPerson
query, we could so by calling artemis.document/inline-fragments
:
(-> get-person-doc
(d/compose fragments/name-fields)
(d/inline-fragments))
If we were to execute the above query, it would be like executing something like:
query getPerson($id: String!) {
person(id: $id) {
id
# inlined fields below
firstName
lastName
}
}
Fragments on Unions
More complex GraphQL schemas are likely to eventually encounter the need for interfaces and unions. Artemis supports fragments on unions, so the below would work:
(parse-document
"query search($term: String!) {
search(term: $term) {
... on Person {
__typename
id
firstName
lastName
}
... on Company {
__typename
id
name
address
}
}
}")
Keep in mind that because unions switch on type and the Artemis store likely doesn’t know anything about your GraphQL schema types, it’s important to include the __typename
field in our union selection sets, so that the cache can correctly match up a selection set with an entity.