Conocer y comprender cómo se realizan las conexiones hacia los servidores a través de internet y sus implicaciones en el desarrollo de servidores

1

Bienvenida y presentación del curso

2

Qué es Node y cómo instalarlo

3

¿Qué son y cómo se usan las peticiones HTTP?

4

Métodos, cabeceras y estados

5

Cuerpo y query de la petición

Crear un servidor HTTP en Javascript, y comenzar a escuchar y responder peticiones desde un cliente .

6

Crear un servidor HTTP desde NodeJS

7

¿Cómo pueden venir las peticiones?

8

Recibir información desde el cliente: Body y Query

9

Información contextual: Leer las cabeceras

10

Tipos de respuesta: Vacía, plana, con datos y estructurada

11

Respuestas coherentes

12

Servir archivos estáticos

13

Errores: Cómo presentarlos e implicaciones en la seguridad

Comprender y desarrollar la arquitectura básica de un backend en NodeJS, y comunicarse entre módulos

14

Conceptualmente: Rutas, controladores y bases de datos

15

Rutas y capa de red: Responsabilidades y límites

16

Controladores: Definiendo la lógica de negocio

17

Almacenando la información en una base de datos

Utilizar una base de datos para definir, modelar, almacenar y recuperar la información de nuestra aplicación

18

Tipos de Bases de Datos: Relacionales y No Relacionales

19

Crear y Configurar tu Base de Datos con MongoDB

20

MongoDB: Almacenar y leer datos

21

MongoDB: Actualizar datos

22

MongoDB: Consultar datos

23

MongoDB: Eliminar Datos

24

Gestionar conexiones a la base de datos desde la API

Uso de entidades para crear aplicaciones escalables

25

Escalando la arquitectura: Múltiples entidades

26

Relacionando nuestras entidades

27

Cómo recibir ficheros desde NodeJS

28

Guardar el fichero en el servidor

Conocer el protocolo de websockets, e implementar comunicación cliente/servidor con SocketIO.

29

WebSockets: Qué son, por qué son interesantes y cómo usarlos

30

Manejo de Websockets con NodeJS

31

Conectar la API al servidor de WebSockets

Revisión de lo aprendido, y próximos pasos

32

Revisión y próximos pasos

33

Tips para escalar nuestro proyecto

No tienes acceso a esta clase

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

MongoDB: Consultar datos

22/33
Recursos

Aportes 28

Preguntas 7

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

En caso de que queramos hacer una búsqueda por el nombre ignorando mayúsculas o minúsculas se puede implementar el siguiente código:

  let userFilter = {};
  if (user) {
    userFilter.user = new RegExp(user, "i");
  }

Mongo puede utilizar Regular Expressions para realizar búsquedas y en estas es posible indicarle que busque “case-insensitive”. Esto se logra con el flag “i” que vemos en el código. Este código se traduce a: /usuario/i.
.
Platzi cuenta con un curso de RegExp por si alguien quiere tomarlo 😃 https://platzi.com/clases/expresiones-regulares/

Con la especificacion del metodo getMessages del store.js vista en esta clase, al no especificar el parametro user en el query, se retornara un arreglo vacio. Esto depende de la definicion y alcance del metodo getMessages, pero si en caso yo quisiera obtener toda la lista de usuarios usando dicho metodo cuando no se especifica el parametro query de user, es solo cambiar la condicion de existencia del parametro filterUser

const get Messages = async (filterUser) => {
    let filter = {}
    if (filterUser) 
   // ... aqui sigue la misma definicion de metodo :D
}

Comparto el código para filtrar también por el texto del mensaje:

  • store.js:
async function getMessages(filterUser, filterMessage) {
    let filter = {}

    if (filterUser){
        filter = {
            user: filterUser
        }
    }
    
    if (filterMessage){
        filter = {
            ...filter,
            message: filterMessage
        }
    }

    return await Model.find(filter)
}
  • controller.js
function getMessages(filterUser, filterMessage) {
    return new Promise((resolve, reject) => {
        try {
            resolve(store.list(filterUser, filterMessage))
        } catch (error) {
            reject(error)
        }
    })
}
  • network.js
