Excelente curso!!!
Introducción
¿Ya tomaste el Curso de NestJS: Programación Modular?
Instalación de Docker para este curso
Instalación de Platzi Store y presentación
Database
Configuración de Docker para MongoDB
Exploración de la base de datos con Mongo Compass
Instalando y conectando MongoDB Driver
Conexión como inyectable
Ejecutando un query
Usando variables de ambiente en Mongo
Mongoose
¿Qué es Mongoose? Instalación y configuración
Implementando Mongoose en Módulos
Conectando Mongo a los servicios
Create, update y delete
Pipe para mongoid
Agregando paginación
Agregando un filtro de rango para precios
Agregando indexadores
Relaciones en MongoDB
Relaciones uno a uno embebidas
Relaciones uno a uno referenciadas
Relaciones uno a muchos embebidas
Cómo tipar relaciones uno a muchos embebidas
Relaciones uno a muchos referenciadas
Manipulación de arrays en MongoDB
Próximos pasos
Continúa con el Curso de NestJS: Autenticación con Passport y JWT
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
Convierte tus certificados en títulos universitarios en USA
Antes: $249
Paga en 4 cuotas sin intereses
Termina en:
Nicolas Molina
Es crucial diseñar bien tu base de datos. Las relaciones uno a muchos pueden crecer indefinidamente y es importante considerar la escalabilidad de tu base de datos.
A lo igual que las relaciones uno a uno, las relaciones uno a muchos requieren contemplar la posible actualización de todo ese array de documentos. Tener un array de objetos puede no ser escalable y una no muy buena decisión de arquitectura de la base de datos.
Estos problemas se solucionan creando arrays de referencias. Un simple array de string que contendrá un item por cada ID al cual deseas hacer referencia dentro de un objeto principal.
Veamos como puedes crear este tipo de relación donde un documento contendrá un array de IDs que hacen referencia a otros documentos de la base de datos.
Prepara la propiedad correspondiente en tu esquema que contendrá el array de referencias.
// users/order.entity.ts
import { Document, Types } from 'mongoose';
import { Product } from '../../products/entities/product.entity';
@Schema()
export class Order extends Document {
@Prop({ type: [{ type: Types.ObjectId, ref: Product.name }] })
products: Types.Array<Product>;
}
Observa que el decorador @Prop()
recibe como tipo un Types.ObjectId
que a su vez se encuentra encerrado por un array []
. También, tienes que tipar la propiedad con Types.Array<>
proveniente desde mongoose
.
De esta simple manera, Mongoose sabe que la propiedad products
contiene un array de MongoID.
El DTO solo necesita recibir un array de string[]
que es el equivalente para un array de MongoID.
// users/order.dto.ts
import { IsMongoId, IsNotEmpty, IsDate, IsArray } from 'class-validator';
import { OmitType, PartialType } from '@nestjs/swagger';
export class CreateOrderDto {
@IsArray()
@IsNotEmpty()
readonly products: string[];
}
Utiliza el decorador @IsArray()
para validar que efectivamente se trate de un array.
Realizar un “Join” o, como se lo conoce en MongoDB, un “Populate” es muy sencillo. Basta con agregar la configuración después del método de búsqueda indicando el nombre de la propiedad a popular.
// users/orders.service.ts
export class OrdersService {
constructor(@InjectModel(Order.name) private orderModel: Model<Order>) {}
findAll() {
return this.orderModel
.find()
.populate('products')
.exec();
}
}
Mongoose sabrá a qué colección ir a buscar los documentos al estar referenciado y tipado desde el esquema.
De esta manera, tu base de datos está lista para manipular grandes volúmenes de datos con los mejores tipos de relaciones que existen. Utiliza el tipo de relación más apropiado para cada escenario.
Contribución creada por: Kevin Fiorentino (Platzi Contributor).
// src/users/entities/order.entity.ts
import { Document, Types } from 'mongoose';
import { Customer } from './customer.entity';
import { Product } from '../../products/entities/product.entity';
@Schema()
export class Order extends Document {
...
@Prop({ type: Types.ObjectId, ref: Customer.name, required: true })
customer: Customer | Types.ObjectId; // 👈 relation 1:1 customer
@Prop({ type: [{ type: Types.ObjectId, ref: Product.name }] })
products: Types.Array<Product>; // 👈 relation 1:N
}
// src/users/dtos/order.dto.ts
import { IsMongoId, IsNotEmpty, IsDate, IsArray } from 'class-validator';
import { OmitType, PartialType } from '@nestjs/swagger'; // 👈 use OmitType
export class CreateOrderDto {
@IsNotEmpty()
@IsMongoId()
readonly customer: string;
@IsDate()
@IsNotEmpty()
readonly date: Date;
@IsArray()
@IsNotEmpty()
readonly products: string[];
}
export class UpdateOrderDto extends PartialType(
OmitType(CreateOrderDto, ['products']), // 👈 implement OmitType
) {}
// src/users/services/orders.service.ts
export class OrdersService {
constructor(@InjectModel(Order.name) private orderModel: Model<Order>) {}
findAll() {
return this.orderModel
.find()
.populate('customer') // 👈 join customer 1:1
.populate('products') // 👈 join products 1:N
.exec();
}
}
Aportes 15
Preguntas 5
Excelente curso!!!
Para los que quieran popular, las skills tienen que usar un populate anidado
return this.orderModel
.find()
.populate('productIds)
.populate({
path: 'customer',
populate: {
path: 'skills',
},
})
.exec();
¿Qué pasa si después de haber echo una Orden se modifica el precio de un producto?
Si se actualiza el precio de alguno de estos productos, al estar referenciado, la orden ya no tendría el precio con el cual se compro el producto inicialmente.
Al día de hoy ya no es necesario colocar el .exec()
Primera vez que me pasa esto en insomnia y no se a que se debe.
Excelente curso, enserio!!
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?