No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

GET: parámetros query

8/23
Recursos

Hay varias maneras de enviar información a un endpoint del tipo GET, cada una con sus ventajas y desventajas. Profundicemos acerca de ellas.

Parámetros de ruta vs Parámetros query

Los parámetros de ruta son aquellos que forman parte del propio endpoint y suelen ser parámetros obligatorios.

@Get('product/:idProduct')
getProduct2(@Param('idProduct') idProduct: string): string {
    return `Producto id: ${idProduct}`;
}

En NestJS se capturan con el decorador @Param().

Por otro lado, están los parámetros de consulta o query en las URL como por ejemplo example.com/products?limit=10&offset=20 que se capturan con el decorador @Query() importado desde @nestjs/common.

@Get('products')
getProducts(@Query('limit') limit = 10, @Query('offset') offset = 0): string {
    return `Lista de productos limit=${limit} offset=${offset}`;
}

Su principal diferencia es que los parámetros de consulta suelen ser opcionales; el comportamiento del endpoint tiene que contemplar que estos datos pueden no existir con un valor por defecto.

Los parámetros de ruta se utilizan para IDs u otros identificadores obligatorios, mientras que los parámetros de consulta se utilizan para aplicar filtros opcionales a una consulta. Utilízalos apropiadamente en tus endpoints según tengas la necesidad.

Evitando el bloqueo de rutas

Un importante consejo a tener en cuenta para construir aplicaciones con NestJS es asegurar que un endpoint no esté bloqueando a otro.
Por ejemplo:

/* Ejemplo Bloqueo de Endpoints */
@Get('products/:idProduct')
endpoint1() {
    // ...
}
@Get('products/filter')
endpoint2() {
    // ...
}

El endpoint1 bloquea al **endpoint2, ya que este está esperando un parámetro :idProduct y si llamamos a localhost:3000/products/filter NestJS entenderá que la palabra filter es el ID que espera el primer endpoint ocasionando que no sea posible acceder al segundo endpoint.

Se soluciona de forma muy sencilla invirtiendo el orden de los mismos. Coloca los endpoints dinámicos en segundo lugar para que no ocasionen problemas.

/* Solución Bloqueo de Endpoints */
@Get('products/filter')
endpoint2() {
    // ...
}
@Get('products/:idProduct')
endpoint1() {
    // ...
}

Este es un inconveniente común que suele suceder en NestJS y es importante que lo conozcas para evitar dolores de cabeza.

import { ..., Query } from '@nestjs/common';

@Controller()
export class AppController {
  ...

  @Get('products')
  getProducts(
    @Query('limit') limit = 100,
    @Query('offset') offset = 0,
    @Query('brand') brand: string,
  ) {
    return `products limit=> ${limit} offset=> ${offset} brand=> ${brand}`;
  }

  @Get('products/filter')
  getProductFilter() {
    return `yo soy un filter`;
  }
}

Contribución creada por: Kevin Fiorentino.

Aportes 35

Preguntas 3

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Con el decorador @Query podemos recibir parámetros de consulta (Query Params) de una URL.

@Get('products')
getProducts(
  @Query('limit') limit = 100,
  @Query('offset') offset = 0,
  @Query('brand') brand: string,
) {
  return `products limit=> ${limit}`;
}

uff se siente muy cómodo utilizar nestjs por el orden que lleva, me está gustando bastante.

Otra forma de trabajar con los distintos params, aprofechando un poco lo que es ts:

interface: (fuera de la clase controller)

interface PaginateParams {
    limit?: number;
    offset?: number;
}

El EP:

@Get()
    getCategories(@Query() params: PaginateParams): string {
        const { limit = 20, offset = 0 } = params;
        return `categoríes paginated with limit(${limit}) and offset(${offset})`;
    }

Al menos a mi me parece más limpia, o al menos me queda más comoda a la vista

Una manera más sencilla de darle formato a nuestro código al momento de guardar algún cambio, es colocar lo siguiente en nuestro archivo settings.json de vscode:

"[typescript]": {
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode"
}

Oficialmente amo Nest ❤️

Ojo Los Query params a peasr de tiparlos como “number” van a recibirse como strings.

  @Get('products')
  getProducts(
    @Query('limit') limit: number,
    @Query('offset') offset: number,
    @Query('brand') brand: string,
  ) {
    typeof limit
    return `products limit=> ${typeof limit} offset=> ${typeof offset} brand=> ${brand}`;
  }

