Relaciones embebidas en MongoDB: Manejo y ejemplos prácticos

Clase 18 de 24Curso de NestJS: Persistencia de Datos con MongoDB

Contenido del curso

Mongoose

Resumen

MongoDB es una base de datos No Relacional. Aun así, requerimos la posibilidad de crear relaciones entre documentos de diferentes colecciones y es posible hacerlo.

Documento dentro de otro documento

La relación más sencilla y más utilizada es guardando un documento dentro de otro, formando una relación uno a uno embebida.

{ "name": "Producto Uno", "category": { "name": "Category", "image": "..." } }

Implementación relación uno a uno

Implementar esta lógica con Mongoose y NestJS es muy sencillo.

Paso 1: preparar el esquema

Agrega la propiedad en tu esquema que contendrá el documento embebido.

// products/product.entity.ts import { Prop, Schema, SchemaFactory, raw } from '@nestjs/mongoose'; export class Product extends Document { @Prop( raw({ name: { type: String }, image: { type: String }, }) ) category: Record<string, any>; }

El decorador @Prop() recibe un raw() con la estructura del objeto que estará dentro del objeto principal. La relación es resuelta gracias al tipado Record propio de TypeScript.

Paso 2: validar sub documento

El DTO será el encargado de validar la estructura de este sub documento.

// products/dto/category.dto.ts import { IsString, IsNotEmpty, IsUrl } from 'class-validator'; export class CreateCategoryDto { @IsString() @IsNotEmpty() readonly name: string; @IsUrl() @IsNotEmpty() readonly image: string; }

Prepara el DTO para la creación de la categoría con los campos que le corresponde a la misma que estarán embebidos dentro del documento principal.

// products/products.dto.ts import { ValidateNested } from 'class-validator'; import { CreateCategoryDto } from './category.dtos'; export class CreateProductDto { @IsNotEmpty() @ValidateNested() @ApiProperty() readonly category: CreateCategoryDto; }

Importa el DTO de la categoría y utilízalo como propiedad para el DTO de creación de productos. Agrégale el decorador @ValidateNested() para que NestJS haga la validación de la estructura correspondiente del objeto dentro.

De esta sencilla manera, puedes crear relaciones uno a una, o guardar un objeto dentro de otro en MongoDB a la vez que válidas la estructura del mismo.

Contribución creada por: Kevin Fiorentino (Platzi Contributor).


Código de ejemplo para relaciones uno a uno embebidas

// src/products/entities/product.entity.ts import { Prop, Schema, SchemaFactory, raw } from '@nestjs/mongoose'; export class Product extends Document { ... @Prop( raw({ name: { type: String }, image: { type: String }, }), ) category: Record<string, any>; // 👈 new field }
// src/products/dtos/category.dtos.ts import { IsString, IsNotEmpty, IsUrl } from 'class-validator'; export class CreateCategoryDto { ... @IsUrl() @IsNotEmpty() readonly image: string; // 👈 new field }
// src/products/dtos/products.dtos.ts import { ValidateNested, // 👈 new decorator } from 'class-validator'; import { CreateCategoryDto } from './category.dtos'; // 👈 export class CreateProductDto { @IsNotEmpty() @ValidateNested() @ApiProperty() readonly category: CreateCategoryDto; // 👈 new field }