Introducción a GraphQL
GraphQL se divide en dos partes, el lenguaje de consultas que es la sintaxis utilizada para escribir consultas y un framework en el lado del servidor que se encarga de procesar las consultas.
En GraphQL se utiliza un sistema de tipado de datos que sirve para describir la forma en que se pueden recibir/enviar los datos y esto lo hace muy intuitivo pues con solo leer el schema donde están definidos los tipos de objetos que tiene el API, se puede intuir como es su uso.
Ejemplo el tipo de objeto Product
, se asemeja bastante al formato JSON y sin saber aun nada de GraphQL se puede ver que un Product
va a tener una propiedad id
, title
y price
.
Con GraphQL es muy sencillo solicitar datos anidados en una sola consulta. Por ejemplo un Product
puede tener una propiedad llamada collection
de tipo Collection
con sus respectivas propiedades.
GraphQL vs REST
REST es un estilo para escribir APIs donde se exponen funcionalidades para manipular recursos sobre urls con los verbos de http GET
, POST
, PUT
, DELETE
.
Recurso Product
:
- GET shopapi.com/products (Listado de todos los productos)
- GET shopapi.com/products/:id (Un producto por ID)
Recurso Collection
:
- GET shopapi.com/collections (Listado de todas las colecciones)
- GET shopapi.com/collections/:id (Una colección por ID)
Petición de un producto por ID en la url shopapi.com/products/001.
En la respuesta de este producto la propiedad collection
es un ID, entonces si se desea saber más información de esa colección se tiene que hacer otra petición:
shopapi.com/collections/100
Tradicionalmente así esa es la manera en la que funcionan las APIs allá afuera.
Ahora vamos a ver como sería esa consulta con GraphQL
{
query {
product(id: "product_1") {
title
price
collection {
title
}
}
}
}
Esta consulta se hace únicamente en una petición al servidor y la data de la propiedad collection
ya viene incluida. Además es posible especificar la forma de la respuesta escribiendo únicamente las propiedades que se necesitan de ella.
Terminología de GraphQL
- Queries .- Es lo que escribimos para hacer una consulta a un servidor GraphQL donde básicamente seleccionamos propiedades o fields de objetos.
- Fields .- Son propiedades que componen la forma de un tipo de objeto de consulta. Estos se incluyen o excluyen de la consulta para definir como queremos que sea la respuesta.
- Types .- Son un conjunto de fields que componen un tipo de objeto de consulta.
type Product {
id: ID!
title: String!
price: Float!
}
Apollo Launchpad
Tengo un Pad preparado para empezar a escribir nuestras primeras consultas GraphQL construido con Apollo Launchpad que es un servicio tipo CodePen pero para GraphQL.
https://launchpad.graphql.com/lkqqlww31q
- En el panel izquierdo se encuentra el lado del servidor.
- En el panel central es donde se escriben las consultas.
- En el panel derecho es se muestran los resultados.
En el panel izquierdo veremos un tipo de objeto llamado Product
que tiene los fields id
, title
, price
y collection
.
Para escribir una consulta comenzamos con la palabra query
y abrimos llaves como si fuera un JSON. Después escribimos el endpoint products
el cual nos regresará un listado de objetos de tipo Product
y por ultimo definimos la forma de la respuesta agregando únicamente las propiedades o fields que nos interesan de Product
por ejemplo title
y price
.
Anatomia de un Query
Un query o consulta de GraphQL se compone de tres partes:
Declaración de la consulta
Comienza con la declaración query
que le indica a GraphQL que únicamente queremos obtener información seguido de la apertura de llaves.
Endpoint
Llamada al endpoint que resolverá la consulta.
Fields
Definir la forma de la respuesta incluyendo o excluyendo los fields del tipo de objeto que regresa la consulta.
Scalar types
Cada objeto de consulta tiene sus propios fields definidos con un tipo de dato.
Con GraphQL por defecto se pueden utilizar los siguientes tipos de datos escalares o simples.
ID
Int
Float
String
Boolean
Object type field
Un objeto de consulta puede tener fields de tipo object
que a su vez se compone de otros fields escalares o de tipo object
.
Cuando se tiene un tipo de dato object
se debe especificar en la consulta que fields de ese object
se necesitan en la respuesta.
Mutation
Es una consulta especial en GraphQL para cambiar datos en el servidor. La anatomía de una consulta mutation es la siguiente:
Declaración de la consulta
Con la palabra mutation
que le indica a a GraphQL que vamos a cambiar algo, seguido de la apertura de llaves.
Endpoint
Llamado al endpoint que resolverá la consulta y los argumentos que necesita para procesar la consulta. En los argumentos es necesario especificar su nombre en formato de llave: valor.
Para saber que argumentos necesita podemos revisar la definición de la mutation en el schema, además podemos ver de que tipo es la respuesta.
(Todos los fields con el bang !
son requeridos).
Fields
Define la forma de la respuesta que regresa la consulta.
Mutaciones con objetos de entrada
En una mutation es posible utilizar fields o propiedades de tipo input object
que tienen sus propios fields escalares o de tipo object
.
Para escribir esta consulta nos podemos apoyar de variables de consulta de GraphQL. Estas variables de consulta se definen en formato JSON en el panel de Query Variables.
Tenemos un endpoint productVariantCreate
donde de acuerdo a su definición en el schema requiere que le pasemos como argumentos el productId
y el variant
que es un objeto de entrada.
También vamos a utilizar variable de consulta variantToAdd
como argumento en la mutation donde se debe especificar su tipo.
(Las variables de consulta en GraphQL se escriben como si fueran variables de PHP con el signo dólar al inicio).
Operaciones Nombradas
En GraphQL podemos dar nombre a las operaciones que realicemos. A esto se le conoce como Aliases.
Aliases
Esto es de mucha ayuda cuando queremos realizar multiples consultas al mismo endpoint con distintos argumentos en una sola petición.
Para agregar un alias lo escribimos antes de el endpoint seguido de dos puntos :
.
Si no se usan aliases y se intenta hacer un llamado al mismo endpoint mas de una vez, se ocasionará una coalición en el nombre de las llamadas sobre el mismo endpoint.
Un endpoint solo puede regresar un resultado a la vez. Entonces GraphQL nos va a sugerir que hagamos uso de aliases para renombrar el resultado de un endpoint y evitar la coalición de nombres.
Fragments
Se utilizan para agrupar fields sobre un tipo de objeto en específico y poder reutilizarlo en nuestras consultas para evitar la repetición.
Un fragment lo incluimos en una consulta de la siguiente manera:
Se define con la palabra fragment
, un nombre y el tipo de objeto al que pertenecen estas propiedades.