El segundo de tres artículos centrados en la construcción Fullstack React y GraphQL con Express y Couchbase Server.
- Configuración de un servidor NoSQL Couchbase (Parte 1)
- Creación de una API Express-GraphQL (Parte 2)
- Crear un cliente Apollo GraphQL en React (Parte 3)
- Código fuente final
GraphQL con Express
Si no está familiarizado con GraphQL, tómese unos minutos para ponerse al día utilizando la documentación GraphQL. Las siguientes páginas deberían ser un buen comienzo:
Requisitos previos
Crear la estructura del proyecto
Necesitamos crear un directorio en tu máquina para nuestro proyecto, lo llamaremos rage-with-couchbase:
|
1 |
mkdir rabia-con-couchbase && cd $_ |
mkdir creará un nuevo directorio utilizando la cadena rage-with-couchbase para el nombre de la carpeta, bash almacena esa cadena en una variable que podemos utilizar inmediatamente llamada $_.
cambiamos de directorio con $_ asegurándonos de no escribir mal el directorio en el comando concatenado (es magia de bash).
Ahora vamos a crear un .gitignore en la raíz de nuestro proyecto.
|
1 |
toque .gitignore && echo "/node_modules/*" >> .gitignore |
toque generará un .gitignore ignorando todos los node_modules en nuestro proyecto. Esto es importante porque como parte de nuestro proyecto de demostración fullstack React y GraphQL, estaremos rastreando cambios git desde la raíz rage-with-couchbase pero tendremos directorios de servidor y cliente con sus propios paquete.json y node_modules directorio.
echo añadirá el node_modules/ texto dentro del .gitignore esto servirá para ignorar todos los node_modules en la raíz y en todos los subdirectorios.
Creación de nuestro servidor Express
Ahora crearemos el directorio para almacenar nuestro servidor Express y usaremos npm para gestionar sus paquetes.
|
1 |
mkdir couchbase-gql-servidor && cd $_ && npm init -y |
mkdir creará una nueva carpeta dentro de la raíz del proyecto específicamente para nuestro servidor utilizando la cadena servidor couchbase-gql para el nombre, este es el directorio del proyecto de su servidor.
cambiamos de directorio y utilizamos $_ (más magia) y luego inicializamos un npm proyecto utilizando npm init -y aceptando los valores por defecto con el -y bandera.
Instalar dependencias de Express Server
|
1 |
npm instale graphql express express-graphql couchbase && npm instale nodemon -D && código . |
Una vez finalizada la instalación, tenemos que abrir nuestro proyecto con nuestro editor de elección. Yo prefiero VS Code.
Crear nuestro servidor GraphQL
|
1 |
toque servidor.js .gitignore && echo "/node_modules/*" >> .gitignore |
Requerir express/express-graphql/graphql en nuestro servidor.js file:
|
1 2 3 4 5 |
const express = requiere(exprés) const { graphqlHTTP } = requiere(express-graphql) const { construirEsquema } = requiere(graphql) const couchbase = requiere(couchbase) |
Las tres primeras importaciones son necesarias para nuestro servidor GraphQL y la última importación es necesaria para conectar y consultar nuestro servidor Couchbase.
Inicializar Express y conectarse a nuestro cubo
Añade el siguiente código:
|
1 2 3 4 5 6 |
const aplicación = express() const grupo = nuevo couchbase.Grupo(couchbase://localhost, { nombre de usuario: Administrador, contraseña: contraseña }) const cubo = grupo.cubo(muestra-viaje) var colección = cubo.defaultCollection(); |
Arriba estamos conectando a nuestro cluster de Couchbase Server, autenticando con nuestro usuario que configuramos, y abriendo nuestro viaje-muestra cubo. Nunca utilice nombres de usuario y contraseñas por defecto en aplicaciones de producción.
Crear nuestro esquema GraphQL
Añadiendo el siguiente código definiremos dos endpoints que permitirán a nuestro GraphQL Server acceder y recuperar datos de nuestros documentos dentro de nuestro bucket de 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 esquema = construirEsquema(` tipo Línea aérea { id: Int, Indicativo: Cadena, país: Cadena, iata: Cadena, icao: Cadena, nombre: Cadena, tipo: Cadena } entrada AirlineInput { Indicativo: Cadena, país: Cadena, iata: Cadena, icao: Cadena, nombre: Cadena, tipo: Cadena } tipo Consulta { compañías aéreasUK: [Línea aérea], airlineByKey(id: Int!): Línea aérea airlinesByRegion(región: Cadena!): [Línea aérea] } tipo Mutación { actualizarLínea aérea(id: Int!, entrada: AirlineInput): Línea aérea } |
En Consulta especifica qué Consultas GraphQL pueden ejecutar contra su propio gráfico de datos.
Tenemos dos puntos finales definidos por Consulta. Uno llamado "airlinesUK" y el otro "airlineByKey". En nuestra aplicación React, sólo utilizaremos el endpoint "airlinesUK". Hice el endpoint "airlineByKey" simplemente para mostrar un ejemplo de recuperación de un único documento Couchbase por clave. Esta operación no utiliza el lenguaje de consulta N1QL y por lo tanto no tiene ninguna sobrecarga adicional. Entender cuándo y dónde usar cada uno es importante desde la perspectiva de la construcción de la API, no querríamos usar una consulta N1QL para devolver un único documento que podemos obtener por clave.
En nuestro código GraphQL, tenemos un objeto de tipo Línea aérea. Este objeto modela la estructura del documento que se encuentra en nuestro Couchbase viaje-muestra donde el tipo es "aerolínea".
A continuación, tenemos un Endpoint llamado "compañías aéreasUK". Observe que el valor de retorno de este punto final es una matriz de Aerolíneas: [Aerolínea]. Esto significa que volveremos a recibir una lista de compañías aéreas.
También tenemos "airlineByKey"donde obtendremos un único archivo Línea aérea.
Si recuerda nuestras imágenes de Bucket anteriores, cada documento se define mediante una clave con un formato como el siguiente aerolínea_1234 donde 1234 es el id de la compañía aérea.

Mantendremos este id a la hora de utilizar el SDK de NodeJS para obtener nuestro airlineByKey utilizando un simple bucket.get() método.
Crear nuestra implementación de Resolver para cada punto final
Ahora, que hemos definido dos consultas en nuestra API GraphQL-Express utilizando nuestro esquema necesitamos una implementación en JavaScript para recuperar los datos.
Nuestra aplicación React que vamos a crear sólo necesitará el archivo N1QL consulta denominada compañías aéreasUK.
Pero quería mostrarte cómo consultar sin N1QL utilizando la API del SDK de NodeJS utilizando sólo una clave o extendiéndola para utilizar una región (US/UK, etc..), que es la airlineByKey y airlineByRegion aplicación.
Añada el siguiente código a nuestro servidor.js para nuestras consultas N1QL:
(En su código JS, asegúrese de escapar los backticks con barras invertidas)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// Definir consultas N1QL const líneas aéreasUkQuery = ` SELECCIONE aerolínea.* DESDE `viaje-muestra` AS aerolínea DONDE aerolínea.tipo = aerolínea Y aerolínea.país = Reino Unido ` const airlinesByRegionQuery = ` SELECCIONE aerolínea.* DESDE `viaje-muestra` AS aerolínea DONDE aerolínea.tipo = aerolínea Y aerolínea.país = $REGIÓN ` |
Añada el siguiente código a nuestro servidor.js para nuestros 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 raíz = { compañías aéreasUK: async () => { const resultado = await grupo.consulta(líneas aéreasUkQuery) devolver resultado.filas }, /* consulta getAirlinesUK { airlinesUK { id nombre Indicativo país iata icao } } */ airlinesByRegion: async ({región}) => { const opciones = { parámetros: { REGIÓN: región } } const resultado = await grupo.consulta(airlinesByRegionQuery, opciones) devolver resultado.filas }, /* query getAirlinesByRegion($region: String!) { airlinesByRegion(region:$region) { id nombre Indicativo país iata icao } } { "región": "{{country}}" } */ airlineByKey: async ({id}) => { const resultado = await colección.consiga(`aerolínea${id}`) devolver resultado.valor }, /* query getAirlineByKey($id: Int!) { airlineByKey(id:$id) { id nombre Indicativo país iata icao } } { "id": {{id}} } */ actualizarLínea aérea: async ({id, entrada}) => { const resultado = await colección.consiga(`aerolínea${id}`) const nuevoDocumento = { ...resultado.contenido, Indicativo: entrada.Indicativo ? entrada.Indicativo : resultado.valor.Indicativo, país: entrada.país ? entrada.país : resultado.valor.país, iata: entrada.iata ? entrada.iata : resultado.valor.iata, icao: entrada.icao ? entrada.icao : resultado.valor.icao, nombre: entrada.nombre ? entrada.nombre : resultado.valor.nombre, }; consola.registro(nuevoDocumento) await colección.upsert(`aerolínea${id}`, nuevoDocumento) devolver nuevoDocumento } /* mutación updateExistingAirline($id:Int!, $input:AirlineInput) { updateAirline(id:$id, input:$input){ Indicativo país iata } } { "id": 112, "entrada": { "Indicativo": "FLYSTAR", "country": "Reino Unido" } } */ } |
Nota: En la sentencia N1QL anterior, tendrá que escapar los puntos suspensivos en la línea FROM alrededor de con barras invertidas. El ejemplo de código de nuestro blog no muestra esas barras invertidas, pero están ahí y se encuentran en el archivo Código fuente finalviaje-muestra
Para entenderlo mejor, estamos utilizando dos métodos diferentes para consultar nuestro servidor Couchbase.
El primer método corresponde al compañías aéreasUK endpoint, este es su resolver. Necesitamos devolver una promesa y dentro confiar en bucket.querypara tomar una consulta N1QL predefinida que he desglosado línea por línea en la variable statement para facilitar la lectura. Poder ejecutar este tipo de consulta SQL es muy potente para una base de datos de documentos. Gran parte del SQL que conocemos se transfiere y esto es un gran alivio en comparación con otras bases de datos de documentos que tienen una nueva API y un lenguaje de consulta que tendrás que aprender.
El segundo método corresponde al compañías aéreasUK endpoint, este es su resolver. Necesitamos devolver una promesa y dentro confiar en cubo.get y en este caso, sólo estamos definiendo la clave de nuestro documento. Recuerde que una de las grandes cosas sobre el uso de un almacén de datos clave-valor es que podemos elegir fácilmente un solo documento con poca sobrecarga.
Cada uno de los métodos anteriores también comprueba si hay errores de consulta y los resuelve o los rechaza en función de un valor de resultado o error.
Creación de nuestro GraphQL con Express Server
Ahora que tenemos todo resuelto para nuestros puntos finales y consultas, todo lo que tenemos que hacer es utilice nuestro servidor Express y darle un puerto para ejecutar, vamos a hacer eso ahora.
Añade el siguiente código al final de nuestro servidor.js file:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
/* La función graphqlHTTP acepta un esquema, rootValue y graphiql entre otras opciones para configurar nuestro GraphQL Server */ const serverPort = 4000 const serverUrl = /graphql aplicación.utilice(serverUrl, graphqlHTTP({ esquema: esquema, rootValue: raíz, graphiql: verdadero })) aplicación.escuche( serverPort, () => consola.registro(`GraphQL servidor corriendo: http://localhost:${serverPort}${serverUrl}`) ) |
Si alguna vez has creado un servidor Express o Express-GraphQL, este código debería resultarte familiar.
En primer lugar, configuramos nuestro puerto y URL GraphQL.
A continuación, pasamos nuestro esquema GraphQL y sus resolvers y establecemos nuestro graphiql a true. (Esto nos dará un IDE para probar nuestras consultas GraphQL disponibles en localhost:4000/graphql.
Por último, escuchamos en el puerto 4000 y ponemos un mensaje en la consola para indicar que nuestro servidor se está ejecutando.
Vamos a ejecutar nuestro servidor, asegúrese de que su Couchbase:
|
1 |
nodo servidor |
Una vez que tenemos el servidor GraphQL en funcionamiento podemos probar la aplicación Compañías aéreasUK pegando el siguiente código en el panel de consultas de GraphQL IDE:
|
1 2 3 4 5 6 7 8 9 10 |
consulta getAirlinesUK{ compañías aéreasUK { id nombre Indicativo país iata icao } } |
Como indica la consulta, recuperará todas las compañías aéreas con base en el Reino Unido:

A continuación, utilizaremos la función airlineByKey en este ejemplo, también tendremos que crear una variable de consulta y pegarla en el panel correspondiente:
|
1 2 3 4 5 6 7 8 9 10 |
consulta getAirlineByKey($id: Int!) { airlineByKey(id:$id){ id nombre Indicativo país iata icao } } |
|
1 2 3 |
{ "id": 112 } |
Y con eso en su lugar y podemos consultar de nuevo y recuperar un solo documento de la aerolínea por clave:

Con una configuración super sencilla de la API GraphQL, estamos listos para crear nuestra aplicación react que utilizará estos endpoints para una página maestro-detalle utilizando las aerolíneas del Reino Unido en un componente de lista y cuando hagamos clic en una aerolínea en particular, otro componente mostrará los detalles completos de la aerolínea en la parte derecha de la página.