Inscreva-se em minha Newsletter
O GraphQL é apenas uma linguagem de consulta para sua API. Eu acho que o GraphQL é uma boa alternativa ao REST. O GraphQL facilita muito a programação no front-end, pois permite o uso de um único endpoint
, o que reduz o tempo de resposta evitando Over-Fetching ou Under-fetching.
O Over-Fetching (excesso de consultas) ocorre quando campos adicionais são declarados em um fragmento, mas na verdade não são usados no modelo. Isso provavelmente acontecerá quando um código executado.
O Under-fetching (consulta insuficiente) ocorre quando os campos não são declarados em um fragmento, mas são usados em um modelo. Esses dados ausentes provavelmente aparecerão como NoFieldError
ou valor null
.
Nos dois casos, são problemas de desempenho: você deve estar usando mais banda do que deveria ou está fazendo mais solicitações HTTP do que deveria.
Em um mundo perfeito, esses problemas nunca surgiriam; você só tem os endpoints certos para fornecer os dados certos aos seus produtos.
Esses problemas geralmente aparecem quando você dimensiona e interage com seus produtos. Os dados que você usa nas suas páginas geralmente mudam e os custos para manter um endpoint
separado com apenas os dados corretos para cada componente se tornam excessivos.
Portanto, você acaba com um compromisso entre não ter muitos endpoints e fazer com que eles se ajustem às necessidades de cada componente. Isso levará ao Over-Fetching em alguns casos e ao Under-fetching em outros (será necessário chamar um segundo endpoint
).
Portanto, o GraphQL corrige esse problema porque permite solicitar quais dados você deseja para o servidor. Você especifica o que precisa e deseja obter desses dados, em uma única requisição ao servidor.
No entanto, esses benefícios têm um custo, um schema query e um resolver.
Aqui vou explicar como conectar o GraphQL ao PostgreSQL
Afinal, é bem simples, a única coisa que você precisa fazer é implementar adequadamente os métodos de resolução de query e mutation.
PostgreSQL Database
CREATE TABLE people (
id serial PRIMARY KEY,
firstname varchar(40) NOT NULL,
lastname varchar(40) NOT NULL
);
CREATE TABLE emails (
id serial PRIMARY KEY,
email varchar(256) NOT NULL,
person integer REFERENCES people (id),
“primary” boolean DEFAULT false
);
A primeira tabela representa as pessoas e a segunda representa os e-mails das pessoas.
GraphQL Schema
Query {
person(id: ID): Person
}
type Person {
id: ID
firstname: String
lastname: String
emails: [Email!]!
}
type Email {
id: ID
email: String
primary: Boolean
}
Query
SELECT * FROM "emails" WHERE person=person.id;
Quero listar todos os emails de uma única pessoa.
O primeiro passo é pegar o ID da pessoa e buscar os e-mails vinculados a essa pessoa.
Configurando o Express Server
const express = require('express');
const expressGraphQL = require('express-graphql');
const schema = require('./schema');
const app = express();
app.use('/graphql', expressGraphQL({
schema,
graphiql: true
}))
app.listen(4000, () => {
console.log('Listening...')
})
Primeiro, você deve instalar o express
e express-graphql
.
$ npm install express
npm install --save express-graphql
Você verá como definir a configuração que eu estou requisitando na parte superior.
Então, eu tenho o Graphiql definido como true
. O Graphiql é um IDE do GraphQL no qual posso verificar facilmente minhas consultas. Quando o GraphiQL faz uma solicitação, o GraphQL acessa meu banco de dados e diz: “Estou procurando por essa pessoa específica.”
Se você se perguntou, nossa solicitação será assíncrona.
Configurando o GraphQL Schema
const graphql = require('graphql');
const connectionString = 'myURI';
const pgp = require('pg-promise')();
const db = {}
db.conn = pgp(connectionString);
const {
GraphQLObjectType,
GraphQLID,
GraphQLString,
GraphQLBoolean,
GraphQLList,
GraphQLSchema
} = graphql;
const PersonType = new GraphQLObjectType({
name: 'Person',
fields: () => ({
id: { type: GraphQLID },
firstname: { type: GraphQLString },
lastname: { type: GraphQLString },
emails: {
type: new GraphQLList(EmailType),
resolve(parentValue, args) {
const query = `SELECT * FROM "emails" WHERE
person=${parentValue.id}`;
return db.conn.many(query)
.then(data => {
return data;
})
.catch(err => {
return 'The error is', err;
});
}
}
})
})
const EmailType = new GraphQLObjectType({
name: 'Email',
fields: {
id: { type: GraphQLID },
email: { type: GraphQLString },
primary: { type: GraphQLBoolean }
}
})
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
person: {
type: PersonType,
args: { id: { type: GraphQLID } },
resolve(parentValue, args) {
const query = `SELECT * FROM "people" WHERE id=${args.id}`;
return db.conn.one(query)
.then(data => {
return data;
})
.catch(err => {
return 'The error is', err;
});
}
},
emails: {
type: EmailType,
args: { id: { type: GraphQLID } },
resolve(parentValue, args) {
const query = `SELECT * FROM "emails" WHERE id=${args.id}`;
return db.conn.one(query)
.then(data => {
return data;
})
.catch(err => {
return 'The error is', err;
});
}
}
}
})
module.exports = new GraphQLSchema({
query: RootQuery
})
Estou usando o pg-promise
para conectar ao meu banco de dados. Então, eu estou definindo todos os tipos que vou usar.
Você pode ver uma diferença entre os campos no EmailType
e no PersonType
. Os campos de email
são um objeto simples, mas o PersonType
é agrupado com um arrow function.
Por que isso?
Se deixarmos como um objeto simples e quisermos executar esse código, apresentará o seguinte erro: "EmailType is not defined"
. Isso ocorre porque o Javascript não sabe sobre o EmailType
ao declarar PersonType
, porque EmailType
é declarado após PersonType
.
Podemos mover o EmailType
para antes do PersonType
e ele funcionará no EmailType
, então teremos outra propriedade conectada ao PersonType
.
A maneira como as tags de fechamentos funcionam dentro do javascript - a função é definida, mas não é executada até depois que todo esse arquivo foi executado.
Esse não é um problema do GraphQL, é um problema de como o javascript trata closures (fechamentos) e closure scopes (escopos de fechamento). Saiba mais.
Inicie seu código com:
node server.js
Visite:
http://localhost:4000/graphql
Adicione a consulta de cliente:
query {
person(id: "1") {
id
firstname
lastname
emails {
id
email
verified
}
}
}
Execute a consulta e veja os resultados.
Espero que este exemplo básico te ajude a entender melhor o GraphQL.