Angelo Zambrano
Les comparto mi código en TypeScript:
Madrov
Con Grapi puedes crear una API GraphQL auto-generada. https://github.com/scalars/grapi
Mauricio Serginho Matias Conde
pasanos tu repo para ver la config con ts porfaa
Ya hemos visto cómo consultar información mediante GraphQL, pero en un API también vas a necesitar mandar información para que sea almacenada, dentro de GraphQL esto es posible gracias a la especificación mutation.
Un mutation va a requerir de un campo de tipo Input que son como plantillas que le van a indicar qué campos son necesarios para insertar o modificar información.
La sintaxis de una mutation queda de la siguiente manera:
nombreMutation(input: InputType): tipo
Angelo Zambrano
Les comparto mi código en TypeScript:
Madrov
Con Grapi puedes crear una API GraphQL auto-generada. https://github.com/scalars/grapi
Mauricio Serginho Matias Conde
pasanos tu repo para ver la config con ts porfaa
Rodrigo Luis
Oscar Martinez
Te funcionó normal el codigo de los resolvers? o hiciste alguna modificación, tambien estoy usando atlas y lo uncio que veo es en el dashboard de atlas que si hay operaciones pero en web no me retorna nada
Rodrigo Luis
Hola @oscar no cambie nada en los resolvers, solo en el archivo db.js
Un ejemplo de mutations que ando implementando:
createMalware: async (root, { input }) => { const defaults = { family: '', year: '', media: '' } const newMalware = Object.assign(defaults, input) let db let malware try { db = await connectDb () malware = await db.collection('Malwares').insertOne(newMalware) newMalware._id = malware.insertedId } catch (error){ errorHandler(error) } return newMalware },
!mutationsandinputs
Podemos reemplazar const newCourse simplemente con:
course = await db.collection('courses').insertOne({...defaults, ...input});
Brayan Cardozo
Muy buen curso, solo que lo tengo en x2 de velocidad y siento que aun habla muy despacio.
Nicolas Ticona Valdivia
Aparte de Query y Mutation hay otros types built-in ?
Alejandro Moreno Olaverri
Para utilizar GraphQL con una base de datos relacional como MySQL o PostgreSQL, seria bueno utilizar un ORM como sequelize??
Juan Castro
ProfesorQue sea 'bueno" o "malo" es relativo. :sweat_smile:
Algunas personas aman los ORMs. Pero otras aman tener el control total y absoluto de las consultas a la base de datos.
En este tutorial usamos sentencias SQL directamente. No está nada mal.
:point_right: Creating a scalable API using Node, GraphQL, MySQL, and Knex
Henry De La Hoz
Depende del tipo de proyectos que estás desarrollando. Para complementar la otra respuesta y reforzando el concepto de GraphQL, algo muy cool de la herramienta es que es completamente ajeno a la implementación que hagas para manipular tus datos, ni siquiera está atado a un lenguaje de programación (no necesariamente hay que implementar una API con node js). En conclusión, lo más probable es que cualquier tecnología que uses para la capa de datos, vas a poder integrarla fácil con GQL. Éxito Digital
Albert Johanson
Por si alguien lo esta implementando con mongoose
Resolvers
Courses: async () => { const courses = await Course.find() return courses; }, Course: async(root, args) => { const course = await Course.findById(args.id) return course }, }, Mutation: { createCourse: async(root, {input}) => { const newCourse = await Course.create(input) return newCourse } }
Reinaldo Mendoza
Genial, despues de solucionar algunos problemas para conectarme a la base de datos, todo esta funcionando correctamente
Reinaldo Mendoza
Que bueno que el profesor nos esta permitiendo ver esos errores porque como el dijo hace parte del desarrollo
Francisco Javier Suarez Verdugo
Estupenda clase instructor Adrián, queda claro cómo podemos usar GraphQL para hacer consultas y también inserciones de registros en la base de datos, me gusto la organización más estructurada al establecer los tres archivos (resolvers, queries y mutations).
Arturo Reygadas González
Ayuda!!! Estoy intentándolo con MySQL, pero no logro hacer que la mutación inserte.. alguien tiene algún ejemplo?
Enzo Tamaquiza Murillo
Rodrigo Luis
Alguien sabe como se llama el plugin que utilizar para mostrar hace cuento tiempo se hizo un cambio y el commit?
Rodrigo Luis
Ya lo encontré, se llama GitLens se ve interesante les dejo el link por si les interesa
Rodrigo Patiño
¡Gracias! Iba a preguntar lo mismo.
Miguel Angel Reyes Moreno
Jose Daniel Barría Reyes
muy buena clase!
Julio Ignacio Oyarzun Cayuman
Yo lo hice siguiendo los consejos de otros estudiantes y me funciono a la primera xD
Alex Abel Lerman
Danilo Valenzuela
Aiuuuda, los datos sí quedan guardados en la DB pero en la herramienta de GraphiQL se genera el siguiente error. "message": "Cannot return null for non-nullable field Course.description."
Juan Jose Vega
Estoy en las mismas, él lo soluciono con el await pero ahora no funciona :(
Paul Alexander Rodriguez Calixto
Buen dia, yo estoy haciendo el ejercicio con MySql, y me bloque por lo mismo, despues de tanto verificar descubri que en el type tenia campos que no estaba devolviendo la query, asi que fue error de digitacion, tambien otro error que tuve fue en el tipo de response que obtenia por que el respondia un array de objeto en donde la inforamcion estaba en la posicion [0] y yo estaba retornando todo el objeto, chekeate lo que response antes del return final, espero ser de ayuda
Jecsham Castillo
Con mongo no es necesario agregar campos como defaults
Juan Jose Vega
Pero si no se hace devuelve null
Al usar MongoDB Atlas y querer hacer un insertOne a la base de datos me salía el siguiente error
MongoError: w has to be a number or a string
Lo solucione en el archivo db.js agregando los parámetros de la URL(?retryWrites=true&w=majority) a los parámetros de la función connect
client = await MongoClient.connect(mongoUrl, { useNewUrlParser: true, retryWrites: true, w: 'majority' })
El código completo quedaría de la siguiente forma:
'use stric' const {MongoClient} = require('mongodb') const { DB_USER, DB_PASS, DB_HOST, DB_NAME, } = process.env const mongoUrl = `mongodb+srv://${DB_USER}:${DB_PASS}@${DB_HOST}/test` let connection async function connectDB () { if (connection) return connection let client try { client = await MongoClient.connect(mongoUrl, { useNewUrlParser: true, retryWrites: true, w: 'majority' }) connection = client.db(DB_NAME) } catch (error) { console.error('Could not connect to db', mongoUrl, error) process.exit(1) } return connection } module.exports = connectDB
Yo tambien estoy haciendo con MYSQL te dejo aqui el code si lo quieres intentar o seguir los pasos. SCHEMA
type Mutation { "crea un nuevo curso" createCurso(input: CursoInput!): Course } input CursoInput { titulo: String! descripcion: String! id_teacher: Int! } type Course { id_curso: ID titulo: String descripcion: String id_teacher: Int }
STORE
async function create_curso(input){ return await new Promise( (resolve, reject) => { db.query(`INSERT INTO curso (titulo, descripcion, id_teacher) VALUES ('${input.titulo}', '${input.descripcion}', ${input.id_teacher})`, (err, data) => { if(err) return reject(err); resolve(data); }); }); }
resolvers
createCurso: async (req) => { const data = await create_curso(req.input); console.log(data); return data; }
Mutations e Inputs
Las mutations sirven para insertar información.
Insertamos en schema.graphql:
input CourseInput { title: String! teacher: String description: String! topic: String } type Mutation { "Crea un curso" createCourse(input: CourseInput!): Course }
Creamos 'lib/mutations.js':
const connectDb = require('./db') module.exports = { createCourse: async (root, { input }) => { const defaults = { teacher: '', topic: '', } const newCourse = Object.assign(defaults, input) let db let course try { db = await connectDb() course = await db.collection('courses').insertOne(newCourse) newCourse._id = course.insertedId } catch (error) { console.error(error) } return newCourse } }
Creamos 'lib/queries.js':
const connectDb = require('./db') const { ObjectId } = require('mongodb') module.exports = { getCourses: async () => { let db let courses = [] try { db = await connectDb() courses = await db.collection('courses').find().toArray() //*Devuelve todos los cursos } catch (error) { console.console.error(error); } return courses }, getCourse: async (root, { id }) => { let db let course try { db = await connectDb() course = await db.collection('courses').findOne({ _id: ObjectId(id) }) } catch (error) { console.console.error(error); } return course } }
Modificamos resolvers.js:
const queries = require('./queries') const mutations = require('./mutations') module.exports = { Query: queries, Mutation: mutations }
Y si hacemos por ejemplo:
mutation { createCourse(input: { title: "Curso #4" description: "Descripción 4" topic: "Diseño" }) { _id title description } }
Obtendremos de regreso la información que creamos:
{ "data": { "createCourse": { "_id": "61679d9674f13179ec79bbc4", "title": "Curso #4", "description": "Descripción 4" } } }
tengo una duda. La API no me regresa tanto en getCourse como en la mutation nada a menos que el return sea un array. Por qué podrá ser?
let db; let course = []; try { db = await connectDb(); courseToAdd = await db .collection('courses') .findOne({ _id: ObjectID(_id) }); course.push(courseToAdd); } catch (error) { console.error(error); } return course;```
let db; let course;
try { db = await connectDb(); course = await db.collection('courses').insertOne(input); input._id = course.insertedId; } catch (error) { console.log(error); } return [input];
A menos que haga eso, me dice un error como este:
{ "errors": [ { "message": "Expected Iterable, but did not find one for field Mutation.createCourse.", "locations": [ { "line": 2, "column": 3 } ], "path": [ "createCourse" ] } ], "data": { "createCourse": null } }```
Por eso es que lo meti todo en array... pero está bien eso?