No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Nested Types

12/25
Recursos

Aportes 16

Preguntas 2

Ordenar por:

Los aportes, preguntas y respuestas son vitales para aprender en comunidad. Regístrate o inicia sesión para participar.

Con Mongoose se podria tener un codigo mas ordenado y consultas a la base de datos mas simple

Otra cosa que podriamos hacer para poder tener un mejor codigo es abstraer la logica de la base de datos en un archivo por aparte y unicamente a los queries y mutations exponerles una interfaz por la cual hagan los inserts, updates, etc… También si la abstraemos hacemos que los archivos no sepan que base de datos se este usando y asi hacer algo mas mantenible.
Les dejo mi codigo:

😁 Una de las cosas que me costó cuando trate de implementar GraphQL fue el performance, sobre todo en este tema cuando haces cargas de datos de objetos relacionados, y aun más si es sobre base de datos relacionarles, así que me cree esta función que me ayudo a suplir este problema

const fields = (context) => {
  const items = context.fieldNodes[0].selectionSet.selections.map((item) => {
    return item.name.value
  });
  return items;
}

exports.fields = fields;
const { City } = require('../db/');
const { fields } = require('../util');

const cities = async (resolve, root, args, context, info) => {
  const related = fields(context).includes('related');

  let query = City.query().whereNull('city_id');
  query = related ? query.eager('related') : query;

  return query;
};

module.exports = cities;

de esta forma solo cargo las relaciones solo si él usuario lo solicito.

Si alguien conoce una mejor forma de hacerlo 🤓 compártalo

$addToSet comprueba si es un arreglo y si no lo es crear el arreglo y añade el valor del ID de persona.

Es el segundo curso donde veo que usan mongodb en vez de mongoose, me parece que con mongoose es más simple de trabajar.

Pude implementar los nested types, agregando un proveedor de información a los datos de un malware.

    addProvider: async (root, { malwareID, companyID }) => {
        let db
        let malware
        let provider


        try {
                db = await connectDb()
                malware = await db.collection('Malwares').findOne({ 
                    _id: ObjectID(malwareID) 
                })
                provider = await db.collection('Companies').findOne({ 
                    _id: ObjectID(companyID) 
                })
        
        if (!malware || !provider) throw new Error ('La empresa que provee información o el malware no existe')
        
        await db.collection ('Malwares').updateOne(
            { _id: ObjectID(malwareID) },
            { $addToSet: { info_provider: ObjectID(companyID) } }
        )} catch (error){
            errorHandler(error)
        }

        return malware
    }

esos metodos updateOne, findOne, insertOne, son de mongo, pero si quisiera utilizar los de otro tipo de base de datos como mysql o postgres utilizaría los conocidos Select, Insert, Update, Delete…?

Nested Types

Modificamos el schema:

type Course {
    _id: ID!
    title: String!
    teacher: String
    description: String!
    topic: String
    people: [Student]
}

type Mutation {
    "Agrega una persona a un curso"
    addPeople(courseID: ID!, personID: ID!): Course
}

Añadimos la función a mutations.js:

addPeople: async (root, { courseID, personID }) => {
    let db
    let person
    let course
    try {
        db = await connectDb()
        course = await db.collection('courses').findOne({ _id: ObjectId(courseID) })
        person = await db.collection('students').findOne({ _id: ObjectId(personID) })
        if (!course || !person) {
            throw new Error('La persona o el curso no existe')
        }
        await db.collection('courses').updateOne({ _id: ObjectId(courseID) }, { $addToSet: {people: personID } })
    } catch (error) {
        console.error(error)
    }
    return course
    }

Y ahora podemos insertar IDs de estudiantes a los cursos:

mutation {
  addPeople(courseID:"61679d9674f13179ec79bbc4", personID:"6167a46f1479b7347a98b23c"){
    _id
    title
  }
}

Un pequeño detalle y esque el operador $addToSet Busca el campo y si no es un arreglo , va a fallar o tirar un error , no va a convertir el campo a un arreglo. caso contrario que si cuando buscara el campo y este campo simplemente no existe ahi si creara el campo y un arreglo con el valor que le dijimos que insertara.
.
si el campo si es un arreglo , buscara que no exista el valor que va a insertar y si efectivamente no existe ahi añadira el valor . si el valor ya existe simplemente no hara nada , no agregara un duplicado.
.
Lo dice en la documentacion

