Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Relaciones uno a uno referenciadas

19/24
Recursos

🚨 Es importante que esta clase tengas ya esquemas, controladores, servicios y dtos de las entidades:

  • Brand
  • Customer
  • Order
  • User
    Que deberías estar avanzado en ellos y ahora los vamos a usar para empezar a hacer relaciones, pero no te preocupes puedes encontrar estos afectados en la rama 13 y compararlo con lo que tú llevas.
// src/products/entities/brand.entity.ts
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Document } from 'mongoose';

@Schema()
export class Brand extends Document {
  @Prop({ required: true, unique: true }) // 👈 is unique
  name: string;

  @Prop()
  image: string;
}

export const BrandSchema = SchemaFactory.createForClass(Brand);
// src/products/entities/product.entity.ts

import { Document, Types } from 'mongoose';
import { Brand } from './brand.entity';

export class Product extends Document {

  @Prop({ type: Types.ObjectId, ref: Brand.name }) // 👈 relation
  brand: Brand | Types.ObjectId; // 👈 new field

}
// src/products/dtos/products.dtos.ts

import {
  ...,
  IsMongoId, // 👈 new decorator
} from 'class-validator';

export class CreateProductDto {
  ...

  @IsNotEmpty()
  @IsMongoId()
  readonly brand: string; // 👈 new field
}
// src/products/services/products.service.ts

export class ProductsService {

  findAll(params?: FilterProductsDto) {
    if (params) {
      const filters: FilterQuery<Product> = {};
      const { limit, offset } = params;
      const { minPrice, maxPrice } = params;
      if (minPrice && maxPrice) {
        filters.price = { $gte: minPrice, $lte: maxPrice };
      }
      return this.productModel
        .find(filters)
        .populate('brand') // 👈 relation
        .skip(offset)
        .limit(limit)
        .exec();
    }
    return this.productModel.find().populate('brand').exec(); // 👈 relation
  }
}

Aportes 5

Preguntas 1

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

🚨 Es importante que esta clase tengas ya esquemas, controladores, servicios y dtos de las entidades:

  • Brand
  • Customer
  • Order
  • User

Que deberías estar avanzado en ellos y ahora los vamos a usar para empezar a hacer relaciones, pero no te preocupes puedes encontrar estos afectados en la rama 13 y compararlo con lo que tú llevas.

Para el findOne en lugar de usar el método findById() usaremos el método findOne() que es el que admite el populate.
A este método le tendremos que especificar por que campo queremos buscar.
Ejemplo:

async findOne(id: string) {
    const product = await this.productModel
      .findOne({ _id: id })
      .populate('brand')
      .exec();
    if (!product) {
      throw new NotFoundException(`Product #${id} not found`);
    }
    return product;
  }

Me parece mucho mejor este tipo de referencia a pesar de trabajar en una BD no relacional, al final se optimiza espacio en memoria, y como lo dice nicolás, es mucho mejor para las actualizaciones en este caso de una categoría.

Por si a alguien le funciona lo siguiente; mi función findAll() en el servicio de Products se ve de la siguiente manera:

  async findAll(params?: FilterProductsDto) {
    let productsQuery = this.productModel.find().populate('brand');
    const filters: FilterQuery<Product> = {};
    const { limit, offset, minPrice, maxPrice } = params;

    if (minPrice >= 0 || maxPrice >= 0) {
      filters.price = {
        $gte: minPrice,
        $lte: maxPrice,
      };
      productsQuery.find(filters);
    }

    if (!_.isEmpty(params)) {
      productsQuery.skip(offset).limit(limit)
    }
    
    return await productsQuery.exec();
  }

Lo diferente es que las sentencias de filtros y paginados se van encadenando según sea necesario, y en todo el método solo hay una sentencia que retorne. Espero les sea de utilidad.

wow, super genial las relaciones asi con mongo 😮 me esta encantando el curso