Igual que en el @Param podemos usar Pipes.

@Get('products')
  getProducts(
    @Query(
      'limit',
      new ParseIntPipe({ errorHttpStatusCode: HttpStatus.NOT_ACCEPTABLE }),
    )
    limit = 100,
    @Query(
      'offset',
      new ParseIntPipe({ errorHttpStatusCode: HttpStatus.NOT_ACCEPTABLE }),
    )
    offset = 0,
    @Query('brand') brand: string,
  ) {
    return `Product: Brand->${brand} Limit->${limit}. Offset ->${offset}`;
  }

Se ve tan limpio NestJS, se está poniendo interesante el curso, y el profesor lo explica tan bien.

NestJS tiene mucho potencial, la forma esta pensada para que nos centremos en la lógica de negocio. Me interesaría saber más al respecto del manejo de microservicios y el manejo de websockets

Otra forma de asignar valores por defecto seria la siguiente:

  @Get('products')
  getProducts(
    @Query('limit', new DefaultValuePipe(100)) limit: number,
    @Query('offset', new DefaultValuePipe(0)) offset: number,
    @Query('brand') brand: string,
  ) {
    return `products limit=> ${limit}`;
  }

Aquí utilizamos pipes para asignar valores por defecto simplemente agregamos el pipe DefaultValuePipe como segundo parametro de nuestro @Query decorador.

La documentación de Nest detalla mas sobre esto: https://docs.nestjs.com/pipes#providing-defaults

Utilizando el decorador Query de la siguiente manera:

@Get('products')
  getProducts(@Query() params: any) {
    const { limit, offset } = params;
    return `products: limit=> ${limit} offset=> ${offset}`;
  }

Tendríamos como salida lo siguiente:

Los parámetros pueden cambiar, sin embargo, si no pasamos parámetros, se vería de la siguiente manera:

Tenemos undefined

Les dejo una anotación del tip que me pareció importante.

Parámetros tipo Query


Los parámetros tipo query o Query Params son una serie de clave-valor que se agregan al final de la URL, justo después del signo de interrogación (?).

https://myapi.com/customers?name=oscar

Algunos de los usos que le podemos dar a los query params pueden ser, para limitar la cantidad de registros que vamos a traer, realizar algún filtro, o para la paginación de nuestra respuesta, entre otros

Con el decorador @Query podemos recibir parámetros de consulta (Query Params) de una URL.

@Get('products')
getProducts(
  @Query('limit') limit = 100,
  @Query('offset') offset = 0,
  @Query('brand') brand: string,
) {
  return `products limit=> ${limit}`;
}
  • En caso que dentro de la URL no se encuentre el valor, se tomara el valor que asignamos en nuestro controller
  • Si no asignamos un valor inicial nos mostrara undefined
  • También podemos realizar la desestructuración para acceder a los valores.
@Get('products')
	getProduct(@Query() params: any){
		const { limit, offset } = params;
		return `product ${limit} ofset ${offset}}`
	}
