Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Mutations e Inputs

10/25
Recursos

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

Aportes 22

Preguntas 4

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

Les comparto mi código en TypeScript:

Mutation para insertar o guardar informacion

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

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
    },

Podemos reemplazar const newCourse simplemente con:

course = await db.collection('courses').insertOne({...defaults, ...input});

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
        }
    }

Genial, despues de solucionar algunos problemas para conectarme a la base de datos, todo esta funcionando correctamente

Que bueno que el profesor nos esta permitiendo ver esos errores porque como el dijo hace parte del desarrollo

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).

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"
    }
  }
}

Muy buen curso, solo que lo tengo en x2 de velocidad y siento que aun habla muy despacio.

muy buena clase!

Yo lo hice siguiendo los consejos de otros estudiantes y me funciono a la primera xD

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?

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.”

Ayuda!!! Estoy intentándolo con MySQL, pero no logro hacer que la mutación inserte… alguien tiene algún ejemplo?

Con mongo no es necesario agregar campos como defaults

Excelente clase

db.collection(‘courses’).insertOne(input) me retorna un objeto complejo :thinkingFace solo de esta manera puede acceder al ID course.ops[0]._id;

'use strict';
const connectDB = require('./db');

module.exports = {
  createCourse: async (root, { input }) => {
    let db, course;
    try {
      db = await connectDB();
      course = await db.collection('courses').insertOne(input);
      input._id = course.ops[0]._id;
    } catch (error) {
      console.error(error);
    }
    return input;
  },
};

A la fecha de este comentario si desean acceder a los queries y mutations desde el resolver se hace de esta manera:

No sé si mas adelante el profesor lo corrige pero recuerden que en el archivo queries.js es necesario definir la conexión a la base de datos y el ObjectID.

'use strict'

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()
        } catch(error) {
            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.error(error)
        }

        return course
    }
}

Comparto mi conexión a la base de datos:

const MongoClient = require('mongodb').MongoClient;
let connection;

async function connect(url) {
    if (connection) return connection.db("db01");
    
    let client;

    try {
        client = new MongoClient(url, { useNewUrlParser: true, useUnifiedTopology: true});
        connection = await client.connect();
        console.log('[db] succesfully connected');   
    } catch (error) {
        console.error('[db] could not connect to db ', url, error);
        process.exit(1);
    }

    return connection.db("db01");
}

module.exports = connect;