Excelente clase

Se entendio todo muy claro, ya quiero consumirlo desde una pagina jajjajajaj

Si yo quiesiera hacer un api multibase de datos tendría que hacer el api para cada base de datos, o puedo utilizar un ORM y por ejemplo que ORM?

schema.graphql

type Mutation {
  "Crea un curso"
  createCourse(input: CourseInput!): Course
  "Edita un curso"
  editCourse(_id: ID!, input: CourseEditInput): Course
  "Borrar un curso"
  deleteCourse(_id: ID!): String
  "Crea un estudiante"
  createStudent(input: StudentInput!): Student
  "Edita un estudiante"
  editStudent(_id: ID!, input: StudentEditInput): Student
  "Borra un estudiante"
  deleteStudent(_id: ID!): String
  "Agrega una persona a un curso"
  addPeople(courseID: ID!, personID: ID!): Course
}

mutations.js

    addPeople: async (root, { courseID, personID }) => {
        let db
        let person
        let course
        try {
            db = await connectDb()
            course = await db.collection('courses').findOne({ _id: ObjectId(courseID) })
            person = await db.collection('students').findOne({ _id: ObjectId(personID) })

            if (!course || !person) throw new Error('La persona o el curso no existe')

            await db.collection('courses').updateOne(
                { _id: ObjectId(courseID) },
                { $addToSet: { people: ObjectId(personID) }}
            )

        } catch (error) {
            console.error(error)
        }
        return course
    }

Hola Devs:
Codigo de esta clase:

-Para mas detalle pueden entrar a mi repositorio, especificamente al commit de esta clase: Click Aqui

Recuerden, #NuncaParesDeAprender 💚

Para organizar mi codigo lo hice de la siguiente manera, espero les sriva. 😄

  1. Conexion con la base de datos
'use stric'

const { MongoClient } = require('mongodb')
class Conexion {

    constructor() {
        this.mongoConnection()
    }
  
    mongoConnection() {
        MongoClient.connect( process.env.CONECTION_DB, {
            useNewUrlParser: true,
            useUnifiedTopology: true,
        }).then(client => {
            this.db = client.db('code-rockDB')
            console.log('Connected to Database')
        }).catch(err => console.log('Error para conectar Database',err))

    }
}

module.exports = new Conexion()
  1. Controllers para las consultas a MongoDB
const Conexion = require('./db')
const { ObjectID } = require('mongodb')


module.exports = {
    getAllCourses: async () => await Conexion.db.collection('courses').find().toArray(),
    getCourseById: async (id) => await Conexion.db.collection('courses').findOne({ _id: ObjectID(id) }),
    getAllStudents: async () => await Conexion.db.collection('students').find().toArray()
}
  1. Resolvers para graphQl
'use stric'

const mutations = require('./mutations')
const { getAllCourses, getCourseById, getAllStudents } = require('./controllers')


module.exports = {
    Query: {
        getCourses: async () => await getAllCourses(),
        getCourse: async (root, { id }) => await getCourseById(id),
        getStudents: async () => await getAllStudents(),
    },
    Mutation: mutations
 }
  1. Index.js
'use stric'

require('dotenv').config()
const { join } = require('path');
const { readFileSync } = require('fs');
const { graphqlHTTP  } = require('express-graphql');
const { makeExecutableSchema } = require('graphql-tools');
const resolvers = require('./lib/resolves')

// App init
const app = require('express')();
const port = process.env.port || 3000;

// Definiendo el schema
const typeDefs = readFileSync(join(__dirname, 'lib', 'schema.graphql'), 'utf-8')
const schema = makeExecutableSchema({ typeDefs, resolvers })

// Routes
app.use('/api', graphqlHTTP({
    schema: schema,
    rootValue: resolvers,
    graphiql: true
  })
)

// Serve listend
app.listen(port, () => { console.log( `Server is run ${port}`) })

Esta librería de GraphQL me ayuda a auto-generar resolvers conectados a mongo.
https://github.com/scalars/grapi