![](https://static.platzi.com/media/user_upload/code-840e68dd-e05d-41da-8644-bf94497dad90.jpg)
tremenda calce, gracias por explicar el posible fallo con las rutas dinámicas y no dinámicas
@Get('products')
  getProducts(
    @Query('limit') limit = 100,
    @Query('offset') offset = 0,
    @Query('brand') brand: string,
  ) {
    return `products: limit => ${limit} - offset => ${offset} - brand => ${brand}`;
  }

  //! las rutas dinámicas deben de ir al final
  @Get('products/:id')
  getProduct(@Param('id') id: string) {
    return `product ${id}`;
  }

Tambien para formatear el codigo se puede usar el script que maneja nest, esta especificado en el package.json se puede ejecutar escribiendo npm run format en la consola.

Hay que definir primero las rutas no dinámicas y luego las dinámicas para evitar choques

Vengo de ser Frontend y esto es totalmente nuevo para mí, pero me parece muy interesante.

Yo tengo la ¿Costumbre? De definir todo como si fueran arrow functions, con las arrow function al generarse en la primera vez que pasa el interprete de JS, si invocas una arrow arriba de donde se describe la arrow function, eso te va a tirar un error; de manera similar en express o node o cualquier cosa que te haga un server es más facil si tienes todas tus rutas de manera tal que las estaticas van arriba y separadas según el modelo, luego las de query parameters y luego las de params, de esa forma te ahorras un montón de dolores de cabeza y haces más fácil de leer tu código

Definición de Filtros

Para este punto, tomando la sesión como referencia actualizamos nuestros recursos para el soporte de parámetros y de queries.
.

✨ Concepto clave
Consideremos a un parámetros como un pivote de operación sobre un recurso en específico.
Consideremos a un query como un procedural de filtros o selección que se aplicarán sobre algún criterio de selección.

.
De aquí, actualizaremos nuestro servidor con las siguientes especificaciones:
.

.
También, anexaremos una capa ligera para cuando no encontramos una cuenta registrada.
.

.

Nota. No se recomienda utilizar id para hacer búsquedas sobre datos sensibles en usuarios, por lo que se sugiere hacerlo mediante valores únicos como email o username.

.


.

ⴵ Repositorio GitHub: Vizualla

Commit: ♻️ Updated account resource

.


.

Query Request

Anexaremos soporte para id sobre nuestro endpoint para oftener un cuenta. Además, anexaremos una capa ligera para el control de errores:

// controllers/account.controller
import {
    Controller,
    Get,
    Param,
    ParseIntPipe,
    NotFoundException,
} from '@nestjs/common'

import { AccountService } from '@services/account.service'
import { Account } from '@entities/account.entity'

@Controller('account')
export class AccountController {
    constructor(private readonly accountService: AccountService) {}

    /**
     * @description Find an account registered by query if exists.
     * @throws NotFoundException - Account not found.
     * @return Account */
    @Get(':id')
    getAccount(@Param('id', ParseIntPipe) id: number): Account {
        const account = this.accountService.findAccount(id)
        if (!account) throw new NotFoundException('Account not found')
        return account
    }
}

Después. agregaremos nuestros filtros de paginación para obtener todas cuentas mediante offset y limit.

// controllers/accounts.controller
import { Controller, Get, Query } from '@nestjs/common'
import { AccountService } from '@services/account.service'
import { Account } from '@entities/account.entity'

@Controller('accounts')
export class AccountsController {
    constructor(private readonly accountService: AccountService) {}

    /**
     * @description Find all accounts registered.
     * @param {number} offset - Number of accounts to skip.
     * @param {number} limit - Number of accounts to take.
     * @return Account[] */
    @Get()
    getAccounts(
        @Query('offset') offset = 0,
        @Query('limit') limit = 10
    ): Account[] {
        return this.accountService.findAccounts()
    }
}

con el decorador @query podemos pasar por parámetros un objeto filter y hacer q actué similar a un where en una consulta.

gran clase

  @Get(':categoryId/products/:productId')
  getProductByCategory(
    @Param() { categoryId, productId },
    @Query('color') color: string,
  ): string {
    try {
      return `This product ${productId} owns to the category ${categoryId} with is ${color}`;
    } catch (error) {
      console.log(error);
      throw new HttpException('Not Found', HttpStatus.NOT_FOUND);
    }
  }

Por si no se entendio @param se utiliza cuando solo vas a recibir 1 parametro como por ejemplo un ID
y @query se usa cuando vas a recibir mas de 1 parametro. y no es que no puedas usar param para cuando tengas muchos parametros. sino que es mas amigable la sintaxis

En síntesis, se podría decir a modo comparativo que la diferencia entre el decorator @Param y @Query, es la clásica diferencia entre “rutas amigablesFriendly y rutas “no amigablesNo Friendly. Muy buena explicación. Saludos Profe! 😃

Genial!

aqui el link directo a la documentaciòn del decorador @param
https://docs.nestjs.com/custom-decorators#param-decorators

En VS para formatear el código se puede con Shift + Alt + F

Creo que así es un poco más prolijo

interface ProductsFindAllQueryParams {
  limit: number;
  offset: number;
}

@Get('/products')
  findAll(
    @Query() { limit = 100, offset = 0 }: ProductsFindAllQueryParams,
  ): string {
    return `Products Limit=>${limit} OffSet=>${offset}`;
  }

Creo que me estoy enamorando de NestJS y la facilidad de implementar cosas 🥰

Datazo lo del choque de rutas

Excelente maestro, ojala mas curso de este gran instructor 🥴

Excelente, gracias por el consejo del orden de declaracion de rutas estaticas y dinamicas similares.

Me gusta mucho este curso. No sabía lo de colocar las rutas estáticas antes para evitar esos choques. Genial todo ❤️

Buen tip el de la ruta…