Best practices API Get

50 views Asked by At

I'm starting one new NestJS project from scratch. This project will have many CRUDs and I'm trying to figure out which is the best practice to apply the GET method.

As far as I know, GET method should only retrieve data from the DB (formatting the response if needed and applying the filters if are specified in as query params). This implies that the endpoint (lets say "/primarcs") has to be able to return a array of data and a single one document with the same HTTP method.

Let's say I have the next schema in the DB:

{
   "_id": ObjectId,
   "name": String
}

Obviously, I will need one endpoint called "/primarcs" that returns all documents of the BD. This endpoint also has to be able to filter data of the DB by using query params: Ex:

"/resources" -> Returns all documents of the DB (paginated if needed)
"/resources?name=Fulgrim" -> Returns all documents that matches the name "Fulgrim" (paginated if needed)

My doubt emerges in those cases when I want to get one single document. Should I create one new endpoint?

/primarcs/{id} -> Where the {id} is the ID of the document I want to get

Or should I use the existing enpoint and applying a query param?

/primars?_id={id} -> Where the {id} is the ID of the document I want to get
1

There are 1 answers

0
Javien On

The answer is quite simple when you think about applying multiple search criteria.

If you use router parameters, you're going to copy the same handler from /primarcs, and make a change to the part of the find statement. It looks like it's not a big deal, but imagine the code is 1,000 lines. It's basically against the DRY rule (Don't Repeat Yourself).

And, when you need more than one search criteria, you'll find that doing /foo/{id}/{name} is not a good idea.

So, I recommend using query parameters for applying search criteria.

type UserSearchQuery = Partial<Record<'id' | 'name', string>>

class App {
  @Get()
  public async users(@Query() query: UserSearchQuery){
    const users = await Users.find({
        id: { $eq: query.id ?? null },
        name: { $eq: query.name ?? null },
    })

    return users
  }
}

This is more easy to extend and manage your code.