router.get('/', function (req, res) {
    const filterUser = req.query.user || null
    const filterMessage = req.query.message || null

    console.log(filterUser)

    controller.getMessages(filterUser, filterMessage)
        .then(messagesList => {
            response.success(req, res, messagesList, 200)
        })
        .catch( e => {
            response.error(req, res, 'Unexpected error' /*  user message */, 500, e)
        })
})

verifique que si el usuario no existe le diera la respuesta.

store.js

async function getMessage(filterByUser) {
  let filterUser = {};
  if (filterByUser !== null) {
    //Le decimos a mongo que solo nos muestre informacion de ese user (si viene alguno)
    filterUser = { user: filterByUser };
  }
  const messages = await Model.find(filterUser);
  //Verificamos que el usuario exista.
  if (messages.length !== 0) {
    return messages;
  } else {
    console.log("Usuario no se encuenta en la base de datos");
    return "Usuario no encontrado";
  }
}

Vaina me toca repasar mucho Mongo DB. Hay muchas cosas que no entiendo a profundidad.

Aquí tenéis un ejemplo de como se hace un filtro por diferentes parámetros.

message.get("/", async (req, res) => {
  /* Creamos el filtro de búsqueda */
  let filter = {};
  const { user = null, message = null } = req.query;
  user && (filter.user = new RegExp(user, "i"));
  message && (filter.message = new RegExp(message, "i"));
  /* Hacemos la consulta */
  try {
    const list = await controller.getMessages(filter);
    success({ req, res, data: list, status: 201 });
  } catch (info) {
    error({ req, res, error: "error", status: 500, info });
  }
});

Podríamos también pasar el usuario como:
…/message/user/:name …?

Cual sería la mejor forma???

si yo quiero hacer la siguiente consulta ++**SQL SELECT * FROM messages WHERE user LIKE “%carl%” **++en mongo con node
¿Cómo sería?

Genial! También puede hacerse mas corto de la siguiente forma en el store.js:

let listUsers = async (filterUser) => { 

    if(filterUser!=null) { filterUser = {user : filterUser} }
    const users = await Model.find(filterUser) 
    return users
}

En este caso, el filtro lo debería establecer el cliente desde el frontend, verdad? Desde el backend buscamos en la BD con el filtro y devolvemos lo que el usuario quiera ver.

Para el update podemos hacerlo asi

async update(id: string, changes: PropsMessage) {
    const result = await MessageModel.findByIdAndUpdate(id, changes);
    return result;
  }

Otra forma de filtrar de forma mas dinámica sin limitar solo a un campo puede ser la siguiente:

function readMessages(filters) {
    const filter = {};

    for (const key in filters) {
        if (filters[key]) {
            filter[key] = filters[key];
        }
    }

    return Model.find(filter);
}

Bueno, es bastante habitual que tengamos servicios que manejan parámetros opcionales. Para usar los parámetros opcionales debemos usar el símbolo ? luego de cada parámetro:

Para procesar estos parámetros opcionales deberemos procesarlos en nuestro Storage:

Finalmente recordemos que deberemos poder enviarlos desde el navegador, en este caso yo uso Postman:

Lectura recomendada: Encoding de parámetros para elementos de la URL

Para consultar la información dentro de la base de datos con filtros como el del usuario podemos usar la siguiente modificación

network.js

router.get("/", async(req, res) => {
// Ingreso del filtro con query
  const filterMessages = req.query.user || null;
    try {
      const allMessages = await 
      //Envio del filtro a controller
      controller.getMessages(filterMessages);
      response.success(req, res, allMessages, 200);
    } catch (error) {
      response.error(req, res, error, 500, "Error getting messages");
    }
});

controller.js

// Recibo como parametro el filtro
function getMessages(filterUser) {
    return new Promise((resolve, _reject) => {
    // Envio al store el filtro como parametro
        resolve(store.list(filterUser));
    });
}

store.js

// recibo el filtro como parametro
async function getMessages(filterUser) {
// hago un filtro como objeto para recibir al filtro ingresado
    let filter = {};
    if(filterUser !== null) {
        filter = {user: filterUser};
    }
    // de no recibir filtro el Model recibira un filtro nulo
    return await Model.find(filter);
}

La búsqueda ya un poco más elaborada, lo bueno que tiene este código es que se puede ir
agregando campos al modelo de tipo string y debería seguir funcionando, para todos los campos string,
también aplique el truco de usar regex en la consulta para que pueda buscar valores parciales.

