How to handle relationships in a REST api
Asked Answered
P

1

6

I am trying to get my head around how to handle relationships in REST.

I have read this question.

If I have Drivers and Cars in my api and a Driver can only exist if connected to a Car I would make Drivers a subresource in Cars. The relationship between a Car and a Driver contains a set of properties, say averageSpeed and timeOnTheRoad. One Car can have many Drivers, but a Driver can only have one Car.

How should I add a new driver? How should I add a relationship between a driver and a car?

If I add a resource Wunderbaums which is not a subresource to Cars, but a Car can contain Wunderbaums. How should I add a relationship between a Car and a Wunderbaum?

One way of adding a relationship between two entities is to POST to /entityA/{id}/entityB/{id} and send properties for the relationship in the body. This would work for my example with Cars and Wunderbaums since Wunderbaums is not a subresource of Cars, but it would not work in my example with Cars and Drivers since it would interfere with CRUD functionality for Drivers. The path cars/{id}/drivers{id} would be the same for creating a relationship between a Car and a Driver as for creating a Driver.

I also found this unanswered question on the subject.

Edit 1
@JB Nizet suggested that I put the relationship properties inside of the Driver, since its a one to many relationship. It would be a possible solution, but what if a Driver could have many Cars? Should we handle one to many relations different than many to many relations?

Edit 2
We could put relationship properties with the Driver in a many to many relationship scenario as well. The question then is if Driver has its own resource, is it ok that cars/2/drivers/4 returns a different set of properties than drivers/4? In the case where I get the Driver by its relation to Car I will include avrageSpeed and timeOnTheRoad in the response.

Porringer answered 26/10, 2015 at 12:57 Comment(11)
it would interfere with CRUD functionality for Drivers - could you clarify please?Nescience
I updated my answer. The problem is that the same path would be used for creating a relationship as for creating a Driver, which would not be possible.Porringer
Great! Why then, don't you add a separate endpoint for managing cars (/cars/), drivers (/drivers/) and one to establish relation between each other /cars/{carID}/drivers/ or /drivers/{driverID}/cars/?Nescience
Because a Driver can only exist if connected to a Car, so I made it a subresource of Cars. This could be wrong... but the only way you should be able to get a Driver from my api is by a Car.Porringer
And what is the problem then? You said: The path cars/{id}/drivers{id} would be the same for creating a relationship between a Car and a Driver as for creating a Driver: how is that a problem? A driver cannot exist without its car, so every time you create a driver, you MUST create the relationship between the driver and its car.Dipody
Where do I put the properties averageSpeed and timeOnTheRoad in the relationship between a Car and a Driver?Porringer
A Driver belongs to one and only one car, by your description, so just put it in the driver.Dipody
That would be a solution, but what if tomorrow a Driver is suppose to be able to have more than one car? Should we handle many to many relations different than one to many?Porringer
From the REST point of view it doesn't matter. From DB point of view, use join table. To refer cars particular driver use: /cars/{ID}/drivers/{ID}/, all drivers /cars/{ID}/drivers/. If you change driver to able to handle many cars, it remains the same, just introduce /drivers/{ID}/cars/ along with /drivers/{ID}/cars/{ID}. With one to many relation keep the data with drivers entity. With many to many relation you may keep them in join table.Nescience
I am using a graph database, so the relationship actually contains the properties. One problem I see with the solution of putting properties from the relationship in Driver is that if I havet a resource where I get a car without the relationship I would get another answer. cars/2/drivers/4 would give a different response than drivers/4, is that best practise in a REST api?Porringer
Rather not. One would expect that the ID will be the same. However it impossible to be done in another way. Unless you can force the ID or relation and this ID not necessarily needs to be unique in such kind of DB. Don't know that but suppose that there's a workaround.Nescience
E
0

From a DDD perspective, I think perhaps you're asking the wrong question; the question is not 'how do Cars and Drivers relate in the database and thus how should they manifest in the API', but "what capabilities does my API expose and what behaviors does it support"?

In other words, what does the/each REST API call mean in the context of the business (or the user's mind)? If the request is "what cars have I driven?" then driver ->> car is the relationship for that API call. If the request is "assign Tim to drive the Minivan" then the relationship for that API call is Driving -> Driver,Car

Building a CRUD system out of REST can work fine, but it sounds like what you want is a step beyond that.

Exceptionable answered 18/3, 2017 at 20:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.