O segundo de três artigos focados na criação de React Fullstack e GraphQL com o Express e o Couchbase Server.
- Configuração de um servidor NoSQL Couchbase (Parte 1)
- Criação de uma API Express-GraphQL (Parte 2)
- Criar um cliente Apollo GraphQL em React (Parte 3)
- Código-fonte final
GraphQL com o Express
Se não estiver familiarizado com o GraphQL, reserve alguns minutos para se atualizar usando a documentação do GraphQL. As páginas a seguir devem ser um bom começo:
Pré-requisitos
Criar estrutura de projeto
Precisamos criar um diretório em seu computador para nosso projeto, que chamaremos de raiva com base de toque:
|
1 |
mkdir rage-with-couchbase && cd $_ |
mkdir criará um novo diretório usando a string raiva com base de toque para o nome da pasta, o bash armazena essa string em uma variável que podemos usar imediatamente chamada $_.
alteramos os diretórios usando $_ garantindo que não digitemos incorretamente o diretório no comando concatenado (é a mágica do bash).
Agora vamos criar um .gitignore na raiz do nosso projeto.
|
1 |
touch .gitignore && echo "/node_modules/*" >> .gitignore |
toque gerará um .gitignore ignorando todos os arquivos módulos_nó e subdiretórios em nosso projeto. Isso é importante porque, como parte do nosso projeto de demonstração fullstack React e GraphQL, rastrearemos as alterações do git a partir da raiz raiva com base de toque mas teremos diretórios de servidor e cliente com seus próprios package.json e módulos_nó diretório.
eco adicionará o node_modules/ texto dentro do .gitignore isso servirá para ignorar todos os arquivos módulos_nó na raiz e em todos os subdiretórios.
Criando nosso Express Server
Agora, criaremos o diretório para armazenar nosso servidor Express e usaremos o npm para gerenciar seus pacotes.
|
1 |
mkdir couchbase-gql-server && cd $_ && npm init -y |
mkdir criará uma nova pasta dentro da raiz do projeto especificamente para nosso servidor usando a string servidor couchbase-gql para o nome, esse é o diretório do projeto do servidor.
mudamos de diretório e usamos o $_ (mais mágica) e, em seguida, inicializamos um npm projeto usando npm init -y aceitando os valores padrão com a opção -y bandeira.
Instalar as dependências do Express Server
|
1 |
npm install graphql express express-graphql couchbase && npm install nodemon -D && code . |
Após a conclusão da instalação, precisamos abrir o projeto com o editor de nossa preferência. Eu prefiro o VS Code.
Criar nosso servidor GraphQL
|
1 |
touch server.js .gitignore && echo "/node_modules/*" >> .gitignore |
Exigir express/express-graphql/graphql em nossa servidor.js file:
|
1 2 3 4 5 |
const express = require('express') const { graphqlHTTP } = require('express-graphql') const { buildSchema } = require('graphql') const couchbase = require('couchbase') |
As três primeiras importações são necessárias para o nosso servidor GraphQL e a última importação é necessária para a conexão e a consulta ao nosso servidor Couchbase.
Inicializar o Express e conectar-se ao nosso Bucket
Adicione o seguinte código:
|
1 2 3 4 5 6 |
const app = express() const cluster = new couchbase.Cluster('couchbase://localhost', { username: 'Administrator', password: 'password' }) const bucket = cluster.bucket('travel-sample') var collection = bucket.defaultCollection(); |
Acima, estamos nos conectando ao nosso cluster do Couchbase Server, autenticando com o usuário que configuramos e abrindo nosso amostra de viagem balde. Nunca use nomes de usuário e senhas padrão em aplicativos de produção.
Criar nosso esquema GraphQL
A adição do código abaixo definirá dois pontos de extremidade que permitirão que o nosso servidor GraphQL acesse e recupere dados dos nossos documentos dentro do nosso bucket do Couchbase Server.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
const schema = buildSchema(` type Airline { id: Int, callsign: String, country: String, iata: String, icao: String, name: String, type: String } input AirlineInput { callsign: String, country: String, iata: String, icao: String, name: String, type: String } type Query { airlinesUK: [Airline], airlineByKey(id: Int!): Airline airlinesByRegion(region: String!): [Airline] } type Mutation { updateAirline(id: Int!, input: AirlineInput): Airline } |
O Consulta especifica qual tipo de Consultas GraphQL clientes podem executar em seu próprio gráfico de dados.
Temos dois pontos de extremidade definidos por isso Consulta. Um chamado "airlinesUK" e o outro "airlineByKey". Em nosso aplicativo React, usaremos apenas o endpoint "airlinesUK". Criei o endpoint "airlineByKey" simplesmente para mostrar um exemplo de recuperação de um único documento do Couchbase por chave. Essa operação não usa a linguagem de consulta N1QL e, portanto, não tem nenhuma sobrecarga adicional. Entender quando e onde usar cada uma delas é importante do ponto de vista da criação da API; não queremos usar uma consulta N1QL para retornar um único documento que podemos obter por chave.
Em nosso código GraphQL, temos um objeto do tipo Companhia aérea. Esse objeto modela a estrutura do documento encontrada em nosso Couchbase amostra de viagem onde o tipo é "companhia aérea".
Em seguida, temos um endpoint chamado "companhias aéreasUK". Observe que o valor de retorno desse ponto final é uma matriz de Airline: [Companhia aérea].. Isso significa que receberemos uma lista de companhias aéreas de volta.
Também temos "companhia aéreaByKey", onde buscaremos um único Companhia aérea.
Se você se lembra das imagens do Bucket acima, cada documento é definido por uma chave em um formato como companhia aérea_1234 onde 1234 é o id da companhia aérea.

Manteremos isso id em mente ao usar o SDK do NodeJS para buscar nossos companhia aéreaByKey usando um simples bucket.get() método.
Criar nossa implementação de resolvedor para cada endpoint
Agora que definimos duas consultas em nossa API GraphQL-Express usando nosso esquema precisamos de uma implementação em JavaScript para recuperar os dados.
Nosso aplicativo React que criaremos precisará apenas do N1QL consulta nomeada companhias aéreasUK.
Mas eu queria mostrar a você como fazer consultas sem N1QL usando a API do SDK do NodeJS usando apenas uma chave ou estendendo-a para usar uma região (EUA/Reino Unido, etc.), que é o companhia aéreaByKey e companhia aérea por região implementação.
Adicione o seguinte código ao nosso servidor.js para nossas consultas N1QL:
(Em seu código JS, certifique-se de escapar dos sinais de barra invertida com barras invertidas)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// Define N1QL Queries const airlinesUkQuery = ` SELECT airline.* FROM `travel-sample` AS airline WHERE airline.type = 'airline' AND airline.country = 'United Kingdom' ` const airlinesByRegionQuery = ` SELECT airline.* FROM `travel-sample` AS airline WHERE airline.type = 'airline' AND airline.country = $REGION ` |
Adicione o seguinte código ao nosso servidor.js para nossos resolvedores GraphQL:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
const root = { airlinesUK: async () => { const result = await cluster.query(airlinesUkQuery) return result.rows }, /* query getAirlinesUK { airlinesUK { id name callsign country iata icao } } */ airlinesByRegion: async ({region}) => { const options = { parameters: { REGION: region } } const result = await cluster.query(airlinesByRegionQuery, options) return result.rows }, /* query getAirlinesByRegion($region: String!) { airlinesByRegion(region:$region) { id name callsign country iata icao } } { "region": "{{country}}" } */ airlineByKey: async ({id}) => { const result = await collection.get(`airline_${id}`) return result.value }, /* query getAirlineByKey($id: Int!) { airlineByKey(id:$id) { id name callsign country iata icao } } { "id": {{id}} } */ updateAirline: async ({id, input}) => { const result = await collection.get(`airline_${id}`) const newDocument = { ...result.content, callsign: input.callsign ? input.callsign : result.value.callsign, country: input.country ? input.country : result.value.country, iata: input.iata ? input.iata : result.value.iata, icao: input.icao ? input.icao : result.value.icao, name: input.name ? input.name : result.value.name, }; console.log(newDocument) await collection.upsert(`airline_${id}`, newDocument) return newDocument } /* mutation updateExistingAirline($id:Int!, $input:AirlineInput) { updateAirline(id:$id, input:$input){ callsign country iata } } { "id": 112, "input": { "callsign": "FLYSTAR", "country": "United Kingdom" } } */ } |
Observação: Na instrução N1QL acima, você precisará escapar dos pontos finais na linha FROM em torno de com barras invertidas. O exemplo de código do nosso blog não mostra essas barras invertidas, mas elas estão lá e estão na seção Código-fonte finalamostra de viagem
Apenas para esclarecer isso, estamos usando dois métodos diferentes para consultar nosso Couchbase Server.
O primeiro método corresponde ao companhias aéreasUK este é o seu resolvedor. Precisamos retornar uma promessa e, dentro dela, confiar no bucket.querypara usar uma consulta N1QL predefinida que eu dividi linha por linha na variável de instrução para facilitar a leitura. A capacidade de executar esse tipo de consulta SQL é muito poderosa para um banco de dados de documentos. Muito do SQL que conhecemos é transferido e isso é um grande alívio em comparação com outros bancos de dados de documentos que têm uma API totalmente nova e uma linguagem de consulta que você precisará aprender.
O segundo método corresponde ao companhias aéreasUK este é o seu resolvedor. Precisamos retornar uma promessa e, dentro dela, confiar no bucket.get e, nesse caso, estamos apenas definindo a chave do nosso documento. Lembre-se de que uma das vantagens de usar um armazenamento de dados de valor-chave é que podemos escolher facilmente um único documento com pouca sobrecarga.
Cada um dos métodos acima também testa os erros de consulta e os resolve ou rejeita com base em um resultado ou erro.
Criando nosso GraphQL com o Express Server
Agora que temos tudo organizado para nossos endpoints e consultas, tudo o que precisamos fazer é uso nosso servidor Express e fornecer a ele uma porta para execução, vamos fazer isso agora.
Adicione o seguinte código ao final do nosso servidor.js file:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
/* The graphqlHTTP function accepts a schema, rootValue and graphiql among other options for configuring our GraphQL Server */ const serverPort = 4000 const serverUrl = '/graphql' app.use(serverUrl, graphqlHTTP({ schema: schema, rootValue: root, graphiql: true })) app.listen( serverPort, () => console.log(`GraphQL server running: https://localhost:${serverPort}${serverUrl}`) ) |
Se você já criou um servidor Express ou Express-GraphQL, esse código deve lhe parecer familiar.
Primeiro, configuramos nossa porta e o URL do GraphQL.
Em seguida, passamos nosso esquema GraphQL e seus resolvedores e definimos nosso gráfico para true. (Isso nos dará um IDE para testar nossas consultas GraphQL disponíveis em localhost:4000/graphql.
Por fim, escutamos na porta 4000 e definimos uma mensagem no console para indicar que nosso servidor está em execução.
Vamos executar nosso servidor e garantir que seu Couchbase:
|
1 |
node server |
Assim que tivermos o servidor GraphQL em execução, poderemos testar o Companhias aéreasUK colando o código a seguir no painel de consulta do GraphQL IDE:
|
1 2 3 4 5 6 7 8 9 10 |
query getAirlinesUK{ airlinesUK { id name callsign country iata icao } } |
Como a consulta indica, ele recuperará todas as nossas companhias aéreas baseadas no Reino Unido:

Em seguida, usaremos o companhia aéreaByKey neste exemplo, também precisaremos criar uma variável de consulta e colá-la no respectivo painel:
|
1 2 3 4 5 6 7 8 9 10 |
query getAirlineByKey($id: Int!) { airlineByKey(id:$id){ id name callsign country iata icao } } |
|
1 2 3 |
{ "id": 112 } |
Com isso em mãos, podemos consultar novamente e recuperar um único documento da companhia aérea por chave:

Com uma configuração super simples da API GraphQL, estamos prontos para criar nosso aplicativo react que usará esses endpoints para uma página mestre de detalhes usando as companhias aéreas do Reino Unido em um componente de lista e, quando clicarmos em uma companhia aérea específica, outro componente mostrará os detalhes completos da companhia aérea no lado direito da página.