// messages_controller.js

const store = require("./messages_store");
const modelProps = store.getModelProps();
const modelStringProps = store.getModelProps("string");

function listMessages(query) {
  return new Promise(async (resolve, reject) => {
    try {
      const search_query = getSearchQuery(query);
      if (!search_query) {
        resolve([]);
        return;
      }

      const messages = await store.list(search_query);
      resolve(messages);
    } catch (error) {
      console.error("[Error listMessages]:", error.stack);
      reject(error);
    }
  });
}

function getSearchQuery(query) {
  for (let [property, value] of Object.entries(query)) {
    if (!modelProps.includes(property)) {
      return false;
    }

    if (modelStringProps.includes(property)) {
      if (typeof value === "string") value = [value];
      query[property] = new RegExp(value.join("|"), "i");
    }
  }
  return query;
}

// messages_store.js

const Model = require("./messages_model");
Model.schemaProps = Object.keys(Model.schema.obj);

async function list(query) {
  const all_documents = await Model.find(query);
  return all_documents;
}

function getModelProps(filter_type) {
  return Model.schemaProps.filter((prop) => {
    if (filter_type) {
      const propType = Model.schema.paths[prop].instance.toLowerCase();
      const is_filter_type = propType === filter_type.toLowerCase();
      return is_filter_type ? prop : null;
    }
    return prop;
  });
}

module.exports = {
  list,
  getModelProps
};

Codigo ES6+:

Ruta: componente/message/network.js

router.get('/',async (req,res)=>{
    try {
        const filterUser = req.query.user || null;
        const messages = await getMessages(filterUser);
        response.success(req, res, messages, 200);
    } catch (e) {
        response.error(req, res, 'Error inesperado', 500, e);
    }
});

Ruta: componente/message/controller.js

const getMessages = (filterUser)=> {
    return new Promise((resolve,reject)=>{
        resolve(store.list(filterUser));
    })
}

Ruta: componente/message/store.js

async function getMessages(filterUser) {
    let filter ={}

    if(filterUser != null)filter ={ user: new RegExp(`${filterUser}`,'i') }
    const messages = await Model.find(filter);
    return messages;
}

No se le pudo seguir el ritmo a la parte de mongo porque mlab ya no prensta la info de esta manera.

Para quitar el __v y para anadir la fecha ademas de constrains a los datos del modelo:

const userSchema = new Schema({
email: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
},
}, {
timestamps: true, // agrega la fecha de creacion y actualziacion
versionKey: false //quita el __v
})

Wow genial aprender estas cosas

I teresante

filter === select?

Todo Muy interesante 😃

Igual es posible simpleifiar el if por un valor trusty en caso de que este vacio dara false

async function getMessage(filterUser){
  let filter = {};
  if(filterUser){
    filter = { user: filterUser}
  }
  const messages = await Model.find(filter);
  return messages;
}```

Actualmente tengo dos colecciones, que se encuentran referenciadas por un id, como imprimo un valor dentro de la referencia, si quisiera imprimir los datos del empleado y un campo de la referencia de tipo sangre como estatus sin traerme el id.

const users = await Empleado.find();
console.log(users.tipo_sangre.nombre);

const EmpleadoSchema = new Schema(
    {
        num_seguro_social: {   
            type: String, 

            maxlength: [20, "Tamaño Maximo para numero de seguro social 20 caracteres"],
            unique:true,
            trim:true
        },
        tipo_sangre:{
                type:Schema.Types.ObjectId,
                ref:"cat_tps"
        }
    },
    {
        timestamps: true
    }
    );

const cat_tps = new Schema ({

    nombre:{
        type: String,
        require: true
    },

    status: {
        type: Boolean,
        default:true
    }
});

Super 😃 ✌

Recomiendo hacer la validacion en el network o controller, ya que la logica deberia ir ahi y no en el store.
Ejemplo:

  • Network.js
const {user: filteredUser} = req.query;
const filter = filteredUser ?{ user: filteredUser } :{}
...
getMessages(filter)

Práctica: se me queda cargando en insomnia. 😦

Me encanta la simplicidad de este curso pero me quedan dudas con la seguridad