NationalBankBelgium / REST-API-Design-Guide

NBB's REST-ish API Design Guide
Other
806 stars 152 forks source link

Identify a ressource by a composite key #12

Open kenji-getpowered opened 6 years ago

kenji-getpowered commented 6 years ago

Hi,

in our job we hav a resource that has a verion and for a business case the only identifier possible is a composite key so we came to these solutions.

1/ /myresource/code/version/ 2/ /myresource?code=anycode&version=1 3/ /myresource/metacode with metacode=code+version

Several solutions appear on the internet, but we went for

2/ /myresource?code=anycode&version=1

that will return an array of 1 myresource

1/ /myresource/code/version => KO because /code/ is not an unique ID so it's not REST because url id should lead to a resource.

3/ /myresource/metacode => KO it's not clean as metacode is not really a property of the REST resource.

Did you have the case? How would you handle it?

RobbyDeLaet commented 6 years ago

Hi,

When there is no unique key available, the resource can be retrieved by using the combination of query parameters that make up the composite key. This method is also the easiest, because your REST Api should already implement this method. This keeps your code maintainable.

If you use HATEOAS, don't forget to add the combination of query parameters to identify a single resource.

The first method is indeed not REST. The third method will lead you in a direction that makes your code hard to maintain and you will also loose performance.

So to answer your question, I use your second method, the combination of query parameters.

kenji-getpowered commented 6 years ago

It's difficult because

2/ /myresource?code=anycode&version=1 ==> means that query param are mandatory abd that is ugly and harder to cache.

3/ /myresource/metacode ===> we could consider metacode as a property of the object not going at datasrouce level.

I am not sure there is a clean answer on this one.

lochenv commented 3 years ago

Quite old,

Basically I would go for the metacode. I would remind that we are discussing in terms of API and not datasource or data. The model you return to your client is not necessarily a reprensentation of your data object, it can be something different, I mean, for security reasons for example, your won't show all fields to the client (as internal fields only) or, depending on the role of the connected user, your won't show some fields.

Moreover, your code+version is indeed a unique key and can be added as well as a property in your data model, that's a choice we've made also at data level, differentiate what a business key was from a technical unique key. Even if it does not match all normal form od Relational Database it much simpler to handle (even for foreign key) and faster (index on 1 field only). There are also plenty of ways to make your "metacode" appear in your json file without modifiying you code

davidliang2008 commented 2 years ago

I would go for 3/ as well unless there is a better way. The only thing I am not happy with the query parameter approach 2/ is that calling /resources endpoint with query parameters usually should return a list, instead of a single resource identified by the composite key.

It will be confusing if the business said you should expect an unique resource can be located by the composite key, but the API returns an array with just 1 item.