Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Filtrando precios con operadores

28/33
Recursos

Aportes 4

Preguntas 1

Ordenar por:

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

Lo que hicimios

// src\products\dtos\products.dtos.ts

@IsOptional()
@IsPositive()
minPrice: number;

@ValidateIf((item) => item.minPrice)
@IsPositive()
maxPrice: number;
// src\products\services\products.service.ts

// Cambiamos el servicio
async findAll(params?: FilterProductDto) {
    if (params) {
      const where: FindConditions<Product> = {};
      const { limit, offset } = params;
      const { maxPrice, minPrice } = params;
      
      if (minPrice && maxPrice) {
        where.price = Between(minPrice, maxPrice);
      }

      return this.productRepo.find({
        relations: ['brand'],
        where,
        take: limit,
        skip: offset,
      });
    }

    return this.productRepo.find({
      relations: ['brand'],
    });
  }

A medida que va avanzando el curso quedo más maravillado con todo lo que puedo hacer con Nest JS ofrece.

Aquí dejo un ejemplo con más condiciones, con ordenamiento y alguna que otra cosa más:

Para dividir un poco el Dto me cree una clase de la que heredarán los otros filter con limit y offset ya que estos son muy comunes en cualquier filtro

import { IsOptional, IsPositive, Min } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';

export class BaseFilterDto {
  @ApiProperty()
  @IsOptional()
  @IsPositive()
  readonly limit: number;

  @ApiProperty()
  @IsOptional()
  @Min(0)
  readonly offset: number;
}

Al Dto de filtrar productos le añadí varias opciones más como que puedas pasar solo un minimo o maximo precio, ordenar por un parámetro en concreto, orden descendente o ascendente y buscar por id de marca.

export class FilterProductsDto extends BaseFilterDto {
  @ApiProperty()
  @IsOptional()
  @Min(0)
  readonly minPrice: number;

  @ApiProperty()
  @IsOptional()
  @IsPositive()
  readonly maxPrice: number;

  @ApiProperty({ enum: ['price', 'id'] })
  @ValidateIf((item) => item.order)
  @IsEnum(['price', 'id'])
  readonly orderBy: string;

  @ApiProperty({ enum: ['ASC', 'DESC'] })
  @ValidateIf((item) => item.orderBy)
  @IsEnum(['ASC', 'DESC'])
  readonly order: string;

  @ApiProperty()
  @IsOptional()
  @IsNumber()
  readonly brandId: number;
}

Para terminar el service me queda de la siguiente manera:

async findAll(params?: FilterProductsDto) {
    const { limit, offset, maxPrice, minPrice, orderBy, order, brandId } =
      params;
    const findOptions: FindManyOptions<Product> = {};

    const where: FindConditions<Product> = {};
    if (minPrice && maxPrice) {
      where.price = Between(minPrice, maxPrice);
    } else if (minPrice) {
      where.price = MoreThanOrEqual(minPrice);
    } else if (maxPrice) {
      where.price = LessThanOrEqual(maxPrice);
    }

    if (brandId) where.brand = { id: brandId };
    if (orderBy && order) findOptions.order = { [orderBy]: order };
    findOptions.where = where;
    findOptions.skip = offset;
    findOptions.take = limit;
    findOptions.relations = ['brand', 'categories'];

    return await this.productRepository.find(findOptions);
  }

Es necesario hacer las validaciones a ambos campos o el otro pasa como vacío

@IsPositive()
  @ValidateIf((item) => item.minPrice)
  maxPrice: number

  @IsPositive()
  @ValidateIf((item) => item.maxPrice)
  minPrice: number