Question: I want to create API for accessing product details by name, details are in array in `products.service` file but when I hit API I only get `[]`, get data by id but not by using the name.
**products.controller**

```
  @Get()
  getProducts() {
    return this.productsService.getProducts();
  }

  @Get(':id') 
  getProduct(@Param() params) {
    console.log('get a single product', params.id);
    return this.productsService.getProducts().filter(p => p.id == params.id);
  }

  @Get(':name') 
  getProductByName(@Param() params) {
    console.log('get a single product', params.name);
    return this.productsService.getProducts().filter(p => p.name == params.name);
  }

}

```

**products.service**

```
@Injectable()
export class ProductsService {

    products = [{
        id: 1,
        name: 'chocolate'
      },
      {
        id: 2,
        name: 'cadbery'
      }];

      getProducts() {
        return this.products;
      }
}

```

Answer: 
Explanation
===========

In the controller your 2 routes `getProduct` and `getProductByName` detect the same pattern that is `api-path/:param` where `param` could represent an `id` or a `name`, but Nestjs doesn't know how to make the difference.

This means that when you request your api with `api-path/2` or `api-path/cadbery`, Nest calls the first function that matches the pattern, which in your case is `getProduct`.

This is why you can only find by id and not by name, because `getProduct` is always executed and `getProductByName` is never called.

Solution
========

Use only 1 route with query params:

```
@Get() // No path param.
getProducts(@Query() query) {
  if (query.id != null) { // Filter by id.
    return this.productsService.getProducts().filter(p => p.id == query.id);
  } else if (query.name != null) { // Filter by name.
    return this.productsService.getProducts().filter(p => p.name == query.name;
  }

  return this.productsService.getProducts(); // Or return all products.
}

```

Now you can:

* get all products by calling `GET api-path`
* filter by id with `GET api-path?id=2`
* filter by name with `GET api-path?name=cadbery`

If the route `getProduct` is already used somewhere in your front and you don't want to introduce breaking changes, you can keep the route and adapt `getProducts` to only filter by name:

```
@Get()
getProducts(@Query() query) {
  if (query.name != null) { // Filter by name.
    return this.productsService.getProducts().filter(p => p.name == query.name;
  }

  return this.productsService.getProducts(); // Or return all products.
}

@Get(':id') // Keep the pattern api-path/:id.
getProduct(@Param() params) {
  return this.productsService.getProducts().filter(p => p.id == params.id);
}

```
This is one of those weird quirks of how the underlying adapters parse Query and URL parameters. Even though you may send in something like `GET /products/2` and you're expecting `{ id: 2, name: 'cadbery' }` back, what's really happening is that the `req.params.id` is being returned as `'2'` instead of `2`. In other words, even though it is a number, it is parsed as a string, and `'2' === 2` returns false, so you never find the proper product, even though it's there.

Using `return this.productsService.getProducts().filter(p => p.id == Number.parseInt(params.id));` would fix that up.