How keys are built
GraphQL only For plain HTTP, name keys in the Surrogate-Key header on your origin's response.
The directive says which fields form a key. This page is what GraphPilot does with the values it finds in a response, and what happens when a directive cannot produce a key at all.
How values become keys
Section titled “How values become keys”- A deep key includes its full path.
@surrogateKey(of: "category.id")producesProduct:category.id:<id>. Each segment must be a valid field, and the last one must not be an object, interface or union. - An enum contributes its value as it appears in the response, for example
Product:stockStatus:SOLD_OUT. - A list of scalars or enums contributes one key per distinct element, not one key holding
the whole list:
tags: ["new", "bestseller"]yieldsProduct:tags:newandProduct:tags:bestseller. The order of the elements does not matter, and an element that appears twice yields its key once. In a composite key, a list multiplies out into one key per combination, as described under composite keys. - A list of objects contributes a key for each object, based on the key fields.
- Keys are collected in a set. A key that two directives, or two objects, both produce is attached once, so defining the same key twice costs nothing at runtime.
- Field names in a composite key are sorted alphabetically, and casing is never changed. The only other normalization is the character folding, which leaves ordinary ASCII values untouched.
- The key does not depend on the client’s aliases. See aliases.
When a field is null
Section titled “When a field is null”A key is generated even when a field it names is null, with an empty value:
@surrogateKey(of: "brand.id") on a product without a brand produces Product:brand.id:. That
keeps caching and purging symmetric: a cached product without a brand can still be purged, an
update from null to a value can purge both the old key (Product:brand.id:) and the new one
(Product:brand.id:acme), and a purge of Product:brand.id: reaches every product without a
brand.
A key on a field that returns an object is the exception: @surrogateKey(of: "id") on
Category.featured produces no key at all when featured is null, because there is no object to
key. A static key on that field is still attached.
A union member or implementor on which the path does not exist at all contributes no key; the
empty value only appears when the field exists and is null. With @surrogateKey(of: "author.id") on a search field returning Book | Movie:
... on Book { author { id } } # author.id = "A1"... on Movie { director { name } } # Movie has no author fieldA book produces Query:search.author.id:A1; a movie produces no key from this directive. Add a
second directive, such as @surrogateKey(of: "director.id"), to key movies as well.
Aliases
Section titled “Aliases”When the fragments of a union or interface field use different aliases, GraphPilot reads the response path that matches each object:
query { search { # Returns Union type ... on Book { author { _gp_id: id } # Uses alias "_gp_id" } ... on Magazine { _gp_author: author { id } # Uses alias "_gp_author" for entire field } }}For @surrogateKey(of: "author.id"), a book is read at author._gp_id and yields
Query:search.author.id:BA1; a magazine is read at _gp_author.id and yields
Query:search.author.id:MA1. The key is the same whichever alias the client used, so a purge
reaches the response either way.
When a directive produces no key
Section titled “When a directive produces no key”A directive the deployment build refuses contributes no key, and the deployment still succeeds.
Every other key in the schema still applies, including a static value on the same directive, so
the first thing you notice without reading the diagnostics is a response that never invalidates.
The build refuses, with the type, the directive, and its line and column:
- an
ofnaming a field that does not exist, or a path that does not end in a scalar, enum, or list thereof; - an argument of the wrong type;
- a bare
@surrogateKeyon a type that needs a selection; - a directive written where no key can come from, such as inside
extend typeor on a field argument.
Read the diagnostics of your deployment. The portal
shows them under Schema → Findings for the live deployment and on each deployment’s page under
Deployments. gpilot deploy prints them when the deployment
finishes, and the GraphPilot API returns them too. Only the deployment build validates your
schema, so read its diagnostics.
Check them whenever you change a type that carries a key. If a field used in an of argument is
removed or renamed, the next deployment reports it and the directive produces no key from then
on. Keys already in the cache are not affected until they are invalidated or expire. To see the
keys your directives produced for real data, read the gp-surrogate-key
header.