Reto resuelto:
Introducción al proyecto del curso y su arquitectura
Creación de Backend Complejo con Microservicios y Arquitectura Escalable
Modelado de Datos para una Red Social Básica en SQL
Creando la estructura principal
Configuración de un Servidor API con Express y Node.js
Estructuración de API y Gestión de Datos en JavaScript
Controladores con Inyección de Dependencias en Node.js
Documentación de APIs con Swagger en Node.js
Autenticación basada en tokens
Autenticación y Seguridad con Tokens JWT en Aplicaciones Web
Autenticación de Usuarios con JWT y Gestión de Contraseñas Seguras
Implementación de Login Seguro con JWT y Cifrado de Contraseñas
Cifrado de Contraseñas con Bcrypt en Aplicaciones Node.js
Autenticación y Autorización con JWT en Node.js
Implementación de Autenticación y Autorización en Aplicaciones Web
Manejo de Errores y Seguridad en Aplicaciones Node.js
Almacenando datos: MySql
Almacenamiento de Datos con MySQL en Node.js
Funciones CRUD en Base de Datos con Node.js
Creación de Tabla Intermedia para Relaciones de Seguimiento de Usuarios
Gestión de Seguidores y Publicaciones en Redes Sociales
Microservicios en Node
Arquitectura de Microservicios: Separación y Gestión Eficiente
Creación de Microservicios para Bases de Datos con Node.js
Conexión y Configuración de Microservicios de Bases de Datos Remotas
Separación Horizontal de Microservicios: Implementación y Beneficios
Gestión de Microservicios en Producción con PM2
Puesta en producción serverless
Despliegue de Aplicaciones Serverless con Vercel y AWS
Variables de Entorno y Despliegue Local con Node.js
Cacheando nuestra aplicación
Implementación de Caché con Redis para Microservicios
Conexión de Microservicios a Redis y Gestión de Caché
Cacheo y Optimización de Consultas en Microservicios
Puesta en producción en virtual machine
Instalación y Configuración de Microservicios en Máquinas Virtuales
Configuración de Nginx como proxy para microservicios en producción
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
Una de las funciones más útiles que podemos implementar en una aplicación es la de mostrar los seguidores de un usuario. Para conseguirlo, debemos crear una consulta específica que nos permita extraer esa información de nuestra base de datos. Aquí te explicamos cómo lograrlo.
Primero, debes definir una función que interactúe con tu API para obtener los seguidores del usuario. Esto se hace mediante una consulta SQL que relacione las tablas de usuarios y seguidores adecuadamente. Es crucial utilizar el concepto de JOIN
para relacionar las entidades y asegurarte de que la consulta esté optimizada para un rendimiento eficiente.
function getFollowers(userId) {
const query = `
SELECT follower_id
FROM followers
INNER JOIN users ON followers.follower_id = users.id
WHERE followers.followed_id = ?
`;
// Ejecutamos la consulta con el parámetro del usuario
db.query(query, [userId], (error, results) => {
if (error) {
throw error;
}
return results;
});
}
Con esta función, puedes solicitar los seguidores de un usuario específico y, al ejecutarla, obtendrás una lista de los seguidores de forma clara y precisa.
Para enriquecer las funcionalidades de nuestra aplicación, resulta esencial añadir nuevas entidades que permitan a los usuarios crear contenido, como por ejemplo publicar posts. A continuación, te guiaremos en el proceso de creación de una nueva entidad Post
.
Crea la Carpeta para 'Posts': Organiza tu proyecto añadiendo una nueva carpeta denominada posts
, en donde incluirás todos los archivos relacionados con esta funcionalidad.
Define Archivos Requeridos: Dentro de posts
, debes crear, al menos, los siguientes archivos:
post.model.js
: Define aquí el esquema de cómo se almacenarán los posts en la base de datos.post.controller.js
: Aquí se gestionarán las funciones esenciales (crear, leer, actualizar, eliminar) para los posts.post.routes.js
: Especifica las rutas de la API que permitirán la interacción con los posts.Modifica el Índice de la API: Asegúrate de importar el componente de Post
en el índice principal de tu API para que todas las rutas y controles queden correctamente enlazados.
app.use('/api/posts', require('./posts/post.routes'));
Al seguir estos pasos, estarás preparado para permitir que los usuarios de tu aplicación puedan publicar sus propios contenidos en su muro.
Incorporar una nueva entidad implica también modificar la estructura de tu base de datos para soportar esta funcionalidad adecuadamente. Aquí te indicamos cómo hacerlo.
CREATE TABLE posts (
id VARCHAR(32) PRIMARY KEY,
title TEXT NOT NULL,
body TEXT NOT NULL,
author_id VARCHAR(32),
FOREIGN KEY (author_id) REFERENCES users(id)
);
Definir Atributos Clave:
id
: Identificador único para cada post.title
: Texto breve que actúa como título del post.body
: Contenido completo del post.author_id
: Referencia al usuario que creó el post.Ajustar la Relación con Usuarios: Asegúrate de que la tabla 'posts' esté bien referenciada con la tabla 'usuarios' para vincular cada post a su autor correcto.
Con estos cambios, tu base de datos estará lista para manejar eficazmente las operaciones de creación, lectura, actualización y eliminación de posts, proporcionando una experiencia fluida para los usuarios.
Aportes 17
Preguntas 3
Reto resuelto:
Si quieren que en la query JOIN devuleva todos los Post de un user tiene que quitarle el [0] al ultimo resolve d ela sentecia. Quedaria asi.
function query(table, query, join){
let joinQuery = '';
if(join){
const key = Object.keys(join)[0];
const val = join[key];
joinQuery =`JOIN ${key} ON ${table}.${val} = ${key}.id`;
// Object.entries(join).forEach(([key, value]) => {
// const[from, to] = value;
// joinQuery+= `JOIN ${key} ON ${table}.${from} = ${key}.${to}`;
// })
}
// debug(`${table}, ${JSON.stringify(query)}, ${joinQuery}`);
return new Promise((resolve, reject) => {
connection.query(`SELECT * FROM ${table} ${joinQuery} WHERE ${table}.?`, query, (err, res) =>{
if(err) return reject(err)
//AQUI+++++
//resolve(res[0] || null);
resolve(res || null);
})
})
}
Les comparto la función query, donde acepta varios parámetros para el join
function query(table, query, join = null) {
let joinQuery = '';
if (join) {
Object.entries(join).forEach(([key, value]) => {
const [from, to] = value;
joinQuery+= `JOIN ${key} ON ${table}.${from} = ${key}.${to}`;
})
}
debug(`${table}, ${JSON.stringify(query)}, ${joinQuery}`);
return new Promise((resolve, reject) => {
connection.query(`SELECT * FROM ${table} ${joinQuery} WHERE ?`, query, (error, data) => {
if (error) return reject(error);
resolve(data);
})
});
}```
si quieres traer una lista en lugar de un solo registro de las personas siguiendo. cambia
resolve(res[0] || null)
por
resolve(res || null);
aqui te devuelve una lista pero afecta al servicio de login por eso les recomiendo una condicion con el join para la respuesta
if (join) {
resolve(res || null)
} else {
resolve(res[0] || null)
}
No me gusta que las tablas no estén relacionadas
como seria el codigo, para traerme todos los seguidore.? actualmente el codigo solo trae un seguidor.!
me imagino que se usa un forEach pero no se como va la cosa.!
Si quieren que en la consulta query les devuelva todos los post, like que dependen de una JOIN le tienen que quitar en el ultimo resolve en [0] de la funcion query. quedaria asi.
function query(table, query, join){
let joinQuery = '';
if(join){
const key = Object.keys(join)[0];
const val = join[key];
joinQuery =`JOIN ${key} ON ${table}.${val} = ${key}.id`;
// Object.entries(join).forEach(([key, value]) => {
// const[from, to] = value;
// joinQuery+= `JOIN ${key} ON ${table}.${from} = ${key}.${to}`;
// })
}
// debug(`${table}, ${JSON.stringify(query)}, ${joinQuery}`);
return new Promise((resolve, reject) => {
connection.query(`SELECT * FROM ${table} ${joinQuery} WHERE ${table}.?`, query, (err, res) =>{
if(err) return reject(err)
resolve(res || null);
})
})
}
Buena solución al reto! En base a eso, modifiqué el método que elimina para hacer un endpoint que hace unfollow. Acá mi solución:
.
Método remove de mysql.js:
function remove(table, firstCondition, othersCondition = []) {
let andConditions = "";
if (othersCondition.length > 0) {
andConditions = othersCondition.map(c => "AND ?").join(" ");
}
return new Promise((resolve, reject) => {
connection.query(
`DELETE FROM ${table} WHERE ? ${andConditions}`,
[firstCondition, ...othersCondition],
(err, data) => {
if (err) return reject(err);
return resolve(data);
}
);
});
}
.
Método unfollow de userController:
const unfollow = (from, to) => {
return store.remove("follows", { user_from: from }, [{ user_to: to }]);
};
.
El userNetwork ya se lo conocen 😃
Vamos bien!!!
Hola saben por que no puedo colocar el caracter de pregunta en la sentencias, estoy usando MSSQL :
Me sale el siguiente error:
e:21740) UnhandledPromiseRejectionWarning: RequestError: Incorrect syntax near '?'.
at handleError (C:\trabajo\GOCHO\OneDrive - GRUPO OSPEDALE\Documentos\GOCHO\PROYECTOS\KERBERUS\API_IVR_TRANSACCIONAL\node_modules\mssql\lib\tedious\request.js:374:15)
at Connection.emit (events.js:375:28)
y el metodo es tal cual el del profesor :
function query(table, query, join) {
let joinQuery = '';
if (join) {
const key = Object.keys(join)[0];
const val = join[key];
joinQuery = `JOIN ${key} ON ${table}.${val} = ${key}.id`;
}
return new Promise((resolve, reject) => {
connection.query(`SELECT * FROM ${table} ${joinQuery} WHERE ${table}.?`, query, (err, res) => {
if (err) return reject(err);
resolve(res[0] || null);
})
})
}
Solo como mejora, sería ideal poner la llave foránea user como user_id para que al implementar relaciones por medio de algún ORM se pueda diferenciar que user_id es el ID y user es el objeto user a través de una relación.
Controller quedó así
async function following({id}) {
const join = {
[TABLA]: ['user_to_id', 'id'],
};
return store.query(`${TABLA}_follow`, {user_from_id: id}, join);
}```
Acá dejo todo mi reto, tuve que modificar mi método get para que obtenga arreglos de condiciones.
https://github.com/behagoras/platzi-practico-node/tree/posts-likes
Hola, tengo una duda, como seria la mejor manera de comunicar componentes? , por ejemplo si requiero de una funcionalidad de otro componente importo el controlador de este? , o hay alguna otra forma ?
Excelente clase
Super 😃
Me podrian ayudar por favor con este error
{
"error": false,
"status": 500,
"body": "Cannot enqueue Query after fatal error."
}
En la consola me sale esto
code: 'PROTOCOL_ENQUEUE_AFTER_FATAL_ERROR',
fatal: false
}
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?